diff --git a/aio/content/examples/built-in-directives/src/app/app.component.html b/aio/content/examples/built-in-directives/src/app/app.component.html index 17b3fed9a4..6e5d8cba2f 100644 --- a/aio/content/examples/built-in-directives/src/app/app.component.html +++ b/aio/content/examples/built-in-directives/src/app/app.component.html @@ -7,11 +7,8 @@

NgModel examples

Current item name: {{currentItem.name}}

- - -

@@ -27,10 +24,8 @@

- -

@@ -77,12 +72,9 @@


NgStyle Binding

-
This div is x-large or smaller.
- -

[ngStyle] binding to currentStyles - CSS property names

currentStyles is {{currentStyles | json}}

@@ -134,7 +126,6 @@

Show/hide vs. NgIf

-
Show with class
Hide with class
@@ -144,7 +135,6 @@
Show with style
Hide with style
-
diff --git a/aio/content/examples/built-in-directives/src/app/app.component.ts b/aio/content/examples/built-in-directives/src/app/app.component.ts index a2035effa5..9610096841 100644 --- a/aio/content/examples/built-in-directives/src/app/app.component.ts +++ b/aio/content/examples/built-in-directives/src/app/app.component.ts @@ -21,7 +21,10 @@ export class AppComponent implements OnInit { item: Item; // defined to demonstrate template context precedence items: Item[]; + // #docregion item currentItem: Item; + // #enddocregion item + // trackBy change counting 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 index b40d5c9af5..59909eedc7 100644 --- 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 @@ -5,9 +5,13 @@ import { Item } from './item'; selector: 'app-stout-item', template: `I'm a little {{item.name}}, short and stout!` }) + +// #docregion input export class StoutItemComponent { @Input() item: Item; } +// #enddocregion input + @Component({ selector: 'app-best-item', diff --git a/aio/content/guide/ajs-quick-reference.md b/aio/content/guide/ajs-quick-reference.md index 23b6d61028..ebfb822779 100644 --- a/aio/content/guide/ajs-quick-reference.md +++ b/aio/content/guide/ajs-quick-reference.md @@ -140,8 +140,7 @@ The following table lists some of the key AngularJS template features with their Angular has true template input variables that are explicitly defined using the `let` keyword. - For more information, see the [ngFor micro-syntax](guide/built-in-directives#microsyntax) - section of the [Built-in Directives](guide/built-in-directives) page. + For more information, see the [Template input variables](guide/structural-directives#template-input-variable) section of [Structural Directives](guide/structural-directives). @@ -641,7 +640,7 @@ The following are some of the key AngularJS built-in directives and their equiva For more information on style binding, see the [Style binding](guide/attribute-binding#style-binding) section of the [Attribute binding](guide/attribute-binding) page. - For more information on the `ngStyle` directive, see the [NgStyle](guide/built-in-directives#ngStyle) + For more information on the `ngStyle` directive, see the [NgStyle](guide/built-in-directives#ngstyle) section of the [Built-in directives](guide/built-in-directives) page. diff --git a/aio/content/guide/architecture-components.md b/aio/content/guide/architecture-components.md index 8f38847295..5e3606e761 100644 --- a/aio/content/guide/architecture-components.md +++ b/aio/content/guide/architecture-components.md @@ -181,7 +181,7 @@ The `ngModel` directive, which implements two-way data binding, is an example of Angular has more pre-defined directives that either alter the layout structure (for example, [ngSwitch](guide/built-in-directives#ngSwitch)) or modify aspects of DOM elements and components -(for example, [ngStyle](guide/built-in-directives#ngStyle) and [ngClass](guide/built-in-directives#ngClass)). +(for example, [ngStyle](guide/built-in-directives#ngstyle) and [ngClass](guide/built-in-directives#ngClass)).
diff --git a/aio/content/guide/attribute-directives.md b/aio/content/guide/attribute-directives.md index 42562504e9..047d011a91 100644 --- a/aio/content/guide/attribute-directives.md +++ b/aio/content/guide/attribute-directives.md @@ -22,7 +22,7 @@ Two examples are [NgFor](guide/built-in-directives#ngFor) and [NgIf](guide/built Learn about them in the [Structural Directives](guide/structural-directives) guide. *Attribute directives* are used as attributes of elements. -The built-in [NgStyle](guide/built-in-directives#ngStyle) directive in the +The built-in [NgStyle](guide/built-in-directives#ngstyle) directive in the [Built-in directives](guide/built-in-directives) guide, for example, can change several element styles at the same time. diff --git a/aio/content/guide/built-in-directives.md b/aio/content/guide/built-in-directives.md index 294b90f690..901eeea7db 100644 --- a/aio/content/guide/built-in-directives.md +++ b/aio/content/guide/built-in-directives.md @@ -1,6 +1,8 @@ # Built-in directives -Angular offers two kinds of built-in directives: [_attribute_ directives](guide/attribute-directives) and [_structural_ directives](guide/structural-directives). +Directives are classes that add additional behavior to elements +in your Angular applications. +With Angular's built-in directives, you can manage forms, lists, styles, and what users see.
@@ -8,29 +10,31 @@ See the for a working example containing the code
-For more detail, including how to build your own custom directives, see [Attribute Directives](guide/attribute-directives) and [Structural Directives](guide/structural-directives). +The different types of Angular directives are as follows: + +1. [Components](guide/component-overview)—directives with a template. + This type of directive is the most common directive type. +1. [Attribute directives](guide/built-in-directives#built-in-attribute-directives)—directives that change the appearance or behavior of an element, component, or another directive. +1. [Structural directives](guide/built-in-directives#built-in-structural-directives)—directives that change the DOM layout by adding and removing DOM elements. + +This guide covers built-in [attribute directives](guide/built-in-directives#built-in-attribute-directives) and [structural directives](guide/built-in-directives#built-in-structural-directives). {@a attribute-directives} ## Built-in attribute directives -Attribute directives listen to and modify the behavior of -other HTML elements, attributes, properties, and components. -You usually apply them to elements as if they were HTML attributes, hence the name. +Attribute directives listen to and modify the behavior of other HTML elements, attributes, properties, and components. -Many NgModules such as the [`RouterModule`](guide/router "Routing and Navigation") -and the [`FormsModule`](guide/forms "Forms") define their own attribute directives. +Many NgModules such as the [`RouterModule`](guide/router "Routing and Navigation") and the [`FormsModule`](guide/forms "Forms") define their own attribute directives. The most common attribute directives are as follows: * [`NgClass`](guide/built-in-directives#ngClass)—adds and removes a set of CSS classes. -* [`NgStyle`](guide/built-in-directives#ngStyle)—adds and removes a set of HTML styles. +* [`NgStyle`](guide/built-in-directives#ngstyle)—adds and removes a set of HTML styles. * [`NgModel`](guide/built-in-directives#ngModel)—adds two-way data binding to an HTML form element. {@a ngClass} -## `NgClass` +## Adding and removing classes with `NgClass` -Add or remove several CSS classes simultaneously with `ngClass`. - - +You can add or remove multiple CSS classes simultaneously with `ngClass`.
@@ -38,114 +42,72 @@ To add or remove a *single* class, use [class binding](guide/attribute-binding#c
-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. +### Using `NgClass` with an expression - +On the element you'd like to style, add `[ngClass]` and set it equal to an expression. +In this case, `isSpecial` is a boolean set to `true` in `app.component.ts`. +Because `isSpecial` is true, `ngClass` applies the class of `special` to the `
`. -Adding an `ngClass` property binding to `currentClasses` sets the element's classes accordingly: + - +### Using `NgClass` with a method -
+1. To use `NgClass` with a method, add the method to the component class. + In the following example, `setCurrentClasses()` sets the property `currentClasses` with an object that adds or removes three classes based on the `true` or `false` state of three other component properties. -Remember that in this situation you'd call `setCurrentClasses()`, -both initially and when the dependent properties change. + Each key of the object is a CSS class name. + If a key is `true`, `ngClass` adds the class. + If a key is `false`, `ngClass` removes the class. -
+ -{@a ngStyle} -## `NgStyle` +1. In the template, add the `ngClass` property binding to `currentClasses` to set the element's classes: -Use `NgStyle` to set many inline styles simultaneously and dynamically, based on the state of the component. + -### Without `NgStyle` +For this use case, Angular applies the classes on initialization and in case of changes. +The full example calls `setCurrentClasses()` initially with `ngOnInit()` and when the dependent properties change through a button click. +These steps are not necessary to implement `ngClass`. +For more information, see the `app.component.ts` and `app.component.html`. -For context, consider setting a *single* style value with [style binding](guide/attribute-binding#style-binding), without `NgStyle`. +{@a ngstyle} +## Setting inline styles with `NgStyle` - +You can use `NgStyle` to set multiple inline styles simultaneously, based on the state of the component. -However, to set *many* inline styles at the same time, use the `NgStyle` directive. +1. To use `NgStyle`, add a method to the component class. -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: + In the following example, `setCurrentStyles()` sets the 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: +1. To set the element's styles, add an `ngStyle` property binding to `currentStyles`. - - -
- -Remember to call `setCurrentStyles()`, both initially and when the dependent properties change. - -
+ +For this use case, Angular applies the styles upon initialization and in case of changes. +To do this, the full example calls `setCurrentStyles()` initially with `ngOnInit()` and when the dependent properties change through a button click. +However, these steps are not necessary to implement `ngStyle` on its own. +See the `app.component.ts` and `app.component.html` for this optional implementation. {@a ngModel} -## `[(ngModel)]`: Two-way binding +## Displaying and updating properties with `ngModel` -The `NgModel` directive allows you to display a data property and -update that property when the user makes changes. Here's an example: +You can use the `NgModel` directive to display a data property and update that property when the user makes changes. - +1. Import `FormsModule` and add it to the NgModule's `imports` list. + -### Import `FormsModule` to use `ngModel` +1. Add an `[(ngModel)]` binding on an HTML `
` element and set it equal to the property, here `name`. -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 [Forms](guide/forms#ngModel). + -Remember to import the `FormsModule` to make `[(ngModel)]` available as follows: + This `[(ngModel)]` syntax can only set a data-bound property. - - - -You could achieve the same result with separate bindings to -the `` element's `value` property and `input` event: - - - -To streamline the syntax, the `ngModel` directive hides the 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. -Angular provides *value accessors* for all of the basic HTML form elements and the -[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. For more information, see -the API documentation on [DefaultValueAccessor](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/two-way-binding) -and skip `NgModel` altogether. -The `sizer` in the -[Two-way Binding](guide/two-way-binding) 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: - - - -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: +To customize your configuration, you can write the expanded form, which separates the property and event binding. +Use [property binding](guide/property-binding) to set the property and [event binding](guide/event-binding) to respond to changes. +The following example changes the `` value to uppercase: @@ -155,198 +117,146 @@ Here are all variations in action, including the uppercase version: NgModel variations
+ +### `NgModel` and value accessors + +The `NgModel` directive works for an element supported by a [ControlValueAccessor](api/forms/ControlValueAccessor). +Angular provides *value accessors* for all of the basic HTML form elements. +For more information, see [Forms](guide/forms). + +To apply `[(ngModel)]` to a non-form native element or a third-party custom component, you have to write a value accessor. +For more information, see the API documentation on [DefaultValueAccessor](api/forms/DefaultValueAccessor). + +
+ +When you write an Angular component, you don't need a value accessor or `NgModel` if you name the value and event properties according to Angular's [two-way binding syntax](guide/two-way-binding#how-two-way-binding-works). + +
+ {@a structural-directives} -## Built-in _structural_ directives + +## 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 -the host elements to which they are attached. +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: +This section introduces the most common built-in structural directives: -* [`NgIf`](guide/built-in-directives#ngIf)—conditionally creates or destroys subviews from the template. +* [`NgIf`](guide/built-in-directives#ngIf)—conditionally creates or disposes of subviews from the template. * [`NgFor`](guide/built-in-directives#ngFor)—repeat a node for each item in a list. * [`NgSwitch`](guide/built-in-directives#ngSwitch)—a set of directives that switch among alternative views. -
+For more information, see [Structural Directives](guide/structural-directives). -The deep details of structural directives are covered in the -[Structural Directives](guide/structural-directives) guide, -which explains the following: - -* 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. -* Why you [can only apply one structural directive](guide/structural-directives#one-per-element "one per host element") to an element. - -
{@a ngIf} -## NgIf +## Adding or removing an element with `NgIf` -You can add or remove an element from the DOM by applying an `NgIf` directive to -a host element. -Bind the directive to a condition expression like `isActive` in this example. +You can add or remove an element by applying an `NgIf` directive to a host element. + +When `NgIf` is `false`, Angular removes an element and its descendants from the DOM. +Angular then disposes of their components, which frees up memory and resources. + +To add or remove an element, bind `*ngIf` to a condition expression such as `isActive` in the following example. -
+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 and disposes of the component and all of its sub-components. -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). +For more information on `NgIf` and `NgIfElse`, see the [NgIf API documentation](api/common/NgIf). -
+### Guarding against `null` -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. +By default, `NgIf` prevents display of an element bound to a null value. - -### 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/attribute-binding#class-binding) or [style](guide/attribute-binding#style-binding) binding. - - - -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 -unnecessarily. - -`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. - -If you are hiding large component trees, consider `NgIf` as a more -efficient alternative to showing/hiding. - -
- -For more information on `NgIf` and `ngIfElse`, see the [API documentation about NgIf](api/common/NgIf). - -
- -### Guard against 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`. - -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`. +To use `NgIf` to guard a `
`, add `*ngIf="yourProperty"` to the `
`. +In the following example, the `currentCustomer` name appears because there is a `currentCustomer`. +However, if the property is `null`, Angular does not display the `
`. +In this example, Angular does not display the `nullCustomer` because it is `null`. + {@a ngFor} -## `NgFor` +## Listing items with `NgFor` -`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. -The text assigned to `*ngFor` is the instruction that guides the repeater process. +You can use the `NgFor` directive to present a list of items. -The following example shows `NgFor` applied to a simple `
`. +1. Define a block of HTML that determines how Angular renders a single item. + +1. To list your items, assign the short hand `let item of items` to `*ngFor`. -
+The string `"let item of items"` instructs Angular to do the following: -Don't forget the asterisk (`*`) in front of `ngFor`. For more information -on the asterisk, see the [asterisk (*) prefix](guide/structural-directives#the-asterisk--prefix) section of -[Structural Directives](guide/structural-directives). + * Store each item in the `items` array in the local `item` looping variable + * Make each item available to the templated HTML for each iteration + * Translate `"let item of items"` into an `` around the host element + * Repeat the `` for each `item` in the list -
+For more information see the [`` section](guide/structural-directives#the-ng-template) of [Structural directives](guide/structural-directives). +### Repeating a component view -You can also apply an `NgFor` to a component element, as in the following example. +To repeat a component element, apply `*ngFor` to the selector. +In the following example, the selector is ``. -{@a microsyntax} +You can reference a template input variable, such as `item`, in the following locations: -
-
*ngFor microsyntax
+ * within the `ngFor` host element + * within the host element descendants to access the item's properties -The string assigned to `*ngFor` is not a [template expression](guide/interpolation). Rather, -it's a *microsyntax*—a little language of its own that Angular interprets. -The string `"let item of items"` means: - -> *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 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. -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 `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. +The following example references `item` first in an interpolation and then passes in a binding to the `item` property of the `` component. -For more information about template input variables, see -[Structural Directives](guide/structural-directives#template-input-variable). +For more information about template input variables, see [Structural Directives](guide/structural-directives#template-input-variable). -### `*ngFor` with `index` +### Getting the `index` of `*ngFor` -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. +You can get the `index` of `*ngFor` 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 item name. +In the `*ngFor`, add a semicolon and `let i=index` to the short hand. +The following example gets the `index` in a variable named `i` and displays it with the item name. -
+The index property of the `NgFor` directive context returns the zero-based index of the item in each iteration. -`NgFor` is implemented by the `NgForOf` directive. Read more about the other `NgForOf` context values such as `last`, `even`, -and `odd` in the [NgForOf API reference](api/common/NgForOf). +{@a one-per-element} -
+## Repeating elements when a condition is true -{@a trackBy} -### *ngFor with `trackBy` +To repeat a block of HTML when a particular condition is true, put the `*ngIf` on a container element that wraps an `*ngFor` element. +One or both elements can be an `` so you don't have to introduce extra levels of HTML. -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. +Because structural directives add and remove nodes from the DOM, apply only one structural directive per element. -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 more information about `NgFor` see the [NgForOf API reference](api/common/NgForOf). - +{@a ngfor-with-trackby} +### Tracking items with `*ngFor` `trackBy` -In the microsyntax expression, set `trackBy` to the `trackByItems()` method. +By tracking changes to an item list, you can reduce the number of calls your application makes to the server. +With the `*ngFor` `trackBy` property, Angular can change and re-render only those items that have changed, rather than reloading the entire list of items. - +1. Add a method to the component that returns the value `NgFor` should track. + In this example, the value to track is the item's `id`. + If the browser has already rendered `id`, Angular keeps track of it and doesn't re-query the server for the same `id`. -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. + + +1. In the short hand expression, set `trackBy` to the `trackByItems()` method. + + + +**Change ids** creates new items with new `item.id`s. +In the following illustration of the `trackBy` effect, **Reset items** creates new items with the same `item.id`s. * With no `trackBy`, both buttons trigger complete DOM element replacement. * With `trackBy`, only changing the `id` triggers element replacement. @@ -355,53 +265,82 @@ Here is an illustration of the `trackBy` effect. Animation of trackBy
-
-Built-in directives use only public APIs; that is, -they do not have special access to any private APIs that other directives can't access. +Built-in directives use only public APIs. +They do not have special access to any private APIs that other directives can't access.
-{@a ngSwitch} -## The `NgSwitch` directives +{@a ngcontainer} -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. +## Hosting a directive without a DOM element + +The Angular `` is a grouping element that doesn't interfere with styles or layout because Angular doesn't put it in the DOM. + +You can use [``](guide/structural-directives#ngcontainer) when there's no single element to host the directive. + +Here's a conditional paragraph using ``. + + - -`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. +1. Import the `ngModel` directive from `FormsModule`. -**Bind to `[ngSwitch]`**. You'll get an error if you try to set `*ngSwitch` because -`NgSwitch` is an *attribute* directive, not a *structural* directive. -Rather than touching the DOM directly, it changes the behavior of its companion directives. +1. Add `FormsModule` to the imports section of the relevant Angular module. -**Bind to `*ngSwitchCase` and `*ngSwitchDefault`**. -The `NgSwitchCase` and `NgSwitchDefault` directives are _structural_ directives -because they add or remove elements from the DOM. +1. To conditionally exclude an `