I'm trying a simple AngularJS looping using 'ng-repeat' directive as below :
<div ng-app="" ng-init="numbers=[1,3,5,2]">
<ul>
<li ng-repeat="item in numbers">{{ item }}</li>
</ul>
</div>
The result of this is as below, which is perfect
1
3
5
2
However, when I change the 'numbers' array like this
<div ng-app="" ng-init="numbers=[1,3,5,2,2]">
being the rest as is, it does not work.
The only change I have made is that I've added one more item in the 'numbers' array '2'. The issue I figured out is whenever an item is repeated in the array ( '2' in this case ), the problem occurs.
The console log I noticed is like below
Error: [ngRepeat:dupes] http://errors.angularjs.org/1.3.14/ngRepeat/dupes?p0=item%20in%20numbers&p1=number%3A2&p2=2
at Error (native)
at http://ajax.googleapis.com/ajax/libs/angularjs/1.3.14/angular.min.js:6:417
at http://ajax.googleapis.com/ajax/libs/angularjs/1.3.14/angular.min.js:232:494
at Object.fn (http://ajax.googleapis.com/ajax/libs/angularjs/1.3.14/angular.min.js:122:53)
at l.$get.l.$digest (http://ajax.googleapis.com/ajax/libs/angularjs/1.3.14/angular.min.js:123:138)
at l.$get.l.$apply (http://ajax.googleapis.com/ajax/libs/angularjs/1.3.14/angular.min.js:126:58)
at http://ajax.googleapis.com/ajax/libs/angularjs/1.3.14/angular.min.js:17:479
at Object.e [as invoke] (http://ajax.googleapis.com/ajax/libs/angularjs/1.3.14/angular.min.js:36:315)
at d (http://ajax.googleapis.com/ajax/libs/angularjs/1.3.14/angular.min.js:17:400)
at tc (http://ajax.googleapis.com/ajax/libs/angularjs/1.3.14/angular.min.js:18:179)
Also, if the array is of string type values, the same problem persists too.
For example, <div ng-app="" ng-init="names=['Bishnu', 'Sagar', 'John', 'Bishnu']">
in this case also I'm facing the same issue.
This behavior of AngularJS is very strange.
Does anyone know the reason, and how to resolve?
Try this...
The ngRepeat directive instantiates a template once per item from a collection. Each template instance gets its own scope, where the given loop variable is set to the current collection item, and $index is set to the item index or key.
ngRepeat makes the corresponding changes to the DOM
When an item is added, a new instance of the template is added to the DOM.
When an item is removed, its template instance is removed from the DOM.
When items are reordered, their respective templates are reordered in the DOM.
By default, ngRepeat does not allow duplicate items in arrays. This is because when there are duplicates, it is not possible to maintain a one-to-one mapping between collection items and DOM elements.
If you do need to repeat duplicate items, you can substitute the default tracking behavior with your own using the track by expression
<div ng-repeat="n in [42, 42, 43, 43] track by $index">
{{n}}
</div>
Refer:https://docs.angularjs.org/api/ng/directive/ngRepeat
As per the Angular Docs Duplicates are not allowed. You need to use 'track by' expression to specify unique keys.
Created this Plnkr for your reference
<div ng-app="" ng-init="numbers=[1,3,5,2,2]">
<ul>
<li ng-repeat="item in numbers track by $index">{{ item }}</li>
</ul>
</div>
You need to use track by $index to iterate through duplicate entry as well.
you can try like this
<div ng-repeat="value in [4, 4] track by $index">{{value}}</div>
Related
I can not believe that i am unable to do the simple following object made up of two arrays
{"M":
[
"Alpha",
"Beta",
"Zeta"],
"F":
[
"Alpha",
"Omega"
]}
All i want to do is have a nested ng-repeat like the following
<a
class="list-group-item list-group-item-info"
ng-repeat="(key,list) in vm.result">
{{key}}
<a
class="list-group-item"
ng-repeat="name in list">
{{name}}
</a>
</a>
any one has any idea why it does not work.
It shows the key properly, but fails to iterate in the list and hence the name is not shown and no errors are shown in the console either
thanks
bottom line of your problem:
https://www.w3.org/TR/html401/struct/links.html#h-12.2.2
nested links are illegal
Links and anchors defined by the A element must not be nested; an A element must not contain any other A elements.
Since the DTD defines the LINK element to be empty, LINK elements may not be nested either.
Change your outer element to a <div> or <span> and it works
i am new in angular and i go through this doc https://docs.angularjs.org/api/ng/directive/ngRepeat but do not understand the objective of track by clause using with ng-option.
here are few usage
<div ng-repeat="n in [42, 42, 43, 43] track by $index">
{{n}}
</div>
<div ng-repeat="n in [42, 42, 43, 43] track by myTrackingFunction(n)">
{{n}}
</div>
<div ng-repeat="model in collection track by model.id">
{{model.name}}
</div>
<div ng-repeat="obj in collection track by $id(obj)">
{{obj.prop}}
</div>
<div ng-repeat="model in collection | orderBy: 'id' as filtered_result track by model.id">
{{model.name}}
</div>
track by is something close to order by clause in sql ?
if yes then how can i specify sort order like ASC or DESC ?
in last code track by and orderBy both use....what they are doing. not clear what kind of output will come.
what is difference between orderBy & track by ?
orderBy is filter that i know. so track by is also a filter.
i know i am asking very basic question. basically posting here because things is not clear after reading it from doc. looking for some help and example to understand what track by does ?
how track by is different from orderby in terms of usage ?
By default orderBy will be in ascending order. You can use "reverse" for descending order like
In HTML Template Binding
{{ orderBy_expression | orderBy : expression : reverse}}
In JavaScript
$filter('orderBy')(array, expression, reverse)
If you do need to repeat duplicate items, you can substitute the default tracking behavior with your own using the track by expression.
For example, you may track items by the index of each item in the collection, using the special scope property $index:
`<div ng-repeat="n in [42, 42, 43, 43] track by $index">
{{n}}
</div>`
ngRepeat uses a function to "keep track" of all items in the collection and their corresponding DOM elements
If a new item is added to the collection, ngRepeat will know that all other items already have DOM elements, and will not re-render them.
See the detail
If you have object for ngRepeat and it have any identity field (Like primary key value or Unique value), use it in track by.
Good thing is that if you are re-loading the list, dome will not re-render for existing items but only the new ones.
So I have a list of workspaces:
<li class="workspace-object" ng-repeat="w in workspaces | filter:searchQuery" ng-click="selectWorkspace(w)">
{{w.name | titleCase }}
</li>
That List gets updated in the database by some function, and then I call the loadWorkspaces function below, to re-populate the $scope.workspaces object
$scope.loadWorkspaces = function() {
APIService.getWorkspaces().then(function(data){
$scope.workspaces = data;
});
}
When this happens, the $scope.workspaces, when logged out, reads the right updated information immediately, however, the ng-repeat DUPLICATES, before it updates to the proper list. I have no idea why this happens. Any ideas?
In this example, I am updating the workspace title, and that update runs the loadworkspaces function.
Try this ...
w in workspaces track by $index
When the contents of the collection change, ngRepeat makes the corresponding > changes to the DOM:
When an item is added, a new instance of the template is added to the DOM.
When an item is removed, its template instance is removed from the DOM.
When items are reordered, their respective templates are reordered in the DOM.
By default, ngRepeat does not allow duplicate items in arrays. This is because when there are duplicates, it is not possible to maintain a one-to-one mapping between collection items and DOM elements.
If you do need to repeat duplicate items, you can substitute the default tracking behavior with your own using the track by expression.
For example, you may track items by the index of each item in the collection, using the special scope property $index
Accepted answer did not help me (Using Angular 1.1.10), my repeat was still updating delayed. I struggled for ages before I got it working.
Instead of repeating my custom directive like so;
<my-directive ng-repeat="item in myarray track by item.id" some-binding="item"></my-directive>
I (magically) got it working after moving the ng-repeat to a (non-directive) parent element, like so:
<div ng-repeat="item in myarray track by item.id">
<my-directive some-binding="item"></my-directive>
</div>
I need to repeat over either a collection or an array, depending on the situation.
How Would I do that, provided the following approach causes "ngRepeat: dupes", code snippet as follows:
<div ng-if="cause.length" ng-repeat="k in cause">
{{k}}
</div>
<div ng-if="!cause.length" ng-repeat="(k,v) in cause">
{{k}}
</div>
add track by $index to end of ng-repeat declaration any you will not get any Dupes error...
<div ng-if="cause.length" ng-repeat="k in cause track by $index">
{{k}}
</div>
<div ng-if="!cause.length" ng-repeat="(k,v) in cause track by $index">
{{k}}
</div>
UPDATE
If no tracking function is specified the ng-repeat associates elements by identity in the collection. It is an error to have more than one tracking function to resolve to the same key. (This would mean that two distinct objects are mapped to the same DOM element, which is not possible.)
and this explanation from angularjs documentation explains why it resolve this error...
I have an array of 3 items and want them to be "ng-repeated"
<li ng-repeat="item in obj.items id="testobj{{testobj.number}}">
</li>
When I look at the page, it appears that the id of the "li" is just "testobj" for all 3 items and not testobj1 testobj2 testobj3 like I was expecting. What is the issue?
Your ng-repeat attribute is missing a final ".
The {{ }} binding is probably coming back with no data and so being treated as if it was an empty string. I see no reference to testobj (the scope variable) anywhere outside of your binding. Is this defined, or should your id read id="testobj{{item.number}}" or something similar?