I'm creating a website with multiple tabs, and one of them is listing elements, it's the Product tab.
I've got a problem with "ng-repeat", I want to fill a HTML depending on a table of table in angular on the tab, it works fine on the first load, but if I go to another tab and then go again on the product tab, the "ng-repeat" repeats once more and it stacks with the first one.
Example:
Firstload: an apple and a strawberry are loaded fine.
Secondload: I now have apple strawberry and apple strawberry
And so on.
<slick dots="true" prev-arrow="null" next-arrow="null" init-onload="true" data="productsTab">
<div class="productsPage scrollBar" ng-repeat="tab in productsTab">
<div class="productsProduct" ng-repeat="product in tab">
<div class="productsProductTitle">{{product.name}}</div>
</div>
</div>
</slick>
I can also say that I load my data from a factory that I get in controller this way:
productsFactory.build().then(function(facto) {
$scope.productsTab = facto;
});
Hope you can help me!
I think your problem is that init-onload. I am not sure what it does, but if it triggers the call to the controller in some way, it also triggers the promise every time you go back to the tab. You can cache the results from the promise inside the service. Here's an article from this site on how to cache promises:
Caching a promise object in AngularJS service
Hope this will help.
Here is example how to handle multiple ng-repeats, I hope this will help you.
http://plnkr.co/edit/TfGMm1SgpRmgFSTuTuE0?p=preview
<script>
var app=angular.module('myapp',[])
app.controller('demo',function($scope){
$scope.products={
product:[{
name:'abc'
}]
}
})
</script>
</head>
<body ng-app="myapp" ng-controller="demo">
<div ng-repeat="product in products">
<div ng-repeat="p in product">
<span>{{p.name}}</span>
</div>
</div>
</body>
I noticed from the docs I found here https://github.com/vasyabigi/angular-slick that there are no parenthesis on on-init=true. Not sure if that matters.
When I have issues with arrays not resetting I use angular.copy() an empty list variable before loading to the scope. That way I know the array is empty before I add anything to it.
Related
I want to check how many <div class="topology-list"> I have using Angular. At the moment, there are three
I have tried:
angular.element(document.querySelectorAll('.topology-list')).length
This logs 1 (should be 3)
document.querySelectorAll('.topology-list')
Logs 1 too
document.getElementsByClassName('topology-list');
The last one logs an object with the 3 items, but if I add .length it logs 1
Create a directive "your-directive" and put it to the outermost of the HTML
Try the above selections in your directive and all of them should give the correct result.
<body ng-app="yourAppName">
<div your-directive>
<!-- Here your all controllers are loaded-->
</div>
</body>
I have the following simple directory listing. I wish to upload a file and have the ng-repeat list update.
<h3>Directory Listing</h3>
<li ng-repeat="file in filearray track by file.id">
{{file.id}} {{file.filename}}
</li>
I have tried pushing a new item into the filearray array in my controller
$scope.filearray.push({id:max_id, filename: filename});
I have also tried to call the endpoint that provides the directory listing
I have tried with and without $scope.$apply, somehow the ng-repeat does not update (also tried with and without track by). Can someone shed some light on ng-repeat and why it does not dynamically update even on an $scope.$apply ?
EDIT : PROBLEM SOLVED
I had two calls in the main code to the controller ...
<div class="main" ng-controller="MainController">
<form ng-controller="MainController">
...
I am working on my first IONIC-App with AngularJS and I am lead into a dead end.
What I trying to do? There is a overview page with list-elements from a database. The elements comes with ng-repeat, and the $scope-array get filled by an Get-Request via an factory and an OverviewCtrl.
Now the user should have the option to filter stuff. Therefore I like to bring up a modal-windows where the user can select from a selection list. When he select an option the modal should close and the overview-page where he comes from should update.
I try to describe the problem clear as possible:
HTML:
There is this filter.html page (for test reasons, I called it in that way). It gets the "OverviewCtrl" via the app.js. On the page is something like this, to render the overview-elements:
<a class="item item-thumbnail-left" ng-repeat="x in overviews" >
<img src="{{x.pic}}">
<p>{{x.text}}</p>
</a>
So far so good. Also on this filter.html we have this code here, to open the modal:
<div class="buttons">
<button class="button icon-right ion-ios7-arrow-down button-clear button-dark" ng-click="openModal()">
{{modalData.msg}}
</button>
</div>
works fine too.
Factory
I got a factory where all the different HTTP-Get-Requests are realised. So there is also one for the filter. This works all fine, I can see it on the console.
I am returning the callback and in the controller I save it to the $scope.Overview.
Looks like this:
return {listFilter:function(callback){
$http.get("url...").success(callback).error(callback);
}};
Controllers:
AppCtrl:
In the AppCtrl controller are the information for the modal-window like in this example:
Example on Codepen
So the Modal-Window gets its template also in this controller which looks like this:
<div class="modal" ng-controller="ModalCtrl">
<ion-header-bar class="bar bar-header bar-positive">
<h1 class="title">Choose wisely</h1>
<button class="button button-clear button-primary" ng-click="hideModal()">Cancel</button>
</ion-header-bar>
<ion-content>
<div class="list">
<ion-radio ng-model="modalData.msg" ng-repeat="x in filter" ng-click="setFilter(x)">
{{x}}
</ion-radio>
</div>
</ion-content>
OverviewCtrl
Here happens most of the magic. The OverviewCtrl calls by starting the app the factory getData and fills the overviews scope with data. The factory is described later in this post.
ModalCtrl
One fact is, that I first try to use all in one controller which means I had just the OverviewCtrl. But then ng-repeat won't update because there were two kinds of the $scope.overview. One for the ModalCtrl and one for the OverviewCtrl because there where both in the filter.html.
So I try to fix that problem and now I am at the dead end. When I try to call the factory for the Get-Request in the ModalCtrl and write the returned data in the Overview-Scope, the view won't update with ng-repeat. And I am quite sure, that is because I need to call the factory via the OverviewCtrl, right? But thats not possible, because the event comes over the ModalCtrl. Or am I having a big mistake here?
Hope I did not forget something, sorry I am really new to AngularJS and maybe I am not so good in a Description for my problem. Also I am not sure that I finally found the problem, it is just a presumption. Does anyone had another idea? I spend hours for a solution and I am not sure there is one out there. I think it is very complicate with this modal-select, maybe I should try a normal select.
I am new to Angular.js and want to use one ng-controller within another ng-app and ng-controller like this so that I will be able to use the code before I used on the other pages as well.
Please help me out and correct me if I am wrong anywhere.
<div id="divFriendList" class="container" ng-app="friendModule" ng-controller="friendController">
<div id="module2" ng-app="cardsModule" ng-controller="CardsController">
<div ng-repeat="card in cards></div>
</div>
</div>
I am rather new as well, but I believe a way to do this would be to declare a dependency in your module. For example, angular.module('friendModule', ['cardsModule']);. Such an example can be found here. For more about modules and a tutorial on angular you can visit W3Schools.
As for your code, you're missing the closing quotation in <div ng-repeat="card in cards>. Further, you are asking ng-repeat to iterate each card in cards, but you have not defined what cards is. Therefore, you'll want to change
<div id="module2" ng-app="cardsModule" ng-controller="CardsController">
to
<div id="module2" ng-app="cardsModule" ng-controller="CardsController as cards">.
Additionally, you will not get any information displayed if you don't ask for an output such as {{card}}. I would also consider declaring your ng-apps before hand and not when they're needed - but I'm unsure as to the efficiency of this.
What I would update as:
<div id="divFriendList" class="container" ng-app="friendModule" ng-controller="friendController">
<div id="module2" ng-app="cardsModule" ng-controller="CardsController as cards">
<div ng-repeat="card in cards">{{ card }}</div>
</div>
</div>
Hope that helps.
Would like to know the best way to preserve state between tabs. I use bootstrap tabs and angular ui-router. I've a google map in one of the tabs and don't want to reload the map when user selects that tab. Please advise.
Thanks
I think what you are looking for is discussed in this issue: https://github.com/angular-ui/ui-router/issues/63
They are mostly discussing iframes but I believe the same should hold for Google Maps. Unfortunately in the thread they decided that this isn't something that should be implemented in the core release. I haven't tried out the directive they provide (if I get a chance I'll let you know how it goes) but you may be able to get something working with that.
I have actually come across the exact problem you had. My solution was to use styled buttons as my tabs and ng-show for the map tab:
<div id="info-btns">
<button class="btn" ng-model="view" btn-radio="'info'">
Info
</button>
<button class="btn" ng-model="view" btn-radio="'map'" ng-click="loadMap()">
Map
</button>
</div>
<div class="content" ng-show="view != map">
<div ui-view="info"></div>
</div>
<div id="map-container" ng-show="view == 'map'">
<div id="map" class="content" sitemap>
</div>
</div>
ng-show simply uses display:none to hide the map and hence doesn't cause a refresh. You will need to trigger the map to load the first time it is not hidden otherwise it will render incorrectly, hence loadMap()
If I get a chance I'll set up a jsfiddle of this in practice.