Skip to content

Commit

Permalink
docs(common): rewrite docs for NgForOf#ngForTrackBy (#42329)
Browse files Browse the repository at this point in the history
Clarify the prupose of the tracking function and document how to create a good one.

Fixes #40461

PR Close #42329
  • Loading branch information
IgorMinar authored and umairhm committed May 28, 2021
1 parent 92cbb95 commit d08e3a2
Show file tree
Hide file tree
Showing 2 changed files with 55 additions and 16 deletions.
25 changes: 13 additions & 12 deletions packages/common/src/directives/ng_for_of.ts
Expand Up @@ -141,21 +141,22 @@ export class NgForOf<T, U extends NgIterable<T> = NgIterable<T>> implements DoCh
this._ngForOfDirty = true;
}
/**
* A function that defines how to track changes for items in the iterable.
* Specifies a custom `TrackByFunction` to compute the identity of items in an iterable.
*
* When items are added, moved, or removed in the iterable,
* the directive must re-render the appropriate DOM nodes.
* To minimize churn in the DOM, only nodes that have changed
* are re-rendered.
* If a custom `TrackByFunction` is not provided, `NgForOf` will use the item's [object
* identity](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is)
* as the key.
*
* By default, the change detector assumes that
* the object instance identifies the node in the iterable.
* When this function is supplied, the directive uses
* the result of calling this function to identify the item node,
* rather than the identity of the object itself.
* `NgForOf` uses the computed key to associate items in an iterable with DOM elements
* it produces for these items.
*
* The function receives two inputs,
* the iteration index and the associated node data.
* A custom `TrackByFunction` is useful to provide good user experience in cases when items in an
* iterable rendered using `NgForOf` have a natural identifier (for example, custom ID or a
* primary key), and this iterable could be updated with new object instances that still
* represent the same underlying entity (for example, when data is re-fetched from the server,
* and the iterable is recreated and re-rendered, but most of the data is still the same).
*
* @see `TrackByFunction`
*/
@Input()
set ngForTrackBy(fn: TrackByFunction<T>) {
Expand Down
46 changes: 42 additions & 4 deletions packages/core/src/change_detection/differs/iterable_differs.ts
Expand Up @@ -113,14 +113,52 @@ export interface IterableChangeRecord<V> {
}

/**
* An optional function passed into the `NgForOf` directive that defines how to track
* changes for items in an iterable.
* The function takes the iteration index and item ID.
* When supplied, Angular tracks changes by the return value of the function.
* A function optionally passed into the `NgForOf` directive to customize how `NgForOf` uniquely
* identifies items in an iterable.
*
* `NgForOf` needs to uniquely identify items in the iterable to correctly perform DOM updates
* when items in the iterable are reordered, new items are added, or existing items are removed.
*
*
* In all of these scenarios it is usually desirable to only update the DOM elements associated
* with the items affected by the change. This behavior is important to:
*
* - preserve any DOM-specific UI state (like cursor position, focus, text selection) when the
* iterable is modified
* - enable animation of item addition, removal, and iterable reordering
*
* A common use for custom `trackBy` functions is when the model that `NgForOf` iterates over
* contains a property with a unique identifier. For example, given a model:
*
* ```ts
* class User {
* id: number;
* name: string;
* ...
* }
* ```
* a custom `trackBy` function could look like the following:
* ```ts
* function userTrackBy(index, user) {
* return user.id;
* }
* ```
*
* A custom `trackBy` function must have several properties:
*
* - be [idempotent](https://en.wikipedia.org/wiki/Idempotence) (be without side effects, and always
* return the same value for a given input)
* - return unique value for all unique inputs
* - be fast
*
* @see [`NgForOf#ngForTrackBy`](api/common/NgForOf#ngForTrackBy)
* @publicApi
*/
export interface TrackByFunction<T> {
/**
* @param index The index of the item within the iterable.
* @param item The item in the iterable.
*/
(index: number, item: T): any;
}

Expand Down

0 comments on commit d08e3a2

Please sign in to comment.