ng-repeat
is a built in directive in Angular which lets you iterate an array or an object and gives you the ability to repeat an element once for each item in the collection.
ng-repeat an array
<ul>
<li ng-repeat="item in itemCollection">
{{item.Name}}
</li>
</ul>
Where:
item = individual item in the collection
itemCollection = The array you are iterating
ng-repeat an object
<ul>
<li ng-repeat="(key, value) in myObject">
{{key}} : {{value}}
</li>
</ul>
Where:
key = the property name
value = the value of the property
myObject = the object you are iterating
filter your ng-repeat by user input
<input type="text" ng-model="searchText">
<ul>
<li ng-repeat="string in stringArray | filter:searchText">
{{string}}
</li>
</ul>
Where:
searchText = the text that the user wants to filter the list by
stringArray = an array of strings, e.g. ['string', 'array']
You can also display or reference the filtered items elsewhere by assigning the filter output an alias with as aliasName
, like so:
<input type="text" ng-model="searchText">
<ul>
<li ng-repeat="string in stringArray | filter:searchText as filteredStrings">
{{string}}
</li>
</ul>
<p>There are {{filteredStrings.length}} matching results</p>
ng-repeat-start and ng-repeat-end
To repeat multiple DOM elements by defining a start and an end point you can use the ng-repeat-start
and ng-repeat-end
directives.
<ul>
<li ng-repeat-start="item in [{a: 1, b: 2}, {a: 3, b:4}]">
{{item.a}}
</li>
<li ng-repeat-end>
{{item.b}}
</li>
</ul>
Output:
It is important to always close ng-repeat-start
with ng-repeat-end
.
Variables
ng-repeat
also exposes these variables inside the expression
Variable | Type | Details |
---|---|---|
$index | Number | Equals to the index of the current iteration ($index===0 will evaluate to true at the first iterated element; see $first ) |
$first | Boolean | Evaluates to true at the first iterated element |
$last | Boolean | Evaluates to true at the last iterated element |
$middle | Boolean | Evaluates to true if the element is between the $first and $last |
$even | Boolean | Evaluates to true at an even numbered iteration (equivalent to $index%2===0 ) |
$odd | Boolean | Evaluates to true at an odd numbered iteration (equivalent to $index%2===1 ) |
Performance considerations
Rendering ngRepeat
can become slow, especially when using large collections.
If the objects in the collection have an identifier property, you should always track by
the identifier instead of the whole object, which is the default functionality. If no identifier is present, you can always use the built-in $index
.
<div ng-repeat="item in itemCollection track by item.id">
<div ng-repeat="item in itemCollection track by $index">
Scope of ngRepeat
ngRepeat
will always create an isolated child scope so care must be taken if the parent scope needs to be accessed inside the repeat.
Here is a simple example showing how you can set a value in your parent scope from a click event inside of ngRepeat
.
scope val: {{val}}<br/>
ctrlAs val: {{ctrl.val}}
<ul>
<li ng-repeat="item in itemCollection">
<a href="#" ng-click="$parent.val=item.value; ctrl.val=item.value;">
{{item.label}} {{item.value}}
</a>
</li>
</ul>
$scope.val = 0;
this.val = 0;
$scope.itemCollection = [{
id: 0,
value: 4.99,
label: 'Football'
},
{
id: 1,
value: 6.99,
label: 'Baseball'
},
{
id: 2,
value: 9.99,
label: 'Basketball'
}];
If there was only val = item.value
at ng-click
it won't update the val
in the parent scope because of the isolated scope. That's why the parent scope is accessed with $parent
reference or with the controllerAs
syntax (e.g. ng-controller="mainController as ctrl"
).
Nested ng-repeat
You can also use nested ng-repeat.
<div ng-repeat="values in test">
<div ng-repeat="i in values">
[{{$parent.$index}},{{$index}}] {{i}}
</div>
</div>
var app = angular.module("myApp", []);
app.controller("ctrl", function($scope) {
$scope.test = [
['a', 'b', 'c'],
['d', 'e', 'f']
];
});
Here to access the index of parent ng-repeat inside child ng-repeat, you can use $parent.$index
.