Improve this Doc View Source ngRepeat

  1. directive in module ng

Overview

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.

Special properties are exposed on the local scope of each template instance, including:

Variable Type Details
$index number iterator offset of the repeated element (0..length-1)
$first boolean true if the repeated element is first in the iterator.
$middle boolean true if the repeated element is between the first and last in the iterator.
$last boolean true if the repeated element is last in the iterator.
$even boolean true if the iterator position $index is even (otherwise false).
$odd boolean true if the iterator position $index is odd (otherwise false).
Creating aliases for these properties is possible with ngInit. This may be useful when, for instance, nesting ngRepeats.

Iterating over object properties

It is possible to get ngRepeat to iterate over the properties of an object using the following syntax:

<div ng-repeat="(key, value) in myObj"> ... </div>

However, there are a few limitations compared to array iteration:

  • The JavaScript specification does not define the order of keys returned for an object, so AngularJS relies on the order returned by the browser when running for key in myObj. Browsers generally follow the strategy of providing keys in the order in which they were defined, although there are exceptions when keys are deleted and reinstated. See the MDN page on delete for more info.

  • ngRepeat will silently ignore object keys starting with $, because it's a prefix used by AngularJS for public ($) and private ($$) properties.

  • The built-in filters orderBy and filter do not work with objects, and will throw an error if used with one.

If you are hitting any of these limitations, the recommended workaround is to convert your object into an array that is sorted into the order that you prefer before providing it to ngRepeat. You could do this with a filter such as toArrayFilter or implement a $watch on the object yourself.

Tracking and Duplicates

ngRepeat uses $watchCollection to detect changes in the collection. When a change happens, ngRepeat then 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.

To minimize creation of DOM elements, ngRepeat uses a function to "keep track" of all items in the collection and their corresponding DOM elements. For example, if an item is added to the collection, ngRepeat will know that all other items already have DOM elements, and will not re-render them.

All different types of tracking functions, their syntax, and their support for duplicate items in collections can be found in the ngRepeat expression description.

Best Practice: If you are working with objects that have a unique identifier property, you should track by this identifier instead of the object instance, e.g. item in items track by item.id. Should you reload your data later, ngRepeat will not have to rebuild the DOM elements for items it has already rendered, even if the JavaScript objects in the collection have been substituted for new ones. For large collections, this significantly improves rendering performance.

Effects of DOM Element re-use

When DOM elements are re-used, ngRepeat updates the scope for the element, which will automatically update any active bindings on the template. However, other functionality will not be updated, because the element is not re-created:

  • Directives are not re-compiled
  • one-time expressions on the repeated template are not updated if they have stabilized.

The above affects all kinds of element re-use due to tracking, but may be especially visible when tracking by $index due to the way ngRepeat re-uses elements.

The following example shows the effects of different actions with tracking:

Special repeat start and end points

To repeat a series of elements instead of just one parent element, ngRepeat (as well as other ng directives) supports extending the range of the repeater by defining explicit start and end points by using ng-repeat-start and ng-repeat-end respectively. The ng-repeat-start directive works the same as ng-repeat, but will repeat all the HTML code (including the tag it's defined on) up to and including the ending HTML tag where ng-repeat-end is placed.

The example below makes use of this feature:

<header ng-repeat-start="item in items">
  Header {{ item }}
</header>
<div class="body">
  Body {{ item }}
</div>
<footer ng-repeat-end>
  Footer {{ item }}
</footer>

And with an input of ['A','B'] for the items variable in the example above, the output will evaluate to:

<header>
  Header A
</header>
<div class="body">
  Body A
</div>
<footer>
  Footer A
</footer>
<header>
  Header B
</header>
<div class="body">
  Body B
</div>
<footer>
  Footer B
</footer>

The custom start and end points for ngRepeat also support all other HTML directive syntax flavors provided in AngularJS (such as data-ng-repeat-start, x-ng-repeat-start and ng:repeat-start).

Directive Info

  • This directive creates new scope.
  • This directive executes at priority level 1000.
  • This directive can be used as multiElement

Usage

  • as attribute:
    <ANY
      ng-repeat="repeat_expression">
    ...
    </ANY>

Arguments

Param Type Details
ngRepeat repeat_expression

The expression indicating how to enumerate a collection. These formats are currently supported:

  • variable in expression – where variable is the user defined loop variable and expression is a scope expression giving the collection to enumerate.

    For example: album in artist.albums.

  • (key, value) in expression – where key and value can be any user defined identifiers, and expression is the scope expression giving the collection to enumerate.

    For example: (name, age) in {'adam':10, 'amalie':12}.

  • variable in expression track by tracking_expression – You can also provide an optional tracking expression which can be used to associate the objects in the collection with the DOM elements. If no tracking expression is specified, ng-repeat associates elements by identity. It is an error to have more than one tracking expression value resolve to the same key. (This would mean that two distinct objects are mapped to the same DOM element, which is not possible.)

    Default tracking: $id(): item in items is equivalent to item in items track by $id(item). This implies that the DOM elements will be associated by item identity in the collection.

    The built-in $id() function can be used to assign a unique $$hashKey property to each item in the collection. This property is then used as a key to associated DOM elements with the corresponding item in the collection by identity. Moving the same object would move the DOM element in the same way in the DOM. Note that the default id function does not support duplicate primitive values (number, string), but supports duplictae non-primitive values (object) that are equal in shape.

    Custom Expression: It is possible to use any AngularJS expression to compute the tracking id, for example with a function, or using a property on the collection items. item in items track by item.id is a typical pattern when the items have a unique identifier, e.g. database id. In this case the object identity does not matter. Two objects are considered equivalent as long as their id property is same. Tracking by unique identifier is the most performant way and should be used whenever possible.

    $index: This special property tracks the collection items by their index, and re-uses the DOM elements that match that index, e.g. item in items track by $index. This can be used for a performance improvement if no unique identfier is available and the identity of the collection items cannot be easily computed. It also allows duplicates.

    Note: Re-using DOM elements can have unforeseen effects. Read the section on tracking and duplicates for more info.
    Note: the track by expression must come last - after any filters, and the alias expression: item in items | filter:searchText as results track by item.id
  • variable in expression as alias_expression – You can also provide an optional alias expression which will then store the intermediate results of the repeater after the filters have been applied. Typically this is used to render a special message when a filter is active on the repeater, but the filtered result set is empty.

    For example: item in items | filter:x as results will store the fragment of the repeated items as results, but only after the items have been processed through the filter.

    Please note that `as [variable name] is not an operator but rather a part of ngRepeat micro-syntax so it can be used only after all filters (and not as operator, inside an expression).

    For example: item in items | filter : x | orderBy : order | limitTo : limit as results track by item.id .

Animations

Animation Occurs
enter when a new item is added to the list or when an item is revealed after a filter
leave when an item is removed from the list or when an item is filtered out
move when an adjacent item is filtered out causing a reorder or when the item contents are reordered

See the example below for defining CSS animations with ngRepeat.

Click here to learn more about the steps involved in the animation.

Example

This example uses ngRepeat to display a list of people. A filter is used to restrict the displayed results by name or by age. New (entering) and removed (leaving) items are animated.

© 2010–2018 Google, Inc.
Licensed under the Creative Commons Attribution License 4.0.
https://code.angularjs.org/1.7.8/docs/api/ng/directive/ngRepeat