access ng-repeat $index from a inner ng-repeat - angularjs

Knowing that ng-repeat create a scope, how do I access the $index of a parent ng-repeat from a child ng-repeat?
Markup
<div ng-repeat="first in arr">
here there is the first level $index
<div ng-repeat="second in first.arr">
in here I need access to the first level $index
</div>
</div>

Whenever ng-repeat iterate to create a DOM, it also does create a DOM, with new scope which prototypically inherited from the current running scope.
As you wanted to access the ng-repeat $index of outer ng-repeat in inner ng-repeat, you could use $parent.$index to indicate parent ng-repeat
<div ng-repeat="first in arr">
here there is the first level $index
<div ng-repeat="second in first.arr">
in here I need access to the first level {{$parent.$index}}
</div>
</div>
Though the cleaner solution to solve this problem would be, use ng-init on outer ng-repeat and have outer index in scope variable, by which you can get rid of $parent keyword.
<div ng-repeat="first in arr" ng-init="parentIndex=$index">
here there is the first level $index
<div ng-repeat="second in first.arr">
in here I need access to the first level {{parentIndex}}
</div>
</div>

<div ng-repeat="first in [1,2,3]">
here there is the first level {{$index}}
<div ng-repeat="second in ['a', 'b', 'c']">
in here I need access to the first level {{$parent.$index}} / {{$index}}
</div>
Output:
here there is the first level 0
in here I need access to the first level 0 / 0
in here I need access to the first level 0 / 1
in here I need access to the first level 0 / 2
here there is the first level 1
in here I need access to the first level 1 / 0
in here I need access to the first level 1 / 1
in here I need access to the first level 1 / 2
here there is the first level 2
in here I need access to the first level 2 / 0
in here I need access to the first level 2 / 1
in here I need access to the first level 2 / 2

Related

How to define serial number with 2 ng-repeats?

$index is not working as when the inner ng-repeat fires it executes $index and when it is executed fully it nulls the value of $index for the outer ng-repeat.How to give serial number in that case.?
When you use ng-repeat, it creates a child scope. Therefore in case of nested ng-repeats, you can reach the parent via $parent.
hence, you could do something like this:
<div ng-repeat="a in serial1">
<div ng-repeat="b in serial2">
a is {{$parent.$index}}, b is {{$index}}
</div>
</div>

angular scope of ng-model to filter model of a different scope

Reading the docs tutorial, under Template. The code below is taken from app/index.html
Does angular allows cross visibility of sibling scopes?
How is it that the data named query which is is in scope 1 is available to the filter in scope 2 which is a sibling and not a parent scope? Thanks.
<div class="container-fluid">
<div class="row">
<div class="col-md-2"> //-----------scope 1 -----------------
<!--Sidebar content-->
Search: <input ng-model="query">
</div>
<div class="col-md-10"> //-----------scope 2 -----------------
<!--Body content-->
<ul class="phones">
<li ng-repeat="phone in phones | filter:query">
{{phone.name}}
<p>{{phone.snippet}}</p>
</li>
</ul>
</div>
</div>
</div>
There is a $scope tree, starting from $rootScope. In your HTML, there is only 1 scope in play (ignoring ngRepeat, which creates its own child scope with each iteration). So when a user enters a value in the input box, it is being bound to query which resides in the same scope as the sibling div. Hence why both query is bound to the same scope variable, even though they are within sibling divs.
One way to break the binding is to introduce a child scope for your input control. For example, ngController will create a child scope that inherits from the parent scope. As soon as a key is pressed, it creates a copy of query in the child scope. This breaks two-way binding because now two copies of the query variable exist on different scopes.
<div class="col-md-2" ng-controller="anyCtrl"> //-----------scope 1 -----------------
<!--Sidebar content-->
Search: <input ng-model="query">
</div>
You should visualize your $scope tree and get to know which directives will create child scopes. Also keep in mind that $scope variable lookups (reads) are resolved through prototypical $scope inheritance (meaning the definition of the $scope variable could exist higher up the $scope tree). But $scope variable writes will write to its immediate scope - sometimes breaking the apparent binding as I've explained above.

Looping in AngularJS not working

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>

Do something every ng-repeat

I want to get current iteration number using track by. I have some array which is one elemented and has only one element at index=2.
If i dont use track by i get error. How to get current iteration?
<div ng-repeat="tableData in tables track by $index">{{current_iteration}}</div>
Using your existing :
<div ng-repeat="tableData in tables track by $index">
{{ $index }}
</div>
Will result in:
0
1
2
4
5
.....

Using ng-repeat value as filter for nested ng-repeat

I have an outer div that I want to repeat for each cats in art.Categories.
While that repeat loop happens, I want to take the value from the ng-repeat and use it to create a nested ng-repeat. This nested ng-repeat will continue until it runs out of items, then return to the outside ng-repeat, which will continue the process.
My issue is I can't use {{cats.id}} as the filter for the sub-Div.
<div ng-repeat="cats in art.Categories" class="tab-pane" ng-class="{active: $index == 0}" id="{{cats.id}}">
<div ng-repeat="arts in art.Articles | filter: { ids: '{{cats.id}}' }" class="entity_container"></div>
</div>
As the commenter mentioned, a solution is to remove the curly braces. In my example, that means just writing cats.id. As an aside, I need to implement UI's native tabs directives.
Try this:
ng-show="arts.ids==cats.id"

Resources