-
Notifications
You must be signed in to change notification settings - Fork 24.8k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
docs(core): add documentation for errors NG0955 and NG0956 (#55591)
This commit adds detailed description for the errors NG0955 and NG0956. Those errors correspond to the check introduced in the built-in for loop. PR Close #55591
- Loading branch information
1 parent
375e9a7
commit a4a82af
Showing
6 changed files
with
111 additions
and
5 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
@name Track expression resulted in duplicated keys for a given collection. | ||
@category runtime | ||
@shortDescription A track expression specified in the `@for` loop evaluated to duplicated keys for a given collection. Duplicate keys are problematic from the correctness point of view and the tracking expression should be updated. | ||
|
||
@description | ||
A track expression specified in the `@for` loop evaluated to duplicated keys for a given collection, ex.: | ||
|
||
```typescript | ||
@Component({ | ||
template: `@for (item of items; track item.value) {{{item.value}}}`, | ||
}) | ||
class TestComponent { | ||
items = [{key: 1, value: 'a'}, {key: 2, value: 'b'}, {key: 3, value: 'a'}]; | ||
} | ||
``` | ||
|
||
In the provided example the `item.key` tracking expression will find two duplicate keys `a` (at index 0 and 2). | ||
|
||
Duplicate keys are problematic from the correctness point of view: since the `@for` loop can't uniquely identify items it might choose DOM nodes corresponding to _another_ item (with the same key) when performing DOM moves or destroy. | ||
|
||
There is also performance penalty associated with duplicated keys - internally Angular must use more sophisticated and slower data structures while repeating over collections with duplicated keys. | ||
|
||
## Fixing the error | ||
|
||
Change the tracking expression such that it uniquely identifies an item in a collection. In the discussed example the correct track expression would use the unique `key` property (`item.key`): | ||
|
||
```typescript | ||
@Component({ | ||
template: `@for (item of items; track item.key) {{{item.value}}}`, | ||
}) | ||
class TestComponent { | ||
items = [{key: 1, value: 'a'}, {key: 2, value: 'b'}, {key: 3, value: 'a'}]; | ||
} | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
@name Tracking expression caused re-creation of the DOM structure. | ||
@category runtime | ||
@shortDescription The configured tracking expression (track by identity) caused re-creation of the DOM structure for the entire collection, which is problematic from the performance and correctness point of view. | ||
|
||
@description | ||
The identity track expression specified in the `@for` loop caused re-creation of the DOM corresponding to _all_ items. This is very expensive operation that commonly occurs when working with immutable data structures, Example: | ||
|
||
```typescript | ||
@Component({ | ||
template: ` | ||
<button (click)="toggleAllDone()">All done!</button> | ||
<ul> | ||
@for (todo of todos; track todo) { | ||
<li>{{todo.task}}</li> | ||
} | ||
</ul> | ||
`, | ||
}) | ||
export class App { | ||
todos = [ | ||
{ id: 0, task: 'understand trackBy', done: false }, | ||
{ id: 1, task: 'use proper tracking expression', done: false }, | ||
]; | ||
|
||
toggleAllDone() { | ||
this.todos = this.todos.map(todo => ({ ...todo, done: true })); | ||
} | ||
} | ||
``` | ||
|
||
In the provided example the entire list, with all the views (DOM nodes, Angular directives, components, queries etc.) are re-created (!) after toggling the "done" status of items. Here a relatively inexpensive binding update to the `done` property would suffice. | ||
|
||
Apart from having hight performance penalty, re-creating DOM tree result in loose of state in the DOM elements (ex.: focus, text selection, sites loaded in an iframe etc.). | ||
|
||
## Fixing the error | ||
|
||
Change the tracking expression such that it uniquely identifies an item in a collection, regardless of its object identity. In the discussed example the correct track expression would use the unique `id` property (`item.id`): | ||
|
||
```typescript | ||
@Component({ | ||
template: ` | ||
<button (click)="toggleAllDone()">All done!</button> | ||
<ul> | ||
@for (todo of todos; track todo.id) { | ||
<li>{{todo.task}}</li> | ||
} | ||
</ul> | ||
`, | ||
}) | ||
export class App { | ||
todos = [ | ||
{ id: 0, task: 'understand trackBy', done: false }, | ||
{ id: 1, task: 'use proper tracking expression', done: false }, | ||
]; | ||
|
||
toggleAllDone() { | ||
this.todos = this.todos.map(todo => ({ ...todo, done: true })); | ||
} | ||
} | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters