This div is initially saveable, unchanged, and special.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ This div should be {{ canSave ? "": "not"}} saveable,
+ {{ isUnchanged ? "unchanged" : "modified" }} and
+ {{ isSpecial ? "": "not"}} special after clicking "Refresh".
+
+
+
+
This div is special
+
+
Helpful study course
+
Study course
+
+
+
+
NgStyle Binding
+
+
+ This div is x-large or smaller.
+
+
+
+
+
[ngStyle] binding to currentStyles - CSS property names
+
currentStyles is {{currentStyles | json}}
+
+
+
+ This div is initially italic, normal weight, and extra large (24px).
+
+
+
+
+
+
+ |
+ |
+
+
+
+
+ This div should be {{ canSave ? "italic": "plain"}},
+ {{ isUnchanged ? "normal weight" : "bold" }} and,
+ {{ isSpecial ? "extra large": "normal size"}} after clicking "Refresh".
+
+
+
Built-in structural directives
+
NgIf Binding
+
+
If isActive is true, app-item-detail will render:
+
+
+
+
+
+
+
If currentCustomer isn't null, say hello to Laura:
+
+
Hello, {{currentCustomer.name}}
+
+
nullCustomer is null by default. NgIf guards against null. Give it a value to show it:
+
+
Hello, {{nullCustomer}}
+
+
+
+
+
NgIf binding with template (no *)
+
+Add {{currentItem.name}} with template
+
+
+
Show/hide vs. NgIf
+
+
+
Show with class
+
Hide with class
+
+
ItemDetail is in the DOM but hidden
+
+
+
Show with style
+
Hide with style
+
+
+
+
+
NgFor Binding
+
+
+
+
{{item.name}}
+
+
+
+
*ngFor with ItemDetailComponent element
+
+
+
+
+
+
+
+
*ngFor with index
+
with semi-colon separator
+
+
+
{{i + 1}} - {{item.name}}
+
+
+
+
with comma separator
+
+
{{i + 1}} - {{item.name}}
+
+
+
*ngFor trackBy
+
+
+
+
+
without trackBy
+
+
({{item.id}}) {{item.name}}
+
+
+ Item DOM elements change #{{itemsNoTrackByCount}} without trackBy
+
+
+
+
with trackBy
+
+
({{item.id}}) {{item.name}}
+
+
+ Item DOM elements change #{{itemsWithTrackByCount}} with trackBy
+
diff --git a/aio/content/examples/built-in-directives/src/app/item-detail/item-detail.component.spec.ts b/aio/content/examples/built-in-directives/src/app/item-detail/item-detail.component.spec.ts
new file mode 100644
index 0000000000..7559cb65f6
--- /dev/null
+++ b/aio/content/examples/built-in-directives/src/app/item-detail/item-detail.component.spec.ts
@@ -0,0 +1,25 @@
+import { async, ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { ItemDetailComponent } from './item-detail.component';
+
+describe('ItemDetailComponent', () => {
+ let component: ItemDetailComponent;
+ let fixture: ComponentFixture;
+
+ beforeEach(async(() => {
+ TestBed.configureTestingModule({
+ declarations: [ ItemDetailComponent ]
+ })
+ .compileComponents();
+ }));
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(ItemDetailComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/aio/content/examples/built-in-directives/src/app/item-detail/item-detail.component.ts b/aio/content/examples/built-in-directives/src/app/item-detail/item-detail.component.ts
new file mode 100644
index 0000000000..a2f4379aa6
--- /dev/null
+++ b/aio/content/examples/built-in-directives/src/app/item-detail/item-detail.component.ts
@@ -0,0 +1,17 @@
+import { Component, Input } from '@angular/core';
+
+import { Item } from '../item';
+
+@Component({
+ selector: 'app-item-detail',
+ templateUrl: './item-detail.component.html',
+ styleUrls: ['./item-detail.component.css']
+})
+export class ItemDetailComponent {
+
+
+ @Input() item: Item;
+
+ constructor() { }
+
+}
diff --git a/aio/content/examples/built-in-directives/src/app/item-switch.component.ts b/aio/content/examples/built-in-directives/src/app/item-switch.component.ts
new file mode 100644
index 0000000000..b40d5c9af5
--- /dev/null
+++ b/aio/content/examples/built-in-directives/src/app/item-switch.component.ts
@@ -0,0 +1,50 @@
+import { Component, Input } from '@angular/core';
+import { Item } from './item';
+
+@Component({
+ selector: 'app-stout-item',
+ template: `I'm a little {{item.name}}, short and stout!`
+})
+export class StoutItemComponent {
+ @Input() item: Item;
+}
+
+@Component({
+ selector: 'app-best-item',
+ template: `This is the brightest {{item.name}} in town.`
+})
+export class BestItemComponent {
+ @Input() item: Item;
+}
+
+@Component({
+ selector: 'app-device-item',
+ template: `Which is the slimmest {{item.name}}?`
+})
+export class DeviceItemComponent {
+ @Input() item: Item;
+}
+
+@Component({
+ selector: 'app-lost-item',
+ template: `Has anyone seen my {{item.name}}?`
+})
+export class LostItemComponent {
+ @Input() item: Item;
+}
+
+@Component({
+ selector: 'app-unknown-item',
+ template: `{{message}}`
+})
+export class UnknownItemComponent {
+ @Input() item: Item;
+ get message() {
+ return this.item && this.item.name ?
+ `${this.item.name} is strange and mysterious.` :
+ 'A mystery wrapped in a fishbowl.';
+ }
+}
+
+export const ItemSwitchComponents =
+ [ StoutItemComponent, BestItemComponent, DeviceItemComponent, LostItemComponent, UnknownItemComponent ];
diff --git a/aio/content/examples/built-in-directives/src/app/item.ts b/aio/content/examples/built-in-directives/src/app/item.ts
new file mode 100644
index 0000000000..c5bffa1a20
--- /dev/null
+++ b/aio/content/examples/built-in-directives/src/app/item.ts
@@ -0,0 +1,30 @@
+export class Item {
+ static nextId = 0;
+
+ static items: Item[] = [
+ new Item(
+ null,
+ 'Teapot',
+ 'stout'
+ ),
+ new Item(1, 'Lamp', 'bright'),
+ new Item(2, 'Phone', 'slim' ),
+ new Item(3, 'Television', 'vintage' ),
+ new Item(4, 'Fishbowl')
+ ];
+
+
+ constructor(
+ public id?: number,
+ public name?: string,
+ public feature?: string,
+ public url?: string,
+ public rate = 100,
+ ) {
+ this.id = id ? id : Item.nextId++;
+ }
+
+ clone(): Item {
+ return Object.assign(new Item(), this);
+ }
+}
diff --git a/aio/content/examples/built-in-directives/src/assets/potted-plant.svg b/aio/content/examples/built-in-directives/src/assets/potted-plant.svg
new file mode 100644
index 0000000000..871a2096c4
--- /dev/null
+++ b/aio/content/examples/built-in-directives/src/assets/potted-plant.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/aio/content/examples/built-in-directives/src/index.html b/aio/content/examples/built-in-directives/src/index.html
new file mode 100644
index 0000000000..c501fb93bf
--- /dev/null
+++ b/aio/content/examples/built-in-directives/src/index.html
@@ -0,0 +1,14 @@
+
+
+
+
+ BuiltInDirectives
+
+
+
+
+
+
+
+
+
diff --git a/aio/content/examples/built-in-directives/src/main.ts b/aio/content/examples/built-in-directives/src/main.ts
new file mode 100644
index 0000000000..91ec6da5f0
--- /dev/null
+++ b/aio/content/examples/built-in-directives/src/main.ts
@@ -0,0 +1,12 @@
+import { enableProdMode } from '@angular/core';
+import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
+
+import { AppModule } from './app/app.module';
+import { environment } from './environments/environment';
+
+if (environment.production) {
+ enableProdMode();
+}
+
+platformBrowserDynamic().bootstrapModule(AppModule)
+ .catch(err => console.log(err));
diff --git a/aio/content/examples/built-in-directives/stackblitz.json b/aio/content/examples/built-in-directives/stackblitz.json
new file mode 100644
index 0000000000..6824495335
--- /dev/null
+++ b/aio/content/examples/built-in-directives/stackblitz.json
@@ -0,0 +1,10 @@
+{
+ "description": "Built-in Directives",
+ "files": [
+ "!**/*.d.ts",
+ "!**/*.js",
+ "!**/*.[1,2].*"
+ ],
+ "file": "src/app/app.component.ts",
+ "tags": ["Built-in Directives"]
+}
diff --git a/aio/content/guide/template-syntax.md b/aio/content/guide/template-syntax.md
index 419fde5d9a..269f9ca954 100644
--- a/aio/content/guide/template-syntax.md
+++ b/aio/content/guide/template-syntax.md
@@ -1238,80 +1238,64 @@ Angular [NgModel](guide/template-syntax#ngModel).
## Built-in directives
-Earlier versions of Angular included over seventy built-in directives.
-The community contributed many more, and countless private directives
-have been created for internal applications.
+Angular offers two kinds of built-in directives: attribute
+directives and structural directives. This segment reviews some of the most common built-in directives,
+classified as either [_attribute_ directives](guide/template-syntax#attribute-directives) or [_structural_ directives](guide/template-syntax#structural-directives) and has its own built-in directives example.
-You don't need many of those directives in Angular.
-You can often achieve the same results with the more capable and expressive Angular binding system.
-Why create a directive to handle a click when you can write a simple binding such as this?
-
-
-
-
-You still benefit from directives that simplify complex tasks.
-Angular still ships with built-in directives; just not as many.
-You'll write your own directives, just not as many.
-
-This segment reviews some of the most frequently used built-in directives,
-classified as either [_attribute_ directives](guide/template-syntax#attribute-directives) or [_structural_ directives](guide/template-syntax#structural-directives).
+For more detail, including how to build your own custom directives, see [Attribute Directives](guide/attribute-directives) and [Structural Directives](guide/structural-directives).
{@a attribute-directives}
-## Built-in _attribute_ directives
+### Built-in attribute directives
Attribute directives listen to and modify the behavior of
other HTML elements, attributes, properties, and components.
-They are usually applied to elements as if they were HTML attributes, hence the name.
+You usually apply them to elements as if they were HTML attributes, hence the name.
-Many details are covered in the [_Attribute Directives_](guide/attribute-directives) guide.
Many NgModules such as the [`RouterModule`](guide/router "Routing and Navigation")
and the [`FormsModule`](guide/forms "Forms") define their own attribute directives.
-This section is an introduction to the most commonly used attribute directives:
-
-* [`NgClass`](guide/template-syntax#ngClass) - add and remove a set of CSS classes
-* [`NgStyle`](guide/template-syntax#ngStyle) - add and remove a set of HTML styles
-* [`NgModel`](guide/template-syntax#ngModel) - two-way data binding to an HTML form element
+The most common attribute directives are as follows:
+* [`NgClass`](guide/template-syntax#ngClass)—adds and removes a set of CSS classes.
+* [`NgStyle`](guide/template-syntax#ngStyle)—adds and removes a set of HTML styles.
+* [`NgModel`](guide/template-syntax#ngModel)—adds two-way data binding to an HTML form element.
{@a ngClass}
-### NgClass
+### `NgClass`
-You typically control how elements appear
-by adding and removing CSS classes dynamically.
-You can bind to the `ngClass` to add or remove several classes simultaneously.
+Add or remove several CSS classes simultaneously with `ngClass`.
-A [class binding](guide/template-syntax#class-binding) is a good way to add or remove a *single* class.
-
-
-
-
-To add or remove *many* CSS classes at the same time, the `NgClass` directive may be the better choice.
-
-Try binding `ngClass` to a key:value control object.
-Each key of the object is a CSS class name; its value is `true` if the class should be added,
-`false` if it should be removed.
-
-Consider a `setCurrentClasses` component method that sets a component property,
-`currentClasses` with an object that adds or removes three classes based on the
-`true`/`false` state of three other component properties:
-
-
-
-
-Adding an `ngClass` property binding to `currentClasses` sets the element's classes accordingly:
-
-
+
-It's up to you to call `setCurrentClasses()`, both initially and when the dependent properties change.
+To add or remove a *single* class, use [class binding](guide/template-syntax#class-binding) rather than `NgClass`.
+
+
+
+Consider a `setCurrentClasses()` component method that sets a component property,
+`currentClasses`, with an object that adds or removes three classes based on the
+`true`/`false` state of three other component properties. Each key of the object is a CSS class name; its value is `true` if the class should be added,
+`false` if it should be removed.
+
+
+
+
+Adding an `ngClass` property binding to `currentClasses` sets the element's classes accordingly:
+
+
+
+
+
+
+Remember that in this situation you'd call `setCurrentClasses()`,
+both initially and when the dependent properties change.
@@ -1319,35 +1303,34 @@ It's up to you to call `setCurrentClasses()`, both initially and when the depend
{@a ngStyle}
-### NgStyle
+### `NgStyle`
-You can set inline styles dynamically, based on the state of the component.
-With `NgStyle` you can set many inline styles simultaneously.
+Use `NgStyle` to set many inline styles simultaneously and dynamically, based on the state of the component.
-A [style binding](guide/template-syntax#style-binding) is an easy way to set a *single* style value.
+#### Without `NgStyle`
-
+For context, consider setting a *single* style value with [style binding](guide/template-syntax#style-binding), without `NgStyle`.
+
+
-To set *many* inline styles at the same time, the `NgStyle` directive may be the better choice.
+However, to set *many* inline styles at the same time, use the `NgStyle` directive.
-Try binding `ngStyle` to a key:value control object.
-Each key of the object is a style name; its value is whatever is appropriate for that style.
+The following is a `setCurrentStyles()` method that sets a component
+property, `currentStyles`, with an object that defines three styles,
+based on the state of three other component properties:
-Consider a `setCurrentStyles` component method that sets a component property, `currentStyles`
-with an object that defines three styles, based on the state of three other component properties:
-
-
+
Adding an `ngStyle` property binding to `currentStyles` sets the element's styles accordingly:
-
+
-It's up to you to call `setCurrentStyles()`, both initially and when the dependent properties change.
+Remember to call `setCurrentStyles()`, both initially and when the dependent properties change.
@@ -1356,92 +1339,78 @@ It's up to you to call `setCurrentStyles()`, both initially and when the depende
{@a ngModel}
-### NgModel - Two-way binding to form elements with [(ngModel)]
+### `[(ngModel)]`: Two-way binding
-When developing data entry forms, you often both display a data property and
-update that property when the user makes changes.
+The `NgModel` directive allows you to display a data property and
+update that property when the user makes changes. Here's an example:
-Two-way data binding with the `NgModel` directive makes that easy. Here's an example:
-
-
+
-#### _FormsModule_ is required to use _ngModel_
+
+#### Import `FormsModule` to use `ngModel`
Before using the `ngModel` directive in a two-way data binding,
you must import the `FormsModule` and add it to the NgModule's `imports` list.
-Learn more about the `FormsModule` and `ngModel` in the
-[Forms](guide/forms#ngModel) guide.
+Learn more about the `FormsModule` and `ngModel` in [Forms](guide/forms#ngModel).
-Here's how to import the `FormsModule` to make `[(ngModel)]` available.
+Remember to import the `FormsModule` to make `[(ngModel)]` available as follows:
-
+
-#### Inside [(ngModel)]
-Looking back at the `name` binding, note that
-you could have achieved the same result with separate bindings to
-the `` element's `value` property and `input` event.
+You could achieve the same result with separate bindings to
+the `` element's `value` property and `input` event:
-
+
-That's cumbersome. Who can remember which element property to set and which element event emits user changes?
-How do you extract the currently displayed text from the input box so you can update the data property?
-Who wants to look that up each time?
+To streamline the syntax, the `ngModel` directive hides the details behind its own `ngModel` input and `ngModelChange` output properties:
-That `ngModel` directive hides these onerous details behind its own `ngModel` input and `ngModelChange` output properties.
-
-
+
-
-
The `ngModel` data property sets the element's value property and the `ngModelChange` event property
listens for changes to the element's value.
+#### `NgModel` and value accessors
+
The details are specific to each kind of element and therefore the `NgModel` directive only works for an element
supported by a [ControlValueAccessor](api/forms/ControlValueAccessor)
that adapts an element to this protocol.
-The `` box is one of those elements.
Angular provides *value accessors* for all of the basic HTML form elements and the
-[_Forms_](guide/forms) guide shows how to bind to them.
+[Forms](guide/forms) guide shows how to bind to them.
-You can't apply `[(ngModel)]` to a non-form native element or a third-party custom component
-until you write a suitable *value accessor*,
-a technique that is beyond the scope of this guide.
+You can't apply `[(ngModel)]` to a non-form native element or a
+third-party custom component until you write a suitable value accessor. For more information, see
+the API documentation on [DefaultValueAccessor](https://angular.io/api/forms/DefaultValueAccessor).
-You don't need a _value accessor_ for an Angular component that you write because you
-can name the value and event properties
-to suit Angular's basic [two-way binding syntax](guide/template-syntax#two-way) and skip `NgModel` altogether.
-The [`sizer` shown above](guide/template-syntax#two-way) is an example of this technique.
+You don't need a value accessor for an Angular component that
+you write because you can name the value and event properties
+to suit Angular's basic [two-way binding syntax](guide/template-syntax#two-way)
+and skip `NgModel` altogether.
+The `sizer` in the
+[Two-way Binding](guide/template-syntax#two-way) section is an example of this technique.
-
+Separate `ngModel` bindings are an improvement over binding to the
+element's native properties, but you can streamline the binding with a
+single declaration using the `[(ngModel)]` syntax:
-Separate `ngModel` bindings is an improvement over binding to the element's native properties. You can do better.
-
-You shouldn't have to mention the data property twice. Angular should be able to capture
-the component's data property and set it
-with a single declaration, which it can with the `[(ngModel)]` syntax:
-
-
+
-Is `[(ngModel)]` all you need? Is there ever a reason to fall back to its expanded form?
+This `[(ngModel)]` syntax can only _set_ a data-bound property.
+If you need to do something more, you can write the expanded form;
+for example, the following changes the `` value to uppercase:
-The `[(ngModel)]` syntax can only _set_ a data-bound property.
-If you need to do something more or something different, you can write the expanded form.
-
-The following contrived example forces the input value to uppercase:
-
-
+
Here are all variations in action, including the uppercase version:
-
+
@@ -1451,25 +1420,29 @@ Here are all variations in action, including the uppercase version:
## Built-in _structural_ directives
Structural directives are responsible for HTML layout.
-They shape or reshape the DOM's _structure_, typically by adding, removing, and manipulating
+They shape or reshape the DOM's structure, typically by adding, removing, and manipulating
the host elements to which they are attached.
+This section is an introduction to the common built-in structural directives:
+
+* [`NgIf`](guide/template-syntax#ngIf)—conditionally creates or destroys subviews from the template.
+* [`NgFor`](guide/template-syntax#ngFor)—repeat a node for each item in a list.
+* [`NgSwitch`](guide/template-syntax#ngSwitch)—a set of directives that switch among alternative views.
+
+
+
The deep details of structural directives are covered in the
-[_Structural Directives_](guide/structural-directives) guide
-where you'll learn:
+[Structural Directives](guide/structural-directives) guide,
+which explains the following:
-* why you
-[_prefix the directive name with an asterisk_ (\*)](guide/structural-directives#asterisk "The * in *ngIf").
-* to use [``](guide/structural-directives#ngcontainer "")
+* Why you
+[prefix the directive name with an asterisk (\*)](guide/structural-directives#the-asterisk--prefix).
+* Using [``](guide/structural-directives#ngcontainer "")
to group elements when there is no suitable host element for the directive.
-* how to write your own structural directive.
-* that you can only apply [one structural directive](guide/structural-directives#one-per-element "one per host element") to an element.
+* How to write your own structural directive.
+* That you can only apply [one structural directive](guide/structural-directives#one-per-element "one per host element") to an element.
-_This_ section is an introduction to the common structural directives:
-
-* [`NgIf`](guide/template-syntax#ngIf) - conditionally add or remove an element from the DOM
-* [`NgSwitch`](guide/template-syntax#ngSwitch) - a set of directives that switch among alternative views
-* [NgForOf](guide/template-syntax#ngFor) - repeat a template for each item in a list
+
@@ -1478,85 +1451,93 @@ _This_ section is an introduction to the common structural directives:
### NgIf
You can add or remove an element from the DOM by applying an `NgIf` directive to
-that element (called the _host element_).
+a host element.
Bind the directive to a condition expression like `isActive` in this example.
-
+
-
+
-Don't forget the asterisk (`*`) in front of `ngIf`.
+Don't forget the asterisk (`*`) in front of `ngIf`. For more information
+on the asterisk, see the [asterisk (*) prefix](guide/structural-directives#the-asterisk--prefix) section of
+[Structural Directives](guide/structural-directives).
-When the `isActive` expression returns a truthy value, `NgIf` adds the `HeroDetailComponent` to the DOM.
-When the expression is falsy, `NgIf` removes the `HeroDetailComponent`
+When the `isActive` expression returns a truthy value, `NgIf` adds the
+`ItemDetailComponent` to the DOM.
+When the expression is falsy, `NgIf` removes the `ItemDetailComponent`
from the DOM, destroying that component and all of its sub-components.
-#### Show/hide is not the same thing
-You can control the visibility of an element with a
-[class](guide/template-syntax#class-binding) or [style](guide/template-syntax#style-binding) binding:
+#### Show/hide vs. `NgIf`
-
+Hiding an element is different from removing it with `NgIf`.
+For comparison, the following example shows how to control
+the visibility of an element with a
+[class](guide/template-syntax#class-binding) or [style](guide/template-syntax#style-binding) binding.
+
+
-Hiding an element is quite different from removing an element with `NgIf`.
-
-When you hide an element, that element and all of its descendents remain in the DOM.
+When you hide an element, that element and all of its descendants remain in the DOM.
All components for those elements stay in memory and
Angular may continue to check for changes.
-You could be holding onto considerable computing resources and degrading performance,
-for something the user can't see.
+You could be holding onto considerable computing resources and degrading performance
+unnecessarily.
-When `NgIf` is `false`, Angular removes the element and its descendents from the DOM.
-It destroys their components, potentially freeing up substantial resources,
-resulting in a more responsive user experience.
+`NgIf` works differently. When `NgIf` is `false`, Angular removes the element and its descendants from the DOM.
+It destroys their components, freeing up resources, which
+results in a better user experience.
-The show/hide technique is fine for a few elements with few children.
-You should be wary when hiding large component trees; `NgIf` may be the safer choice.
+If you are hiding large component trees, consider `NgIf` as a more
+efficient alternative to showing/hiding.
+
+
+
+**Note:** For more information on `NgIf` and `ngIfElse`, see the [API documentation about NgIf](api/common/NgIf).
+
+
#### Guard against null
-The `ngIf` directive is often used to guard against null.
-Show/hide is useless as a guard.
-Angular will throw an error if a nested expression tries to access a property of `null`.
+Another advantage of `ngIf` is that you can use it to guard against null. Show/hide
+is best suited for very simple use cases, so when you need a guard, opt instead for `ngIf`. Angular will throw an error if a nested expression tries to access a property of `null`.
-Here we see `NgIf` guarding two `
`s.
-The `currentHero` name will appear only when there is a `currentHero`.
-The `nullHero` will never be displayed.
+The following shows `NgIf` guarding two `
`s.
+The `currentCustomer` name appears only when there is a `currentCustomer`.
+The `nullCustomer` will not be displayed as long as it is `null`.
-
+
+
+
+
See also the
-[_safe navigation operator_](guide/template-syntax#safe-navigation-operator "Safe navigation operator (?.)")
-described below.
+[safe navigation operator](guide/template-syntax#safe-navigation-operator "Safe navigation operator (?.)") below.
-
-
{@a ngFor}
+### `NgFor`
-### NgForOf
+`NgFor` is a repeater directive—a way to present a list of items.
+You define a block of HTML that defines how a single item should be displayed
+and then you tell Angular to use that block as a template for rendering each item in the list.
-`NgForOf` is a _repeater_ directive — a way to present a list of items.
-You define a block of HTML that defines how a single item should be displayed.
-You tell Angular to use that block as a template for rendering each item in the list.
+Here is an example of `NgFor` applied to a simple `
`:
-Here is an example of `NgForOf` applied to a simple `
`:
-
-
+
-You can also apply an `NgForOf` to a component element, as in this example:
+You can also apply an `NgFor` to a component element, as in this example:
-
+
@@ -1569,50 +1550,53 @@ The text assigned to `*ngFor` is the instruction that guides the repeater proces
{@a microsyntax}
-#### *ngFor microsyntax
+#### `*ngFor` microsyntax
-The string assigned to `*ngFor` is not a [template expression](guide/template-syntax#template-expressions).
-It's a *microsyntax* — a little language of its own that Angular interprets.
-The string `"let hero of heroes"` means:
+The string assigned to `*ngFor` is not a [template expression](guide/template-syntax#template-expressions). Rather,
+it's a *microsyntax*—a little language of its own that Angular interprets.
+The string `"let item of items"` means:
-> *Take each hero in the `heroes` array, store it in the local `hero` looping variable, and
+> *Take each item in the `items` array, store it in the local `item` looping variable, and
make it available to the templated HTML for each iteration.*
-Angular translates this instruction into a `` around the host element,
-then uses this template repeatedly to create a new set of elements and bindings for each `hero`
+Angular translates this instruction into an `` around the host element,
+then uses this template repeatedly to create a new set of elements and bindings for each `item`
in the list.
-Learn about the _microsyntax_ in the [_Structural Directives_](guide/structural-directives#microsyntax) guide.
+For more information about microsyntax, see the [Structural Directives](guide/structural-directives#microsyntax) guide.
+
{@a template-input-variable}
{@a template-input-variables}
-### Template input variables
-The `let` keyword before `hero` creates a _template input variable_ called `hero`.
-The `NgForOf` directive iterates over the `heroes` array returned by the parent component's `heroes` property
-and sets `hero` to the current item from the array during each iteration.
+#### Template input variables
-You reference the `hero` input variable within the `NgForOf` host element
-(and within its descendants) to access the hero's properties.
-Here it is referenced first in an interpolation
-and then passed in a binding to the `hero` property of the `` component.
+The `let` keyword before `item` creates a template input variable called `item`.
+The `ngFor` directive iterates over the `items` array returned by the parent component's `items` property
+and sets `item` to the current item from the array during each iteration.
-
+Reference `item` within the `ngFor` host element
+as well as within its descendants to access the item's properties.
+The following example references `item` first in an interpolation
+and then passes in a binding to the `item` property of the `` component.
+
+
-Learn more about _template input variables_ in the
-[_Structural Directives_](guide/structural-directives#template-input-variable) guide.
+For more information about template input variables, see
+[Structural Directives](guide/structural-directives#template-input-variable).
-#### *ngFor with _index_
+#### `*ngFor` with `index`
-The `index` property of the `NgForOf` directive context returns the zero-based index of the item in each iteration.
+The `index` property of the `NgFor` directive context
+returns the zero-based index of the item in each iteration.
You can capture the `index` in a template input variable and use it in the template.
-The next example captures the `index` in a variable named `i` and displays it with the hero name like this.
+The next example captures the `index` in a variable named `i` and displays it with the item name.
-
+
@@ -1623,87 +1607,79 @@ and `odd` in the [NgForOf API reference](api/common/NgForOf).
{@a trackBy}
+#### *ngFor with `trackBy`
-#### *ngFor with _trackBy_
+If you use `NgFor` with large lists, a small change to one item, such as removing or adding an item, can trigger a cascade of DOM manipulations. For example, re-querying the server could reset a list with all new item objects, even when those items were previously displayed. In this case, Angular sees only a fresh list of new object references and has no choice but to replace the old DOM elements with all new DOM elements.
-The `NgForOf` directive may perform poorly, especially with large lists.
-A small change to one item, an item removed, or an item added can trigger a cascade of DOM manipulations.
+You can make this more efficient with `trackBy`.
+Add a method to the component that returns the value `NgFor` should track.
+In this case, that value is the hero's `id`. If the `id` has already been rendered,
+Angular keeps track of it and doesn't re-query the server for the same `id`.
-For example, re-querying the server could reset the list with all new hero objects.
-
-Most, if not all, are previously displayed heroes.
-*You* know this because the `id` of each hero hasn't changed.
-But Angular sees only a fresh list of new object references.
-It has no choice but to tear down the old DOM elements and insert all new DOM elements.
-
-Angular can avoid this churn with `trackBy`.
-Add a method to the component that returns the value `NgForOf` _should_ track.
-In this case, that value is the hero's `id`.
-
-
+
-In the microsyntax expression, set `trackBy` to this method.
+In the microsyntax expression, set `trackBy` to the `trackByItems()` method.
-
+
-Here is an illustration of the _trackBy_ effect.
-"Reset heroes" creates new heroes with the same `hero.id`s.
-"Change ids" creates new heroes with new `hero.id`s.
+Here is an illustration of the `trackBy` effect.
+"Reset items" creates new items with the same `item.id`s.
+"Change ids" creates new items with new `item.id`s.
* With no `trackBy`, both buttons trigger complete DOM element replacement.
* With `trackBy`, only changing the `id` triggers element replacement.
-
+
-
{@a ngSwitch}
+## The `NgSwitch` directives
-### The _NgSwitch_ directives
+NgSwitch is like the JavaScript `switch` statement.
+It displays one element from among several possible elements, based on a switch condition.
+Angular puts only the selected element into the DOM.
+
+`NgSwitch` is actually a set of three, cooperating directives:
+`NgSwitch`, `NgSwitchCase`, and `NgSwitchDefault` as in the following example.
-*NgSwitch* is like the JavaScript `switch` statement.
-It can display _one_ element from among several possible elements, based on a _switch condition_.
-Angular puts only the *selected* element into the DOM.
-
-*NgSwitch* is actually a set of three, cooperating directives:
-`NgSwitch`, `NgSwitchCase`, and `NgSwitchDefault` as seen in this example.
-
-
+
-
+
-`NgSwitch` is the controller directive. Bind it to an expression that returns the *switch value*.
-The `emotion` value in this example is a string, but the switch value can be of any type.
+`NgSwitch` is the controller directive. Bind it to an expression that returns
+the *switch value*, such as `feature`. Though the `feature` value in this
+example is a string, the switch value can be of any type.
**Bind to `[ngSwitch]`**. You'll get an error if you try to set `*ngSwitch` because
`NgSwitch` is an *attribute* directive, not a *structural* directive.
-It changes the behavior of its companion directives.
-It doesn't touch the DOM directly.
+Rather than touching the DOM directly, it changes the behavior of its companion directives.
**Bind to `*ngSwitchCase` and `*ngSwitchDefault`**.
The `NgSwitchCase` and `NgSwitchDefault` directives are _structural_ directives
because they add or remove elements from the DOM.
-* `NgSwitchCase` adds its element to the DOM when its bound value equals the switch value.
+* `NgSwitchCase` adds its element to the DOM when its bound value equals the switch value and removes
+its bound value when it doesn't equal the switch value.
+
* `NgSwitchDefault` adds its element to the DOM when there is no selected `NgSwitchCase`.
The switch directives are particularly useful for adding and removing *component elements*.
-This example switches among four "emotional hero" components defined in the `hero-switch.components.ts` file.
-Each component has a `hero` [input property](guide/template-syntax#inputs-outputs "Input property")
-which is bound to the `currentHero` of the parent component.
+This example switches among four `item` components defined in the `item-switch.components.ts` file.
+Each component has an `item` [input property](guide/template-syntax#inputs-outputs "Input property")
+which is bound to the `currentItem` of the parent component.
Switch directives work as well with native elements and web components too.
-For example, you could replace the `` switch case with the following.
+For example, you could replace the `` switch case with the following.
-
+
diff --git a/aio/content/images/guide/built-in-directives/ng-model-anim.gif b/aio/content/images/guide/built-in-directives/ng-model-anim.gif
new file mode 100644
index 0000000000..65af12f6cf
Binary files /dev/null and b/aio/content/images/guide/built-in-directives/ng-model-anim.gif differ
diff --git a/aio/content/images/guide/built-in-directives/ngfor-trackby.gif b/aio/content/images/guide/built-in-directives/ngfor-trackby.gif
new file mode 100644
index 0000000000..4aa5107d63
Binary files /dev/null and b/aio/content/images/guide/built-in-directives/ngfor-trackby.gif differ
diff --git a/aio/content/images/guide/built-in-directives/ngswitch.gif b/aio/content/images/guide/built-in-directives/ngswitch.gif
new file mode 100644
index 0000000000..9405841a20
Binary files /dev/null and b/aio/content/images/guide/built-in-directives/ngswitch.gif differ