docs: separate template syntax into multiple docs (#36954)
This is part of a re-factor of template syntax and structure. The first phase breaks out template syntax into multiple documents. The second phase will be a rewrite of each doc. Specifically, this PR does the following: - Breaks sections of the current template syntax document each into their own page. - Corrects the links to and from these new pages. - Adds template syntax subsection to the left side NAV which contains all the new pages. - Adds the new files to pullapprove. PR Close #36954
This commit is contained in:
parent
5d3d8b8330
commit
5b31a0a294
|
@ -346,20 +346,31 @@ groups:
|
|||
'aio/content/guide/ngmodule-vs-jsmodule.md',
|
||||
'aio/content/guide/module-types.md',
|
||||
'aio/content/guide/template-syntax.md',
|
||||
'aio/content/guide/built-in-template-functions.md',
|
||||
'aio/content/examples/built-in-template-functions/**',
|
||||
'aio/content/guide/event-binding.md',
|
||||
'aio/content/examples/event-binding/**',
|
||||
'aio/content/guide/interpolation.md',
|
||||
'aio/content/examples/interpolation/**',
|
||||
'aio/content/examples/template-syntax/**',
|
||||
'aio/content/images/guide/template-syntax/**',
|
||||
'aio/content/guide/binding-syntax.md',
|
||||
'aio/content/examples/binding-syntax/**',
|
||||
'aio/content/guide/property-binding.md',
|
||||
'aio/content/examples/property-binding/**',
|
||||
'aio/content/guide/attribute-binding.md',
|
||||
'aio/content/examples/attribute-binding/**',
|
||||
'aio/content/guide/two-way-binding.md',
|
||||
'aio/content/examples/two-way-binding/**',
|
||||
'aio/content/guide/built-in-directives.md',
|
||||
'aio/content/examples/built-in-directives/**',
|
||||
'aio/content/images/guide/built-in-directives/**',
|
||||
'aio/content/guide/template-reference-variables.md',
|
||||
'aio/content/examples/template-reference-variables/**',
|
||||
'aio/content/guide/inputs-outputs.md',
|
||||
'aio/content/examples/inputs-outputs/**',
|
||||
'aio/content/images/guide/inputs-outputs/**',
|
||||
'aio/content/guide/template-expression-operators.md',
|
||||
'aio/content/examples/template-expression-operators/**',
|
||||
'aio/content/guide/pipes.md',
|
||||
'aio/content/examples/pipes/**',
|
||||
|
@ -374,7 +385,9 @@ groups:
|
|||
'aio/content/guide/sharing-ngmodules.md',
|
||||
'aio/content/guide/structural-directives.md',
|
||||
'aio/content/examples/structural-directives/**',
|
||||
'aio/content/guide/svg-in-templates.md',
|
||||
'aio/content/images/guide/structural-directives/**',
|
||||
'aio/content/guide/template-statements.md',
|
||||
'aio/content/guide/user-input.md',
|
||||
'aio/content/examples/user-input/**',
|
||||
'aio/content/images/guide/user-input/**'
|
||||
|
|
|
@ -20,7 +20,7 @@ work well for all users, including those who rely on assistive technologies.
|
|||
|
||||
Building accessible web experience often involves setting [ARIA attributes](https://developers.google.com/web/fundamentals/accessibility/semantics-aria)
|
||||
to provide semantic meaning where it might otherwise be missing.
|
||||
Use [attribute binding](guide/template-syntax#attribute-binding) template syntax to control the values of accessibility-related attributes.
|
||||
Use [attribute binding](guide/attribute-binding) template syntax to control the values of accessibility-related attributes.
|
||||
|
||||
When binding to ARIA attributes in Angular, you must use the `attr.` prefix, as the ARIA
|
||||
specification depends specifically on HTML attributes rather than properties of DOM elements.
|
||||
|
@ -44,7 +44,7 @@ NOTE:
|
|||
|
||||
By convention, HTML attributes use lowercase names (`tabindex`), while properties use camelCase names (`tabIndex`).
|
||||
|
||||
See the [Template Syntax](guide/template-syntax#html-attribute-vs-dom-property) guide for more background on the difference between attributes and properties.
|
||||
See the [Binding syntax](guide/binding-syntax#html-attribute-vs-dom-property) guide for more background on the difference between attributes and properties.
|
||||
|
||||
</div>
|
||||
|
||||
|
|
|
@ -74,8 +74,7 @@ The following table lists some of the key AngularJS template features with their
|
|||
The context of the binding is implied and is always the
|
||||
associated component, so it needs no reference variable.
|
||||
|
||||
For more information, see the [Interpolation](guide/template-syntax#interpolation)
|
||||
section of the [Template Syntax](guide/template-syntax) page.
|
||||
For more information, see the [Interpolation](guide/interpolation) guide.
|
||||
</td>
|
||||
|
||||
</tr>
|
||||
|
@ -141,8 +140,8 @@ 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/template-syntax#microsyntax)
|
||||
section of the [Template Syntax](guide/template-syntax) page.
|
||||
For more information, see the [ngFor micro-syntax](guide/built-in-directives#microsyntax)
|
||||
section of the [Built-in Directives](guide/built-in-directives) page.
|
||||
</td>
|
||||
|
||||
</tr>
|
||||
|
@ -258,8 +257,7 @@ The following are some of the key AngularJS built-in directives and their equiva
|
|||
Angular also has **class binding**, which is a good way to add or remove a single class,
|
||||
as shown in the third example.
|
||||
|
||||
For more information see the [Attribute, class, and style bindings](guide/template-syntax#other-bindings)
|
||||
section of the [Template Syntax](guide/template-syntax) page.
|
||||
For more information see [Attribute, class, and style bindings](guide/attribute-binding) page.
|
||||
|
||||
</td>
|
||||
|
||||
|
@ -309,8 +307,7 @@ The following are some of the key AngularJS built-in directives and their equiva
|
|||
|
||||
For a list of DOM events, see: https://developer.mozilla.org/en-US/docs/Web/Events.
|
||||
|
||||
For more information, see the [Event binding](guide/template-syntax#event-binding)
|
||||
section of the [Template Syntax](guide/template-syntax) page.
|
||||
For more information, see the [Event binding](guide/event-binding) page.
|
||||
|
||||
</td>
|
||||
|
||||
|
@ -407,8 +404,7 @@ The following are some of the key AngularJS built-in directives and their equiva
|
|||
Angular uses property binding; there is no built-in *href* directive.
|
||||
Place the element's `href` property in square brackets and set it to a quoted template expression.
|
||||
|
||||
For more information see the [Property binding](guide/template-syntax#property-binding)
|
||||
section of the [Template Syntax](guide/template-syntax) page.
|
||||
For more information see the [Property binding](guide/property-binding) page.
|
||||
|
||||
In Angular, `href` is no longer used for routing. Routing uses `routerLink`, as shown in the following example.
|
||||
|
||||
|
@ -487,8 +483,8 @@ The following are some of the key AngularJS built-in directives and their equiva
|
|||
and event binding (from the view to the component), thereby providing two-way binding.
|
||||
|
||||
For more information on two-way binding with `ngModel`, see the [NgModel—Two-way binding to
|
||||
form elements with `[(ngModel)]`](../guide/template-syntax.html#ngModel)
|
||||
section of the [Template Syntax](guide/template-syntax) page.
|
||||
form elements with `[(ngModel)]`](../guide/built-in-directives#ngModel)
|
||||
section of the [Built-in directives](guide/built-in-directives) page.
|
||||
</td>
|
||||
|
||||
</tr>
|
||||
|
@ -570,8 +566,7 @@ The following are some of the key AngularJS built-in directives and their equiva
|
|||
|
||||
In this example, the `<div>` element is hidden if the `favoriteHero` variable is not truthy.
|
||||
|
||||
For more information on property binding, see the [Property binding](guide/template-syntax#property-binding)
|
||||
section of the [Template Syntax](guide/template-syntax) page.
|
||||
For more information on property binding, see the [Property binding](guide/property-binding) page.
|
||||
</td>
|
||||
|
||||
</tr>
|
||||
|
@ -604,8 +599,7 @@ The following are some of the key AngularJS built-in directives and their equiva
|
|||
Angular uses property binding; there is no built-in *src* directive.
|
||||
Place the `src` property in square brackets and set it to a quoted template expression.
|
||||
|
||||
For more information on property binding, see the [Property binding](guide/template-syntax#property-binding)
|
||||
section of the [Template Syntax](guide/template-syntax) page.
|
||||
For more information on property binding, see the [Property binding](guide/property-binding) page.
|
||||
</td>
|
||||
|
||||
</tr>
|
||||
|
@ -644,11 +638,11 @@ The following are some of the key AngularJS built-in directives and their equiva
|
|||
|
||||
Angular also has **style binding**, which is good way to set a single style. This is shown in the second example.
|
||||
|
||||
For more information on style binding, see the [Style binding](guide/template-syntax#style-binding) section of the
|
||||
[Template Syntax](guide/template-syntax) page.
|
||||
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 [NgStyle](guide/template-syntax#ngStyle)
|
||||
section of the [Template Syntax](guide/template-syntax) page.
|
||||
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.
|
||||
</td>
|
||||
|
||||
</tr>
|
||||
|
@ -704,8 +698,8 @@ The following are some of the key AngularJS built-in directives and their equiva
|
|||
|
||||
The (*) before `ngSwitchCase` and `ngSwitchDefault` is required in this example.
|
||||
|
||||
For more information, see [The NgSwitch directives](guide/template-syntax#ngSwitch)
|
||||
section of the [Template Syntax](guide/template-syntax) page.
|
||||
For more information, see [The NgSwitch directives](guide/built-in-directives#ngSwitch)
|
||||
section of the [Built-in directives](guide/built-in-directives) page.
|
||||
</td>
|
||||
|
||||
</tr>
|
||||
|
|
|
@ -623,7 +623,7 @@ For more information about input type narrowing, see [Input setter coercion](gui
|
|||
|
||||
### Non-null type assertion operator
|
||||
|
||||
Use the [non-null type assertion operator](guide/template-syntax#non-null-assertion-operator) to suppress the `Object is possibly 'undefined'` error when it is inconvenient to use `*ngIf` or when some constraint in the component ensures that the expression is always non-null when the binding expression is interpolated.
|
||||
Use the [non-null type assertion operator](guide/template-expression-operators#non-null-assertion-operator) to suppress the `Object is possibly 'undefined'` error when it is inconvenient to use `*ngIf` or when some constraint in the component ensures that the expression is always non-null when the binding expression is interpolated.
|
||||
|
||||
In the following example, the `person` and `address` properties are always set together, implying that `address` is always non-null if `person` is non-null.
|
||||
There is no convenient way to describe this constraint to TypeScript and the template compiler, but the error is suppressed in the example by using `address!.street`.
|
||||
|
|
|
@ -92,7 +92,7 @@ This example from the `HeroListComponent` template uses three of these forms.
|
|||
* The `{{hero.name}}` [*interpolation*](guide/displaying-data#interpolation)
|
||||
displays the component's `hero.name` property value within the `<li>` element.
|
||||
|
||||
* The `[hero]` [*property binding*](guide/template-syntax#property-binding) passes the value of
|
||||
* The `[hero]` [*property binding*](guide/property-binding) passes the value of
|
||||
`selectedHero` from the parent `HeroListComponent` to the `hero` property of the child `HeroDetailComponent`.
|
||||
|
||||
* The `(click)` [*event binding*](guide/user-input#binding-to-user-input-events) calls the component's `selectHero` method when the user clicks a hero's name.
|
||||
|
@ -126,7 +126,7 @@ Angular pipes let you declare display-value transformations in your template HTM
|
|||
|
||||
Angular defines various pipes, such as the [date](https://angular.io/api/common/DatePipe) pipe and [currency](https://angular.io/api/common/CurrencyPipe) pipe; for a complete list, see the [Pipes API list](https://angular.io/api?type=pipe). You can also define new pipes.
|
||||
|
||||
To specify a value transformation in an HTML template, use the [pipe operator (|)](https://angular.io/guide/template-syntax#pipe).
|
||||
To specify a value transformation in an HTML template, use the [pipe operator (|)](https://angular.io/guide/template-expression-operators#pipe).
|
||||
|
||||
`{{interpolated_value | pipe_name}}`
|
||||
|
||||
|
@ -179,9 +179,9 @@ The `ngModel` directive, which implements two-way data binding, is an example of
|
|||
<code-example path="architecture/src/app/hero-detail.component.html" header="src/app/hero-detail.component.html (ngModel)" region="ngModel"></code-example>
|
||||
|
||||
Angular has more pre-defined directives that either alter the layout structure
|
||||
(for example, [ngSwitch](guide/template-syntax#ngSwitch))
|
||||
(for example, [ngSwitch](guide/built-in-directives#ngSwitch))
|
||||
or modify aspects of DOM elements and components
|
||||
(for example, [ngStyle](guide/template-syntax#ngStyle) and [ngClass](guide/template-syntax#ngClass)).
|
||||
(for example, [ngStyle](guide/built-in-directives#ngStyle) and [ngClass](guide/built-in-directives#ngClass)).
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
|
|
|
@ -0,0 +1,303 @@
|
|||
# Attribute, class, and style bindings
|
||||
|
||||
The template syntax provides specialized one-way bindings for scenarios less well-suited to property binding.
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
See the <live-example></live-example> for a working example containing the code snippets in this guide.
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
## Attribute binding
|
||||
|
||||
Set the value of an attribute directly with an **attribute binding**. This is the only exception to the rule that a binding sets a target property and the only binding that creates and sets an attribute.
|
||||
|
||||
Usually, setting an element property with a [property binding](guide/property-binding)
|
||||
is preferable to setting the attribute with a string. However, sometimes
|
||||
there is no element property to bind, so attribute binding is the solution.
|
||||
|
||||
Consider the [ARIA](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA) and
|
||||
[SVG](https://developer.mozilla.org/en-US/docs/Web/SVG). They are purely attributes, don't correspond to element properties, and don't set element properties. In these cases, there are no property targets to bind to.
|
||||
|
||||
Attribute binding syntax resembles property binding, but
|
||||
instead of an element property between brackets, start with the prefix `attr`,
|
||||
followed by a dot (`.`), and the name of the attribute.
|
||||
You then set the attribute value, using an expression that resolves to a string,
|
||||
or remove the attribute when the expression resolves to `null`.
|
||||
|
||||
One of the primary use cases for attribute binding
|
||||
is to set ARIA attributes, as in this example:
|
||||
|
||||
<code-example path="attribute-binding/src/app/app.component.html" region="attrib-binding-aria" header="src/app/app.component.html"></code-example>
|
||||
|
||||
{@a colspan}
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
#### `colspan` and `colSpan`
|
||||
|
||||
Notice the difference between the `colspan` attribute and the `colSpan` property.
|
||||
|
||||
If you wrote something like this:
|
||||
|
||||
<code-example language="html">
|
||||
<tr><td colspan="{{1 + 1}}">Three-Four</td></tr>
|
||||
</code-example>
|
||||
|
||||
You'd get this error:
|
||||
|
||||
<code-example language="bash">
|
||||
Template parse errors:
|
||||
Can't bind to 'colspan' since it isn't a known native property
|
||||
</code-example>
|
||||
|
||||
As the message says, the `<td>` element does not have a `colspan` property. This is true
|
||||
because `colspan` is an attribute—`colSpan`, with a capital `S`, is the
|
||||
corresponding property. Interpolation and property binding can set only *properties*, not attributes.
|
||||
|
||||
Instead, you'd use property binding and write it like this:
|
||||
|
||||
<code-example path="attribute-binding/src/app/app.component.html" region="colSpan" header="src/app/app.component.html"></code-example>
|
||||
|
||||
</div>
|
||||
|
||||
<hr/>
|
||||
|
||||
{@a class-binding}
|
||||
|
||||
## Class binding
|
||||
|
||||
Here's how to set the `class` attribute without a binding in plain HTML:
|
||||
|
||||
```html
|
||||
<!-- standard class attribute setting -->
|
||||
<div class="foo bar">Some text</div>
|
||||
```
|
||||
|
||||
You can also add and remove CSS class names from an element's `class` attribute with a **class binding**.
|
||||
|
||||
To create a single class binding, start with the prefix `class` followed by a dot (`.`) and the name of the CSS class (for example, `[class.foo]="hasFoo"`).
|
||||
Angular adds the class when the bound expression is truthy, and it removes the class when the expression is falsy (with the exception of `undefined`, see [styling delegation](#styling-delegation)).
|
||||
|
||||
To create a binding to multiple classes, use a generic `[class]` binding without the dot (for example, `[class]="classExpr"`).
|
||||
The expression can be a space-delimited string of class names, or you can format it as an object with class names as the keys and truthy/falsy expressions as the values.
|
||||
With object format, Angular will add a class only if its associated value is truthy.
|
||||
|
||||
It's important to note that with any object-like expression (`object`, `Array`, `Map`, `Set`, etc), the identity of the object must change for the class list to be updated.
|
||||
Updating the property without changing object identity will have no effect.
|
||||
|
||||
If there are multiple bindings to the same class name, conflicts are resolved using [styling precedence](#styling-precedence).
|
||||
|
||||
<style>
|
||||
td, th {vertical-align: top}
|
||||
</style>
|
||||
|
||||
<table width="100%">
|
||||
<col width="15%">
|
||||
</col>
|
||||
<col width="20%">
|
||||
</col>
|
||||
<col width="35%">
|
||||
</col>
|
||||
<col width="30%">
|
||||
</col>
|
||||
<tr>
|
||||
<th>
|
||||
Binding Type
|
||||
</th>
|
||||
<th>
|
||||
Syntax
|
||||
</th>
|
||||
<th>
|
||||
Input Type
|
||||
</th>
|
||||
<th>
|
||||
Example Input Values
|
||||
</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Single class binding</td>
|
||||
<td><code>[class.foo]="hasFoo"</code></td>
|
||||
<td><code>boolean | undefined | null</code></td>
|
||||
<td><code>true</code>, <code>false</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td rowspan=3>Multi-class binding</td>
|
||||
<td rowspan=3><code>[class]="classExpr"</code></td>
|
||||
<td><code>string</code></td>
|
||||
<td><code>"my-class-1 my-class-2 my-class-3"</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>{[key: string]: boolean | undefined | null}</code></td>
|
||||
<td><code>{foo: true, bar: false}</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>Array</code><<code>string</code>></td>
|
||||
<td><code>['foo', 'bar']</code></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
|
||||
The [NgClass](guide/built-in-directives/#ngclass) directive can be used as an alternative to direct `[class]` bindings.
|
||||
However, using the above class binding syntax without `NgClass` is preferred because due to improvements in class binding in Angular, `NgClass` no longer provides significant value, and might eventually be removed in the future.
|
||||
|
||||
|
||||
<hr/>
|
||||
|
||||
## Style binding
|
||||
|
||||
Here's how to set the `style` attribute without a binding in plain HTML:
|
||||
|
||||
```html
|
||||
<!-- standard style attribute setting -->
|
||||
<div style="color: blue">Some text</div>
|
||||
```
|
||||
|
||||
You can also set styles dynamically with a **style binding**.
|
||||
|
||||
To create a single style binding, start with the prefix `style` followed by a dot (`.`) and the name of the CSS style property (for example, `[style.width]="width"`).
|
||||
The property will be set to the value of the bound expression, which is normally a string.
|
||||
Optionally, you can add a unit extension like `em` or `%`, which requires a number type.
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
Note that a _style property_ name can be written in either
|
||||
[dash-case](guide/glossary#dash-case), as shown above, or
|
||||
[camelCase](guide/glossary#camelcase), such as `fontSize`.
|
||||
|
||||
</div>
|
||||
|
||||
If there are multiple styles you'd like to toggle, you can bind to the `[style]` property directly without the dot (for example, `[style]="styleExpr"`).
|
||||
The expression attached to the `[style]` binding is most often a string list of styles like `"width: 100px; height: 100px;"`.
|
||||
|
||||
You can also format the expression as an object with style names as the keys and style values as the values, like `{width: '100px', height: '100px'}`.
|
||||
It's important to note that with any object-like expression (`object`, `Array`, `Map`, `Set`, etc), the identity of the object must change for the class list to be updated.
|
||||
Updating the property without changing object identity will have no effect.
|
||||
|
||||
If there are multiple bindings to the same style property, conflicts are resolved using [styling precedence rules](#styling-precedence).
|
||||
|
||||
<style>
|
||||
td, th {vertical-align: top}
|
||||
</style>
|
||||
|
||||
<table width="100%">
|
||||
<col width="15%">
|
||||
</col>
|
||||
<col width="20%">
|
||||
</col>
|
||||
<col width="35%">
|
||||
</col>
|
||||
<col width="30%">
|
||||
</col>
|
||||
<tr>
|
||||
<th>
|
||||
Binding Type
|
||||
</th>
|
||||
<th>
|
||||
Syntax
|
||||
</th>
|
||||
<th>
|
||||
Input Type
|
||||
</th>
|
||||
<th>
|
||||
Example Input Values
|
||||
</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Single style binding</td>
|
||||
<td><code>[style.width]="width"</code></td>
|
||||
<td><code>string | undefined | null</code></td>
|
||||
<td><code>"100px"</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<tr>
|
||||
<td>Single style binding with units</td>
|
||||
<td><code>[style.width.px]="width"</code></td>
|
||||
<td><code>number | undefined | null</code></td>
|
||||
<td><code>100</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td rowspan=3>Multi-style binding</td>
|
||||
<td rowspan=3><code>[style]="styleExpr"</code></td>
|
||||
<td><code>string</code></td>
|
||||
<td><code>"width: 100px; height: 100px"</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>{[key: string]: string | undefined | null}</code></td>
|
||||
<td><code>{width: '100px', height: '100px'}</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>Array</code><<code>string</code>></td>
|
||||
<td><code>['width', '100px']</code></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
The [NgStyle](guide/built-in-directives/#ngstyle) directive can be used as an alternative to direct `[style]` bindings.
|
||||
However, using the above style binding syntax without `NgStyle` is preferred because due to improvements in style binding in Angular, `NgStyle` no longer provides significant value, and might eventually be removed in the future.
|
||||
|
||||
|
||||
<hr/>
|
||||
|
||||
{@a styling-precedence}
|
||||
|
||||
## Styling Precedence
|
||||
|
||||
A single HTML element can have its CSS class list and style values bound to multiple sources (for example, host bindings from multiple directives).
|
||||
|
||||
When there are multiple bindings to the same class name or style property, Angular uses a set of precedence rules to resolve conflicts and determine which classes or styles are ultimately applied to the element.
|
||||
|
||||
<div class="alert is-helpful">
|
||||
<h4>Styling precedence (highest to lowest)</h4>
|
||||
|
||||
1. Template bindings
|
||||
1. Property binding (for example, `<div [class.foo]="hasFoo">` or `<div [style.color]="color">`)
|
||||
1. Map binding (for example, `<div [class]="classExpr">` or `<div [style]="styleExpr">`)
|
||||
1. Static value (for example, `<div class="foo">` or `<div style="color: blue">`)
|
||||
1. Directive host bindings
|
||||
1. Property binding (for example, `host: {'[class.foo]': 'hasFoo'}` or `host: {'[style.color]': 'color'}`)
|
||||
1. Map binding (for example, `host: {'[class]': 'classExpr'}` or `host: {'[style]': 'styleExpr'}`)
|
||||
1. Static value (for example, `host: {'class': 'foo'}` or `host: {'style': 'color: blue'}`)
|
||||
1. Component host bindings
|
||||
1. Property binding (for example, `host: {'[class.foo]': 'hasFoo'}` or `host: {'[style.color]': 'color'}`)
|
||||
1. Map binding (for example, `host: {'[class]': 'classExpr'}` or `host: {'[style]': 'styleExpr'}`)
|
||||
1. Static value (for example, `host: {'class': 'foo'}` or `host: {'style': 'color: blue'}`)
|
||||
|
||||
</div>
|
||||
|
||||
The more specific a class or style binding is, the higher its precedence.
|
||||
|
||||
A binding to a specific class (for example, `[class.foo]`) will take precedence over a generic `[class]` binding, and a binding to a specific style (for example, `[style.bar]`) will take precedence over a generic `[style]` binding.
|
||||
|
||||
<code-example path="attribute-binding/src/app/app.component.html" region="basic-specificity" header="src/app/app.component.html"></code-example>
|
||||
|
||||
Specificity rules also apply when it comes to bindings that originate from different sources.
|
||||
It's possible for an element to have bindings in the template where it's declared, from host bindings on matched directives, and from host bindings on matched components.
|
||||
|
||||
Template bindings are the most specific because they apply to the element directly and exclusively, so they have the highest precedence.
|
||||
|
||||
Directive host bindings are considered less specific because directives can be used in multiple locations, so they have a lower precedence than template bindings.
|
||||
|
||||
Directives often augment component behavior, so host bindings from components have the lowest precedence.
|
||||
|
||||
<code-example path="attribute-binding/src/app/app.component.html" region="source-specificity" header="src/app/app.component.html"></code-example>
|
||||
|
||||
In addition, bindings take precedence over static attributes.
|
||||
|
||||
In the following case, `class` and `[class]` have similar specificity, but the `[class]` binding will take precedence because it is dynamic.
|
||||
|
||||
<code-example path="attribute-binding/src/app/app.component.html" region="dynamic-priority" header="src/app/app.component.html"></code-example>
|
||||
|
||||
{@a styling-delegation}
|
||||
### Delegating to styles with lower precedence
|
||||
|
||||
It is possible for higher precedence styles to "delegate" to lower precedence styles using `undefined` values.
|
||||
Whereas setting a style property to `null` ensures the style is removed, setting it to `undefined` will cause Angular to fall back to the next-highest precedence binding to that style.
|
||||
|
||||
For example, consider the following template:
|
||||
|
||||
<code-example path="attribute-binding/src/app/app.component.html" region="style-delegation" header="src/app/app.component.html"></code-example>
|
||||
|
||||
Imagine that the `dirWithHostBinding` directive and the `comp-with-host-binding` component both have a `[style.width]` host binding.
|
||||
In that case, if `dirWithHostBinding` sets its binding to `undefined`, the `width` property will fall back to the value of the `comp-with-host-binding` host binding.
|
||||
However, if `dirWithHostBinding` sets its binding to `null`, the `width` property will be removed entirely.
|
|
@ -18,12 +18,12 @@ There are three kinds of directives in Angular:
|
|||
You saw a component for the first time in the [Getting Started](start "Getting Started with Angular") tutorial.
|
||||
|
||||
*Structural Directives* change the structure of the view.
|
||||
Two examples are [NgFor](guide/template-syntax#ngFor) and [NgIf](guide/template-syntax#ngIf).
|
||||
Two examples are [NgFor](guide/built-in-directives#ngFor) and [NgIf](guide/built-in-directives#ngIf).
|
||||
Learn about them in the [Structural Directives](guide/structural-directives) guide.
|
||||
|
||||
*Attribute directives* are used as attributes of elements.
|
||||
The built-in [NgStyle](guide/template-syntax#ngStyle) directive in the
|
||||
[Template Syntax](guide/template-syntax) guide, for example,
|
||||
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.
|
||||
|
||||
## Build a simple attribute directive
|
||||
|
|
|
@ -0,0 +1,318 @@
|
|||
|
||||
# Binding syntax: an overview
|
||||
|
||||
Data-binding is a mechanism for coordinating what users see, specifically
|
||||
with application data values.
|
||||
While you could push values to and pull values from HTML,
|
||||
the application is easier to write, read, and maintain if you turn these tasks over to a binding framework.
|
||||
You simply declare bindings between binding sources, target HTML elements, and let the framework do the rest.
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
See the <live-example></live-example> for a working example containing the code snippets in this guide.
|
||||
|
||||
</div>
|
||||
|
||||
Angular provides many kinds of data-binding. Binding types can be grouped into three categories distinguished by the direction of data flow:
|
||||
|
||||
* From the _source-to-view_
|
||||
* From _view-to-source_
|
||||
* Two-way sequence: _view-to-source-to-view_
|
||||
|
||||
<style>
|
||||
td, th {vertical-align: top}
|
||||
</style>
|
||||
|
||||
<table width="100%">
|
||||
<col width="30%">
|
||||
</col>
|
||||
<col width="50%">
|
||||
</col>
|
||||
<col width="20%">
|
||||
</col>
|
||||
<tr>
|
||||
<th>
|
||||
Type
|
||||
</th>
|
||||
<th>
|
||||
Syntax
|
||||
</th>
|
||||
<th>
|
||||
Category
|
||||
</th>
|
||||
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
Interpolation<br>
|
||||
Property<br>
|
||||
Attribute<br>
|
||||
Class<br>
|
||||
Style
|
||||
</td>
|
||||
<td>
|
||||
|
||||
<code-example>
|
||||
{{expression}}
|
||||
[target]="expression"
|
||||
bind-target="expression"
|
||||
</code-example>
|
||||
|
||||
</td>
|
||||
|
||||
<td>
|
||||
One-way<br>from data source<br>to view target
|
||||
</td>
|
||||
<tr>
|
||||
<td>
|
||||
Event
|
||||
</td>
|
||||
<td>
|
||||
<code-example>
|
||||
(target)="statement"
|
||||
on-target="statement"
|
||||
</code-example>
|
||||
</td>
|
||||
|
||||
<td>
|
||||
One-way<br>from view target<br>to data source
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
Two-way
|
||||
</td>
|
||||
<td>
|
||||
<code-example>
|
||||
[(target)]="expression"
|
||||
bindon-target="expression"
|
||||
</code-example>
|
||||
</td>
|
||||
<td>
|
||||
Two-way
|
||||
</td>
|
||||
</tr>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
Binding types other than interpolation have a **target name** to the left of the equal sign, either surrounded by punctuation, `[]` or `()`,
|
||||
or preceded by a prefix: `bind-`, `on-`, `bindon-`.
|
||||
|
||||
The *target* of a binding is the property or event inside the binding punctuation: `[]`, `()` or `[()]`.
|
||||
|
||||
Every public member of a **source** directive is automatically available for binding.
|
||||
You don't have to do anything special to access a directive member in a template expression or statement.
|
||||
|
||||
|
||||
### Data-binding and HTML
|
||||
|
||||
In the normal course of HTML development, you create a visual structure with HTML elements, and
|
||||
you modify those elements by setting element attributes with string constants.
|
||||
|
||||
```html
|
||||
<div class="special">Plain old HTML</div>
|
||||
<img src="images/item.png">
|
||||
<button disabled>Save</button>
|
||||
```
|
||||
|
||||
With data-binding, you can control things like the state of a button:
|
||||
|
||||
<code-example path="binding-syntax/src/app/app.component.html" region="disabled-button" header="src/app/app.component.html"></code-example>
|
||||
|
||||
Notice that the binding is to the `disabled` property of the button's DOM element,
|
||||
**not** the attribute. This applies to data-binding in general. Data-binding works with *properties* of DOM elements, components, and directives, not HTML *attributes*.
|
||||
|
||||
{@a html-attribute-vs-dom-property}
|
||||
|
||||
### HTML attribute vs. DOM property
|
||||
|
||||
The distinction between an HTML attribute and a DOM property is key to understanding
|
||||
how Angular binding works. **Attributes are defined by HTML. Properties are accessed from DOM (Document Object Model) nodes.**
|
||||
|
||||
* A few HTML attributes have 1:1 mapping to properties; for example, `id`.
|
||||
|
||||
* Some HTML attributes don't have corresponding properties; for example, `aria-*`.
|
||||
|
||||
* Some DOM properties don't have corresponding attributes; for example, `textContent`.
|
||||
|
||||
It is important to remember that *HTML attribute* and the *DOM property* are different things, even when they have the same name.
|
||||
In Angular, the only role of HTML attributes is to initialize element and directive state.
|
||||
|
||||
**Template binding works with *properties* and *events*, not *attributes*.**
|
||||
|
||||
When you write a data-binding, you're dealing exclusively with the *DOM properties* and *events* of the target object.
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
This general rule can help you build a mental model of attributes and DOM properties:
|
||||
**Attributes initialize DOM properties and then they are done.
|
||||
Property values can change; attribute values can't.**
|
||||
|
||||
There is one exception to this rule.
|
||||
Attributes can be changed by `setAttribute()`, which re-initializes corresponding DOM properties.
|
||||
|
||||
</div>
|
||||
|
||||
For more information, see the [MDN Interfaces documentation](https://developer.mozilla.org/en-US/docs/Web/API#Interfaces) which has API docs for all the standard DOM elements and their properties.
|
||||
Comparing the [`<td>` attributes](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/td) attributes to the [`<td>` properties](https://developer.mozilla.org/en-US/docs/Web/API/HTMLTableCellElement) provides a helpful example for differentiation.
|
||||
In particular, you can navigate from the attributes page to the properties via "DOM interface" link, and navigate the inheritance hierarchy up to `HTMLTableCellElement`.
|
||||
|
||||
|
||||
#### Example 1: an `<input>`
|
||||
|
||||
When the browser renders `<input type="text" value="Sarah">`, it creates a
|
||||
corresponding DOM node with a `value` property initialized to "Sarah".
|
||||
|
||||
```html
|
||||
<input type="text" value="Sarah">
|
||||
```
|
||||
|
||||
When the user enters "Sally" into the `<input>`, the DOM element `value` *property* becomes "Sally".
|
||||
However, if you look at the HTML attribute `value` using `input.getAttribute('value')`, you can see that the *attribute* remains unchanged—it returns "Sarah".
|
||||
|
||||
The HTML attribute `value` specifies the *initial* value; the DOM `value` property is the *current* value.
|
||||
|
||||
To see attributes versus DOM properties in a functioning app, see the <live-example name="binding-syntax"></live-example> especially for binding syntax.
|
||||
|
||||
#### Example 2: a disabled button
|
||||
|
||||
The `disabled` attribute is another example. A button's `disabled`
|
||||
*property* is `false` by default so the button is enabled.
|
||||
|
||||
When you add the `disabled` *attribute*, its presence alone
|
||||
initializes the button's `disabled` *property* to `true`
|
||||
so the button is disabled.
|
||||
|
||||
```html
|
||||
<button disabled>Test Button</button>
|
||||
```
|
||||
|
||||
Adding and removing the `disabled` *attribute* disables and enables the button.
|
||||
However, the value of the *attribute* is irrelevant,
|
||||
which is why you cannot enable a button by writing `<button disabled="false">Still Disabled</button>`.
|
||||
|
||||
To control the state of the button, set the `disabled` *property*,
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
Though you could technically set the `[attr.disabled]` attribute binding, the values are different in that the property binding requires to a boolean value, while its corresponding attribute binding relies on whether the value is `null` or not. Consider the following:
|
||||
|
||||
```html
|
||||
<input [disabled]="condition ? true : false">
|
||||
<input [attr.disabled]="condition ? 'disabled' : null">
|
||||
```
|
||||
|
||||
Generally, use property binding over attribute binding as it is more intuitive (being a boolean value), has a shorter syntax, and is more performant.
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
To see the `disabled` button example in a functioning app, see the <live-example name="binding-syntax"></live-example> especially for binding syntax. This example shows you how to toggle the disabled property from the component.
|
||||
|
||||
## Binding types and targets
|
||||
|
||||
The **target of a data-binding** is something in the DOM.
|
||||
Depending on the binding type, the target can be a property (element, component, or directive),
|
||||
an event (element, component, or directive), or sometimes an attribute name.
|
||||
The following table summarizes the targets for the different binding types.
|
||||
|
||||
<style>
|
||||
td, th {vertical-align: top}
|
||||
</style>
|
||||
|
||||
<table width="100%">
|
||||
<col width="10%">
|
||||
</col>
|
||||
<col width="15%">
|
||||
</col>
|
||||
<col width="75%">
|
||||
</col>
|
||||
<tr>
|
||||
<th>
|
||||
Type
|
||||
</th>
|
||||
<th>
|
||||
Target
|
||||
</th>
|
||||
<th>
|
||||
Examples
|
||||
</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
Property
|
||||
</td>
|
||||
<td>
|
||||
Element property<br>
|
||||
Component property<br>
|
||||
Directive property
|
||||
</td>
|
||||
<td>
|
||||
<code>src</code>, <code>hero</code>, and <code>ngClass</code> in the following:
|
||||
<code-example path="template-syntax/src/app/app.component.html" region="property-binding-syntax-1"></code-example>
|
||||
<!-- For more information, see [Property Binding](guide/property-binding). -->
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
Event
|
||||
</td>
|
||||
<td>
|
||||
Element event<br>
|
||||
Component event<br>
|
||||
Directive event
|
||||
</td>
|
||||
<td>
|
||||
<code>click</code>, <code>deleteRequest</code>, and <code>myClick</code> in the following:
|
||||
<code-example path="template-syntax/src/app/app.component.html" region="event-binding-syntax-1"></code-example>
|
||||
<!-- KW--Why don't these links work in the table? -->
|
||||
<!-- <div>For more information, see [Event Binding](guide/event-binding).</div> -->
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
Two-way
|
||||
</td>
|
||||
<td>
|
||||
Event and property
|
||||
</td>
|
||||
<td>
|
||||
<code-example path="template-syntax/src/app/app.component.html" region="2-way-binding-syntax-1"></code-example>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
Attribute
|
||||
</td>
|
||||
<td>
|
||||
Attribute
|
||||
(the exception)
|
||||
</td>
|
||||
<td>
|
||||
<code-example path="template-syntax/src/app/app.component.html" region="attribute-binding-syntax-1"></code-example>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
Class
|
||||
</td>
|
||||
<td>
|
||||
<code>class</code> property
|
||||
</td>
|
||||
<td>
|
||||
<code-example path="template-syntax/src/app/app.component.html" region="class-binding-syntax-1"></code-example>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
Style
|
||||
</td>
|
||||
<td>
|
||||
<code>style</code> property
|
||||
</td>
|
||||
<td>
|
||||
<code-example path="template-syntax/src/app/app.component.html" region="style-binding-syntax-1"></code-example>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
|
@ -0,0 +1,435 @@
|
|||
# Built-in directives
|
||||
|
||||
Angular offers two kinds of built-in directives: [_attribute_ directives](guide/attribute-directives) and [_structural_ directives](guide/structural-directives).
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
See the <live-example></live-example> for a working example containing the code snippets in this guide.
|
||||
|
||||
</div>
|
||||
|
||||
For more detail, including how to build your own custom directives, see [Attribute Directives](guide/attribute-directives) and [Structural Directives](guide/structural-directives).
|
||||
|
||||
<hr/>
|
||||
|
||||
{@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.
|
||||
|
||||
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.
|
||||
* [`NgModel`](guide/built-in-directives#ngModel)—adds two-way data binding to an HTML form element.
|
||||
|
||||
<hr/>
|
||||
|
||||
{@a ngClass}
|
||||
|
||||
## `NgClass`
|
||||
|
||||
Add or remove several CSS classes simultaneously with `ngClass`.
|
||||
|
||||
<code-example path="built-in-directives/src/app/app.component.html" region="special-div" header="src/app/app.component.html"></code-example>
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
To add or remove a *single* class, use [class binding](guide/attribute-binding#class-binding) rather than `NgClass`.
|
||||
|
||||
</div>
|
||||
|
||||
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.
|
||||
|
||||
<code-example path="built-in-directives/src/app/app.component.ts" region="setClasses" header="src/app/app.component.ts"></code-example>
|
||||
|
||||
Adding an `ngClass` property binding to `currentClasses` sets the element's classes accordingly:
|
||||
|
||||
<code-example path="built-in-directives/src/app/app.component.html" region="NgClass-1" header="src/app/app.component.html"></code-example>
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
Remember that in this situation you'd call `setCurrentClasses()`,
|
||||
both initially and when the dependent properties change.
|
||||
|
||||
</div>
|
||||
|
||||
<hr/>
|
||||
|
||||
{@a ngStyle}
|
||||
|
||||
## `NgStyle`
|
||||
|
||||
Use `NgStyle` to set many inline styles simultaneously and dynamically, based on the state of the component.
|
||||
|
||||
### Without `NgStyle`
|
||||
|
||||
For context, consider setting a *single* style value with [style binding](guide/attribute-binding#style-binding), without `NgStyle`.
|
||||
|
||||
<code-example path="built-in-directives/src/app/app.component.html" region="without-ng-style" header="src/app/app.component.html"></code-example>
|
||||
|
||||
However, to set *many* inline styles at the same time, use the `NgStyle` directive.
|
||||
|
||||
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:
|
||||
|
||||
<code-example path="built-in-directives/src/app/app.component.ts" region="setStyles" header="src/app/app.component.ts"></code-example>
|
||||
|
||||
Adding an `ngStyle` property binding to `currentStyles` sets the element's styles accordingly:
|
||||
|
||||
<code-example path="built-in-directives/src/app/app.component.html" region="NgStyle-2" header="src/app/app.component.html"></code-example>
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
Remember to call `setCurrentStyles()`, both initially and when the dependent properties change.
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
<hr/>
|
||||
|
||||
{@a ngModel}
|
||||
|
||||
## `[(ngModel)]`: Two-way binding
|
||||
|
||||
The `NgModel` directive allows you to display a data property and
|
||||
update that property when the user makes changes. Here's an example:
|
||||
|
||||
<code-example path="built-in-directives/src/app/app.component.html" header="src/app/app.component.html (NgModel example)" region="NgModel-1"></code-example>
|
||||
|
||||
|
||||
### 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 [Forms](guide/forms#ngModel).
|
||||
|
||||
Remember to import the `FormsModule` to make `[(ngModel)]` available as follows:
|
||||
|
||||
<code-example path="built-in-directives/src/app/app.module.ts" header="src/app/app.module.ts (FormsModule import)" region="import-forms-module"></code-example>
|
||||
|
||||
|
||||
You could achieve the same result with separate bindings to
|
||||
the `<input>` element's `value` property and `input` event:
|
||||
|
||||
<code-example path="built-in-directives/src/app/app.component.html" region="without-NgModel" header="src/app/app.component.html"></code-example>
|
||||
|
||||
To streamline the syntax, the `ngModel` directive hides the details behind its own `ngModel` input and `ngModelChange` output properties:
|
||||
|
||||
<code-example path="built-in-directives/src/app/app.component.html" region="NgModelChange" header="src/app/app.component.html"></code-example>
|
||||
|
||||
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](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/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:
|
||||
|
||||
<code-example path="built-in-directives/src/app/app.component.html" region="NgModel-1" header="src/app/app.component.html"></code-example>
|
||||
|
||||
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 `<input>` value to uppercase:
|
||||
|
||||
<code-example path="built-in-directives/src/app/app.component.html" region="uppercase" header="src/app/app.component.html"></code-example>
|
||||
|
||||
Here are all variations in action, including the uppercase version:
|
||||
|
||||
<div class="lightbox">
|
||||
<img src='generated/images/guide/built-in-directives/ng-model-anim.gif' alt="NgModel variations">
|
||||
</div>
|
||||
|
||||
<hr/>
|
||||
|
||||
{@a 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.
|
||||
|
||||
This section is an introduction to the common built-in structural directives:
|
||||
|
||||
* [`NgIf`](guide/built-in-directives#ngIf)—conditionally creates or destroys 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.
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
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 [`<ng-container>`](guide/structural-directives#ngcontainer "<ng-container>")
|
||||
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.
|
||||
|
||||
</div>
|
||||
|
||||
<hr/>
|
||||
|
||||
{@a ngIf}
|
||||
|
||||
## 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.
|
||||
|
||||
<code-example path="built-in-directives/src/app/app.component.html" region="NgIf-1" header="src/app/app.component.html"></code-example>
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
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).
|
||||
|
||||
</div>
|
||||
|
||||
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 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.
|
||||
|
||||
<code-example path="built-in-directives/src/app/app.component.html" region="NgIf-3" header="src/app/app.component.html"></code-example>
|
||||
|
||||
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.
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
For more information on `NgIf` and `ngIfElse`, see the [API documentation about NgIf](api/common/NgIf).
|
||||
|
||||
</div>
|
||||
|
||||
### 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 `<div>`s.
|
||||
The `currentCustomer` name appears only when there is a `currentCustomer`.
|
||||
The `nullCustomer` will not be displayed as long as it is `null`.
|
||||
|
||||
<code-example path="built-in-directives/src/app/app.component.html" region="NgIf-2" header="src/app/app.component.html"></code-example>
|
||||
|
||||
<code-example path="built-in-directives/src/app/app.component.html" region="NgIf-2b" header="src/app/app.component.html"></code-example>
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
See also the
|
||||
[safe navigation operator](guide/template-expression-operators#safe-navigation-operator "Safe navigation operator (?.)") below.
|
||||
|
||||
</div>
|
||||
<hr/>
|
||||
|
||||
{@a ngFor}
|
||||
## `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.
|
||||
|
||||
The following example shows `NgFor` applied to a simple `<div>`. (Don't forget the asterisk (`*`) in front of `ngFor`.)
|
||||
|
||||
<code-example path="built-in-directives/src/app/app.component.html" region="NgFor-1" header="src/app/app.component.html"></code-example>
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
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).
|
||||
|
||||
</div>
|
||||
|
||||
You can also apply an `NgFor` to a component element, as in the following example.
|
||||
|
||||
<code-example path="built-in-directives/src/app/app.component.html" region="NgFor-2" header="src/app/app.component.html"></code-example>
|
||||
|
||||
{@a microsyntax}
|
||||
|
||||
<div class="callout is-critical">
|
||||
<header>*ngFor microsyntax</header>
|
||||
|
||||
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 `<ng-template>` 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.
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
{@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 `<app-item-detail>` component.
|
||||
|
||||
<code-example path="built-in-directives/src/app/app.component.html" region="NgFor-1-2" header="src/app/app.component.html"></code-example>
|
||||
|
||||
For more information about template input variables, see
|
||||
[Structural Directives](guide/structural-directives#template-input-variable).
|
||||
|
||||
### `*ngFor` with `index`
|
||||
|
||||
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 item name.
|
||||
|
||||
<code-example path="built-in-directives/src/app/app.component.html" region="NgFor-3" header="src/app/app.component.html"></code-example>
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
`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).
|
||||
|
||||
</div>
|
||||
|
||||
{@a 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.
|
||||
|
||||
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`.
|
||||
|
||||
<code-example path="built-in-directives/src/app/app.component.ts" region="trackByItems" header="src/app/app.component.ts"></code-example>
|
||||
|
||||
In the microsyntax expression, set `trackBy` to the `trackByItems()` method.
|
||||
|
||||
<code-example path="built-in-directives/src/app/app.component.html" region="trackBy" header="src/app/app.component.html"></code-example>
|
||||
|
||||
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.
|
||||
|
||||
<div class="lightbox">
|
||||
<img src="generated/images/guide/built-in-directives/ngfor-trackby.gif" alt="Animation of trackBy">
|
||||
</div>
|
||||
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
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.
|
||||
|
||||
</div>
|
||||
|
||||
<hr/>
|
||||
|
||||
{@a ngSwitch}
|
||||
## 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.
|
||||
<!-- API Flagged -->
|
||||
`NgSwitch` is actually a set of three, cooperating directives:
|
||||
`NgSwitch`, `NgSwitchCase`, and `NgSwitchDefault` as in the following example.
|
||||
|
||||
<code-example path="built-in-directives/src/app/app.component.html" region="NgSwitch" header="src/app/app.component.html"></code-example>
|
||||
|
||||
<div class="lightbox">
|
||||
<img src="generated/images/guide/built-in-directives/ngswitch.gif" alt="Animation of NgSwitch">
|
||||
</div>
|
||||
|
||||
`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.
|
||||
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 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 `item` components defined in the `item-switch.components.ts` file.
|
||||
Each component has an `item` [input property](guide/inputs-outputs#input "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 `<app-best-item>` switch case with the following.
|
||||
|
||||
<code-example path="built-in-directives/src/app/app.component.html" region="NgSwitch-div" header="src/app/app.component.html"></code-example>
|
|
@ -25,7 +25,7 @@ in which two or more components share information.
|
|||
## Pass data from parent to child with input binding
|
||||
|
||||
`HeroChildComponent` has two ***input properties***,
|
||||
typically adorned with [@Input decorations](guide/template-syntax#inputs-outputs).
|
||||
typically adorned with [@Input() decorator](guide/inputs-outputs#input).
|
||||
|
||||
|
||||
<code-example path="component-interaction/src/app/hero-child.component.ts" header="component-interaction/src/app/hero-child.component.ts">
|
||||
|
@ -180,7 +180,7 @@ The child component exposes an `EventEmitter` property with which it `emits` eve
|
|||
The parent binds to that event property and reacts to those events.
|
||||
|
||||
The child's `EventEmitter` property is an ***output property***,
|
||||
typically adorned with an [@Output decoration](guide/template-syntax#inputs-outputs)
|
||||
typically adorned with an [@Output() decorator](guide/inputs-outputs#output)
|
||||
as seen in this `VoterComponent`:
|
||||
|
||||
|
||||
|
|
|
@ -153,14 +153,14 @@ It marks that `<li>` element (and its children) as the "repeater template":
|
|||
<div class="alert is-important">
|
||||
|
||||
Don't forget the leading asterisk (\*) in `*ngFor`. It is an essential part of the syntax.
|
||||
Read more about `ngFor` and `*` in the [ngFor section](guide/template-syntax#ngfor) of the [Template Syntax](guide/template-syntax) page.
|
||||
Read more about `ngFor` and `*` in the [ngFor section](guide/built-in-directives#ngfor) of the [Built-in directives](guide/built-in-directives) page.
|
||||
|
||||
</div>
|
||||
|
||||
Notice the `hero` in the `ngFor` double-quoted instruction;
|
||||
it is an example of a template input variable. Read
|
||||
more about template input variables in the [microsyntax](guide/template-syntax#microsyntax) section of
|
||||
the [Template Syntax](guide/template-syntax) page.
|
||||
more about template input variables in the [microsyntax](guide/built-in-directives#microsyntax) section of
|
||||
the [Built-in directives](guide/built-in-directives) page.
|
||||
|
||||
Angular duplicates the `<li>` for each item in the list, setting the `hero` variable
|
||||
to the item (the hero) in the current iteration. Angular uses that variable as the
|
||||
|
@ -255,7 +255,7 @@ To see it in action, add the following paragraph at the bottom of the template:
|
|||
<div class="alert is-important">
|
||||
|
||||
Don't forget the leading asterisk (\*) in `*ngIf`. It is an essential part of the syntax.
|
||||
Read more about `ngIf` and `*` in the [ngIf section](guide/template-syntax#ngIf) of the [Template Syntax](guide/template-syntax) page.
|
||||
Read more about `ngIf` and `*` in the [ngIf section](guide/built-in-directives#ngIf) of the [Built-in directives](guide/built-in-directives) page.
|
||||
|
||||
</div>
|
||||
|
||||
|
@ -266,7 +266,7 @@ When the component's list of heroes has more than three items, Angular adds the
|
|||
to the DOM and the message appears.
|
||||
If there are three or fewer items, Angular omits the paragraph, so no message appears.
|
||||
|
||||
For more information, see [template expressions](guide/template-syntax#template-expressions).
|
||||
For more information, see [template expression operators](guide/interpolation#template-expressions).
|
||||
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
|
|
@ -0,0 +1,108 @@
|
|||
# Event binding `(event)`
|
||||
|
||||
Event binding allows you to listen for certain events such as
|
||||
keystrokes, mouse movements, clicks, and touches.
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
See the <live-example></live-example> for a working example containing the code snippets in this guide.
|
||||
|
||||
</div>
|
||||
|
||||
Angular event binding syntax consists of a **target event** name
|
||||
within parentheses on the left of an equal sign, and a quoted
|
||||
template statement on the right.
|
||||
The following event binding listens for the button's click events, calling
|
||||
the component's `onSave()` method whenever a click occurs:
|
||||
|
||||
<div class="lightbox">
|
||||
<img src='generated/images/guide/template-syntax/syntax-diagram.svg' alt="Syntax diagram">
|
||||
</div>
|
||||
|
||||
## Target event
|
||||
|
||||
As above, the target is the button's click event.
|
||||
|
||||
<code-example path="event-binding/src/app/app.component.html" region="event-binding-1" header="src/app/app.component.html"></code-example>
|
||||
|
||||
Alternatively, use the `on-` prefix, known as the canonical form:
|
||||
|
||||
<code-example path="event-binding/src/app/app.component.html" region="event-binding-2" header="src/app/app.component.html"></code-example>
|
||||
|
||||
Element events may be the more common targets, but Angular looks first to see if the name matches an event property
|
||||
of a known directive, as it does in the following example:
|
||||
|
||||
<code-example path="event-binding/src/app/app.component.html" region="custom-directive" header="src/app/app.component.html"></code-example>
|
||||
|
||||
If the name fails to match an element event or an output property of a known directive,
|
||||
Angular reports an “unknown directive” error.
|
||||
|
||||
## *$event* and event handling statements
|
||||
|
||||
In an event binding, Angular sets up an event handler for the target event.
|
||||
|
||||
When the event is raised, the handler executes the template statement.
|
||||
The template statement typically involves a receiver, which performs an action
|
||||
in response to the event, such as storing a value from the HTML control
|
||||
into a model.
|
||||
|
||||
The binding conveys information about the event. This information can include data values such as an event object, string, or number named `$event`.
|
||||
|
||||
The target event determines the shape of the `$event` object.
|
||||
If the target event is a native DOM element event, then `$event` is a
|
||||
[DOM event object](https://developer.mozilla.org/en-US/docs/Web/Events),
|
||||
with properties such as `target` and `target.value`.
|
||||
|
||||
Consider this example:
|
||||
|
||||
<code-example path="event-binding/src/app/app.component.html" region="event-binding-3" header="src/app/app.component.html"></code-example>
|
||||
|
||||
This code sets the `<input>` `value` property by binding to the `name` property.
|
||||
To listen for changes to the value, the code binds to the `input`
|
||||
event of the `<input>` element.
|
||||
When the user makes changes, the `input` event is raised, and the binding executes
|
||||
the statement within a context that includes the DOM event object, `$event`.
|
||||
|
||||
To update the `name` property, the changed text is retrieved by following the path `$event.target.value`.
|
||||
|
||||
If the event belongs to a directive—recall that components
|
||||
are directives—`$event` has whatever shape the directive produces.
|
||||
|
||||
## Custom events with `EventEmitter`
|
||||
|
||||
Directives typically raise custom events with an Angular [EventEmitter](api/core/EventEmitter).
|
||||
The directive creates an `EventEmitter` and exposes it as a property.
|
||||
The directive calls `EventEmitter.emit(payload)` to fire an event, passing in a message payload, which can be anything.
|
||||
Parent directives listen for the event by binding to this property and accessing the payload through the `$event` object.
|
||||
|
||||
Consider an `ItemDetailComponent` that presents item information and responds to user actions.
|
||||
Although the `ItemDetailComponent` has a delete button, it doesn't know how to delete the hero. It can only raise an event reporting the user's delete request.
|
||||
|
||||
Here are the pertinent excerpts from that `ItemDetailComponent`:
|
||||
|
||||
<code-example path="event-binding/src/app/item-detail/item-detail.component.html" header="src/app/item-detail/item-detail.component.html (template)" region="line-through"></code-example>
|
||||
|
||||
<code-example path="event-binding/src/app/item-detail/item-detail.component.ts" header="src/app/item-detail/item-detail.component.ts (deleteRequest)" region="deleteRequest"></code-example>
|
||||
|
||||
The component defines a `deleteRequest` property that returns an `EventEmitter`.
|
||||
When the user clicks *delete*, the component invokes the `delete()` method,
|
||||
telling the `EventEmitter` to emit an `Item` object.
|
||||
|
||||
Now imagine a hosting parent component that binds to the `deleteRequest` event
|
||||
of the `ItemDetailComponent`.
|
||||
|
||||
<code-example path="event-binding/src/app/app.component.html" header="src/app/app.component.html (event-binding-to-component)" region="event-binding-to-component"></code-example>
|
||||
|
||||
When the `deleteRequest` event fires, Angular calls the parent component's
|
||||
`deleteItem()` method, passing the *item-to-delete* (emitted by `ItemDetail`)
|
||||
in the `$event` variable.
|
||||
|
||||
## Template statements have side effects
|
||||
|
||||
Though [template expressions](guide/interpolation#template-expressions) shouldn't have [side effects](guide/property-binding#avoid-side-effects), template
|
||||
statements usually do. The `deleteItem()` method does have
|
||||
a side effect: it deletes an item.
|
||||
|
||||
Deleting an item updates the model, and depending on your code, triggers
|
||||
other changes including queries and saving to a remote server.
|
||||
These changes propagate through the system and ultimately display in this and other views.
|
|
@ -36,7 +36,7 @@ This tutorial teaches you how to do the following:
|
|||
* Use `ngModel` to create two-way data bindings for reading and writing input-control values.
|
||||
* Provide visual feedback using special CSS classes that track the state of the controls.
|
||||
* Display validation errors to users and enable or disable form controls based on the form status.
|
||||
* Share information across HTML elements using [template reference variables](guide/template-syntax#template-reference-variables-var).
|
||||
* Share information across HTML elements using [template reference variables](guide/template-reference-variables).
|
||||
|
||||
## Prerequisites
|
||||
|
||||
|
@ -184,7 +184,7 @@ The note reminds you to remove the diagnostic lines when you have finished obser
|
|||
|
||||
When you imported the `FormsModule` in your component, Angular automatically created and attached an [NgForm](api/forms/NgForm "API reference for NgForm") directive to the `<form>` tag in the template (because `NgForm` has the selector `form` that matches `<form>` elements).
|
||||
|
||||
To get access to the `NgForm` and the overall form status, declare a [template reference variable](guide/template-syntax#template-reference-variables-var).
|
||||
To get access to the `NgForm` and the overall form status, declare a [template reference variable](guide/template-reference-variables).
|
||||
|
||||
1. Edit the template file `hero-form.component.html`.
|
||||
|
||||
|
|
|
@ -252,15 +252,15 @@ Data binding is an alternative to manually pushing application data values into
|
|||
event listeners, pulling changed values from the screen, and
|
||||
updating application data values.
|
||||
|
||||
Read about the following forms of binding in [Template Syntax](guide/template-syntax):
|
||||
Read about the following forms of binding in Angular's [Template Syntax](guide/template-syntax):
|
||||
|
||||
* [Interpolation](guide/template-syntax#interpolation)
|
||||
* [Property binding](guide/template-syntax#property-binding)
|
||||
* [Event binding](guide/template-syntax#event-binding)
|
||||
* [Attribute binding](guide/template-syntax#attribute-binding)
|
||||
* [Class binding](guide/template-syntax#class-binding)
|
||||
* [Style binding](guide/template-syntax#style-binding)
|
||||
* [Two-way data binding with ngModel](guide/template-syntax#ngModel)
|
||||
* [Interpolation](guide/interpolation)
|
||||
* [Property binding](guide/property-binding)
|
||||
* [Event binding](guide/event-binding)
|
||||
* [Attribute binding](guide/attribute-binding)
|
||||
* [Class binding](guide/attribute-binding#class-binding)
|
||||
* [Style binding](guide/attribute-binding#style-binding)
|
||||
* [Two-way data binding with ngModel](guide/built-in-directives#ngModel)
|
||||
|
||||
{@a declarable}
|
||||
|
||||
|
@ -472,11 +472,11 @@ Learn more about the injector hierarchy in [Hierarchical Dependency Injectors](g
|
|||
## input
|
||||
|
||||
When defining a [directive](#directive), the `@Input()` decorator on a directive property
|
||||
makes that property available as a *target* of a [property binding](guide/template-syntax#property-binding).
|
||||
makes that property available as a *target* of a [property binding](guide/property-binding).
|
||||
Data values flow into an input property from the data source identified
|
||||
in the [template expression](#template-expression) to the right of the equal sign.
|
||||
|
||||
To learn more, see [input and output properties](guide/template-syntax#inputs-outputs).
|
||||
To learn more, see [input and output properties](guide/inputs-outputs).
|
||||
|
||||
{@a interpolation}
|
||||
|
||||
|
@ -491,7 +491,7 @@ or displayed between element tags, as in this example.
|
|||
```
|
||||
|
||||
|
||||
Read more about [interpolation](guide/template-syntax#interpolation) in [Template Syntax](guide/template-syntax).
|
||||
Read more in the [Interpolation](guide/interpolation) guide.
|
||||
|
||||
{@a ivy}
|
||||
|
||||
|
@ -653,11 +653,11 @@ An object passed to the `subscribe()` method for an [observable](#observable). T
|
|||
## output
|
||||
|
||||
When defining a [directive](#directive), the `@Output{}` decorator on a directive property
|
||||
makes that property available as a *target* of [event binding](guide/template-syntax#event-binding).
|
||||
makes that property available as a *target* of [event binding](guide/event-binding).
|
||||
Events stream *out* of this property to the receiver identified
|
||||
in the [template expression](#template-expression) to the right of the equal sign.
|
||||
|
||||
To learn more, see [Input and Output Properties](guide/template-syntax#inputs-outputs).
|
||||
To learn more, see [Input and Output Properties](guide/inputs-outputs).
|
||||
|
||||
|
||||
{@a P}
|
||||
|
@ -917,7 +917,7 @@ The alternative is a reactive form. For an introduction and comparison of both f
|
|||
|
||||
A TypeScript-like syntax that Angular evaluates within a [data binding](#data-binding).
|
||||
|
||||
Read about how to write template expressions in [Template expressions](guide/template-syntax#template-expressions).
|
||||
Read about how to write template expressions in the [template expressions](guide/interpolation#template-expressions) section of the [Interpolation](guide/interpolation) guide.
|
||||
|
||||
{@a token}
|
||||
|
||||
|
|
|
@ -0,0 +1,342 @@
|
|||
# `@Input()` and `@Output()` properties
|
||||
|
||||
`@Input()` and `@Output()` allow Angular to share data between the parent context
|
||||
and child directives or components. An `@Input()` property is writable
|
||||
while an `@Output()` property is observable.
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
See the <live-example></live-example> for a working example containing the code snippets in this guide.
|
||||
|
||||
</div>
|
||||
|
||||
Consider this example of a child/parent relationship:
|
||||
|
||||
```html
|
||||
<parent-component>
|
||||
<child-component></child-component>
|
||||
</parent-component>
|
||||
|
||||
```
|
||||
|
||||
Here, the `<child-component>` selector, or child directive, is embedded
|
||||
within a `<parent-component>`, which serves as the child's context.
|
||||
|
||||
`@Input()` and `@Output()` act as
|
||||
the API, or application programming interface, of the child
|
||||
component in that they allow the child to
|
||||
communicate with the parent. Think of `@Input()` and `@Output()` like ports
|
||||
or doorways—`@Input()` is the doorway into the component allowing data
|
||||
to flow in while `@Output()` is the doorway out of the component, allowing the
|
||||
child component to send data out.
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
#### `@Input()` and `@Output()` are independent
|
||||
|
||||
Though `@Input()` and `@Output()` often appear together in apps, you can use
|
||||
them separately. If the nested
|
||||
component is such that it only needs to send data to its parent, you wouldn't
|
||||
need an `@Input()`, only an `@Output()`. The reverse is also true in that if the
|
||||
child only needs to receive data from the parent, you'd only need `@Input()`.
|
||||
|
||||
</div>
|
||||
|
||||
{@a input}
|
||||
|
||||
## How to use `@Input()`
|
||||
|
||||
Use the `@Input()` decorator in a child component or directive to let Angular know
|
||||
that a property in that component can receive its value from its parent component.
|
||||
It helps to remember that the data flow is from the perspective of the
|
||||
child component. So an `@Input()` allows data to be input _into_ the
|
||||
child component from the parent component.
|
||||
|
||||
|
||||
<div class="lightbox">
|
||||
<img src="generated/images/guide/inputs-outputs/input.svg" alt="Input data flow diagram">
|
||||
</div>
|
||||
|
||||
To illustrate the use of `@Input()`, edit these parts of your app:
|
||||
|
||||
* The child component class and template
|
||||
* The parent component class and template
|
||||
|
||||
|
||||
### In the child
|
||||
|
||||
To use the `@Input()` decorator in a child component class, first import
|
||||
`Input` and then decorate the property with `@Input()`:
|
||||
|
||||
<code-example path="inputs-outputs/src/app/item-detail/item-detail.component.ts" region="use-input" header="src/app/item-detail/item-detail.component.ts"></code-example>
|
||||
|
||||
|
||||
In this case, `@Input()` decorates the property <code class="no-auto-link">item</code>, which has
|
||||
a type of `string`, however, `@Input()` properties can have any type, such as
|
||||
`number`, `string`, `boolean`, or `object`. The value for `item` will come from the parent component, which the next section covers.
|
||||
|
||||
Next, in the child component template, add the following:
|
||||
|
||||
<code-example path="inputs-outputs/src/app/item-detail/item-detail.component.html" region="property-in-template" header="src/app/item-detail/item-detail.component.html"></code-example>
|
||||
|
||||
|
||||
|
||||
### In the parent
|
||||
|
||||
The next step is to bind the property in the parent component's template.
|
||||
In this example, the parent component template is `app.component.html`.
|
||||
|
||||
First, use the child's selector, here `<app-item-detail>`, as a directive within the
|
||||
parent component template. Then, use [property binding](guide/property-binding)
|
||||
to bind the property in the child to the property of the parent.
|
||||
|
||||
<code-example path="inputs-outputs/src/app/app.component.html" region="input-parent" header="src/app/app.component.html"></code-example>
|
||||
|
||||
Next, in the parent component class, `app.component.ts`, designate a value for `currentItem`:
|
||||
|
||||
<code-example path="inputs-outputs/src/app/app.component.ts" region="parent-property" header="src/app/app.component.ts"></code-example>
|
||||
|
||||
With `@Input()`, Angular passes the value for `currentItem` to the child so that `item` renders as `Television`.
|
||||
|
||||
The following diagram shows this structure:
|
||||
|
||||
<div class="lightbox">
|
||||
<img src="generated/images/guide/inputs-outputs/input-diagram-target-source.svg" alt="Property binding diagram">
|
||||
</div>
|
||||
|
||||
The target in the square brackets, `[]`, is the property you decorate
|
||||
with `@Input()` in the child component. The binding source, the part
|
||||
to the right of the equal sign, is the data that the parent
|
||||
component passes to the nested component.
|
||||
|
||||
The key takeaway is that when binding to a child component's property in a parent component—that is, what's
|
||||
in square brackets—you must
|
||||
decorate the property with `@Input()` in the child component.
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
### `OnChanges` and `@Input()`
|
||||
|
||||
To watch for changes on an `@Input()` property, use
|
||||
`OnChanges`, one of Angular's [lifecycle hooks](guide/lifecycle-hooks#onchanges).
|
||||
`OnChanges` is specifically designed to work with properties that have the
|
||||
`@Input()` decorator. See the [`OnChanges`](guide/lifecycle-hooks#onchanges) section of the [Lifecycle Hooks](guide/lifecycle-hooks) guide for more details and examples.
|
||||
|
||||
</div>
|
||||
|
||||
{@a output}
|
||||
|
||||
## How to use `@Output()`
|
||||
|
||||
Use the `@Output()` decorator in the child component or directive to allow data to flow from
|
||||
the child _out_ to the parent.
|
||||
|
||||
An `@Output()` property should normally be initialized to an Angular [`EventEmitter`](api/core/EventEmitter) with values flowing out of the component as [events](guide/event-binding).
|
||||
|
||||
|
||||
<div class="lightbox">
|
||||
<img src="generated/images/guide/inputs-outputs/output.svg" alt="Output diagram">
|
||||
</div>
|
||||
|
||||
Just like with `@Input()`, you can use `@Output()`
|
||||
on a property of the child component but its type should be
|
||||
`EventEmitter`.
|
||||
|
||||
`@Output()` marks a property in a child component as a doorway
|
||||
through which data can travel from the child to the parent.
|
||||
The child component then has to raise an event so the
|
||||
parent knows something has changed. To raise an event,
|
||||
`@Output()` works hand in hand with `EventEmitter`,
|
||||
which is a class in `@angular/core` that you
|
||||
use to emit custom events.
|
||||
|
||||
When you use `@Output()`, edit these parts of your app:
|
||||
|
||||
* The child component class and template
|
||||
* The parent component class and template
|
||||
|
||||
|
||||
The following example shows how to set up an `@Output()` in a child
|
||||
component that pushes data you enter in an HTML `<input>` to an array in the
|
||||
parent component.
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
The HTML element `<input>` and the Angular decorator `@Input()`
|
||||
are different. This documentation is about component communication in Angular as it pertains to `@Input()` and `@Output()`. For more information on the HTML element `<input>`, see the [W3C Recommendation](https://www.w3.org/TR/html5/sec-forms.html#the-input-element).
|
||||
|
||||
</div>
|
||||
|
||||
## In the child
|
||||
|
||||
This example features an `<input>` where a user can enter a value and click a `<button>` that raises an event. The `EventEmitter` then relays the data to the parent component.
|
||||
|
||||
First, be sure to import `Output` and `EventEmitter`
|
||||
in the child component class:
|
||||
|
||||
```js
|
||||
import { Output, EventEmitter } from '@angular/core';
|
||||
|
||||
```
|
||||
|
||||
Next, still in the child, decorate a property with `@Output()` in the component class.
|
||||
The following example `@Output()` is called `newItemEvent` and its type is
|
||||
`EventEmitter`, which means it's an event.
|
||||
|
||||
|
||||
<code-example path="inputs-outputs/src/app/item-output/item-output.component.ts" region="item-output" header="src/app/item-output/item-output.component.ts"></code-example>
|
||||
|
||||
The different parts of the above declaration are as follows:
|
||||
|
||||
* `@Output()`—a decorator function marking the property as a way for data to go from the child to the parent
|
||||
* `newItemEvent`—the name of the `@Output()`
|
||||
* `EventEmitter<string>`—the `@Output()`'s type
|
||||
* `new EventEmitter<string>()`—tells Angular to create a new event emitter and that the data it emits is of type string. The type could be any type, such as `number`, `boolean`, and so on. For more information on `EventEmitter`, see the [EventEmitter API documentation](api/core/EventEmitter).
|
||||
|
||||
Next, create an `addNewItem()` method in the same component class:
|
||||
|
||||
<code-example path="inputs-outputs/src/app/item-output/item-output.component.ts" region="item-output-class" header="src/app/item-output/item-output.component.ts"></code-example>
|
||||
|
||||
The `addNewItem()` function uses the `@Output()`, `newItemEvent`,
|
||||
to raise an event in which it emits the value the user
|
||||
types into the `<input>`. In other words, when
|
||||
the user clicks the add button in the UI, the child lets the parent know
|
||||
about the event and gives that data to the parent.
|
||||
|
||||
### In the child's template
|
||||
|
||||
The child's template has two controls. The first is an HTML `<input>` with a
|
||||
[template reference variable](guide/template-reference-variables) , `#newItem`,
|
||||
where the user types in an item name. Whatever the user types
|
||||
into the `<input>` gets stored in the `#newItem` variable.
|
||||
|
||||
<code-example path="inputs-outputs/src/app/item-output/item-output.component.html" region="child-output" header="src/app/item-output/item-output.component.html"></code-example>
|
||||
|
||||
The second element is a `<button>`
|
||||
with an [event binding](guide/event-binding). You know it's
|
||||
an event binding because the part to the left of the equal
|
||||
sign is in parentheses, `(click)`.
|
||||
|
||||
The `(click)` event is bound to the `addNewItem()` method in the child component class which
|
||||
takes as its argument whatever the value of `#newItem` is.
|
||||
|
||||
Now the child component has an `@Output()`
|
||||
for sending data to the parent and a method for raising an event.
|
||||
The next step is in the parent.
|
||||
|
||||
## In the parent
|
||||
|
||||
In this example, the parent component is `AppComponent`, but you could use
|
||||
any component in which you could nest the child.
|
||||
|
||||
The `AppComponent` in this example features a list of `items`
|
||||
in an array and a method for adding more items to the array.
|
||||
|
||||
<code-example path="inputs-outputs/src/app/app.component.ts" region="add-new-item" header="src/app/app.component.ts"></code-example>
|
||||
|
||||
The `addItem()` method takes an argument in the form of a string
|
||||
and then pushes, or adds, that string to the `items` array.
|
||||
|
||||
### In the parent's template
|
||||
|
||||
Next, in the parent's template, bind the parent's
|
||||
method to the child's event. Put the child selector, here `<app-item-output>`,
|
||||
within the parent component's
|
||||
template, `app.component.html`.
|
||||
|
||||
<code-example path="inputs-outputs/src/app/app.component.html" region="output-parent" header="src/app/app.component.html"></code-example>
|
||||
|
||||
The event binding, `(newItemEvent)='addItem($event)'`, tells
|
||||
Angular to connect the event in the child, `newItemEvent`, to
|
||||
the method in the parent, `addItem()`, and that the event that the child
|
||||
is notifying the parent about is to be the argument of `addItem()`.
|
||||
In other words, this is where the actual hand off of data takes place.
|
||||
The `$event` contains the data that the user types into the `<input>`
|
||||
in the child template UI.
|
||||
|
||||
Now, in order to see the `@Output()` working, add the following to the parent's template:
|
||||
|
||||
```html
|
||||
<ul>
|
||||
<li *ngFor="let item of items">{{item}}</li>
|
||||
</ul>
|
||||
```
|
||||
|
||||
The `*ngFor` iterates over the items in the `items` array. When you enter a value in the child's `<input>` and click the button, the child emits the event and the parent's `addItem()` method pushes the value to the `items` array and it renders in the list.
|
||||
|
||||
|
||||
## `@Input()` and `@Output()` together
|
||||
|
||||
You can use `@Input()` and `@Output()` on the same child component as in the following:
|
||||
|
||||
<code-example path="inputs-outputs/src/app/app.component.html" region="together" header="src/app/app.component.html"></code-example>
|
||||
|
||||
The target, `item`, which is an `@Input()` property in the child component class, receives its value from the parent's property, `currentItem`. When you click delete, the child component raises an event, `deleteRequest`, which is the argument for the parent's `crossOffItem()` method.
|
||||
|
||||
The following diagram is of an `@Input()` and an `@Output()` on the same
|
||||
child component and shows the different parts of each:
|
||||
|
||||
<div class="lightbox">
|
||||
<img src="generated/images/guide/inputs-outputs/input-output-diagram.svg" alt="Input/Output diagram">
|
||||
</div>
|
||||
|
||||
As the diagram shows, use inputs and outputs together in the same manner as using them separately. Here, the child selector is `<app-input-output>` with `item` and `deleteRequest` being `@Input()` and `@Output()`
|
||||
properties in the child component class. The property `currentItem` and the method `crossOffItem()` are both in the parent component class.
|
||||
|
||||
To combine property and event bindings using the banana-in-a-box
|
||||
syntax, `[()]`, see [Two-way Binding](guide/two-way-binding).
|
||||
|
||||
## `@Input()` and `@Output()` declarations
|
||||
|
||||
Instead of using the `@Input()` and `@Output()` decorators
|
||||
to declare inputs and outputs, you can identify
|
||||
members in the `inputs` and `outputs` arrays
|
||||
of the directive metadata, as in this example:
|
||||
|
||||
<code-example path="inputs-outputs/src/app/in-the-metadata/in-the-metadata.component.ts" region="metadata" header="src/app/in-the-metadata/in-the-metadata.component.ts"></code-example>
|
||||
|
||||
While declaring `inputs` and `outputs` in the `@Directive` and `@Component`
|
||||
metadata is possible, it is a better practice to use the `@Input()` and `@Output()`
|
||||
class decorators instead, as follows:
|
||||
|
||||
<code-example path="inputs-outputs/src/app/input-output/input-output.component.ts" region="input-output" header="src/app/input-output/input-output.component.ts"></code-example>
|
||||
|
||||
See the [Decorate input and output properties](guide/styleguide#decorate-input-and-output-properties) section of the
|
||||
[Style Guide](guide/styleguide) for details.
|
||||
|
||||
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
If you get a template parse error when trying to use inputs or outputs, but you know that the
|
||||
properties do indeed exist, double check
|
||||
that your properties are annotated with `@Input()` / `@Output()` or that you've declared
|
||||
them in an `inputs`/`outputs` array:
|
||||
|
||||
<code-example language="bash">
|
||||
Uncaught Error: Template parse errors:
|
||||
Can't bind to 'item' since it isn't a known property of 'app-item-detail'
|
||||
</code-example>
|
||||
|
||||
</div>
|
||||
|
||||
{@a aliasing-io}
|
||||
|
||||
## Aliasing inputs and outputs
|
||||
|
||||
Sometimes the public name of an input/output property should be different from the internal name. While it is a best practice to avoid this situation, Angular does
|
||||
offer a solution.
|
||||
|
||||
### Aliasing in the metadata
|
||||
|
||||
Alias inputs and outputs in the metadata using a colon-delimited (`:`) string with
|
||||
the directive property name on the left and the public alias on the right:
|
||||
|
||||
<code-example path="inputs-outputs/src/app/aliasing/aliasing.component.ts" region="alias" header="src/app/aliasing/aliasing.component.ts"></code-example>
|
||||
|
||||
|
||||
### Aliasing with the `@Input()`/`@Output()` decorator
|
||||
|
||||
You can specify the alias for the property name by passing the alias name to the `@Input()`/`@Output()` decorator. The internal name remains as usual.
|
||||
|
||||
<code-example path="inputs-outputs/src/app/aliasing/aliasing.component.ts" region="alias-input-output" header="src/app/aliasing/aliasing.component.ts"></code-example>
|
|
@ -0,0 +1,175 @@
|
|||
# Interpolation and template expressions
|
||||
|
||||
Interpolation allows you to incorporate calculated strings into the text
|
||||
between HTML element tags and within attribute assignments. Template
|
||||
expressions are what you use to calculate those strings.
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
See the <live-example></live-example> for all of
|
||||
the syntax and code snippets in this guide.
|
||||
|
||||
</div>
|
||||
|
||||
## Interpolation `{{...}}`
|
||||
|
||||
Interpolation refers to embedding expressions into marked up text.
|
||||
By default, interpolation uses as its delimiter the double curly braces, `{{` and `}}`.
|
||||
|
||||
In the following snippet, `{{ currentCustomer }}` is an example of interpolation.
|
||||
|
||||
<code-example path="interpolation/src/app/app.component.html" region="interpolation-example1" header="src/app/app.component.html"></code-example>
|
||||
|
||||
The text between the braces is often the name of a component
|
||||
property. Angular replaces that name with the
|
||||
string value of the corresponding component property.
|
||||
|
||||
<code-example path="interpolation/src/app/app.component.html" region="component-property" header="src/app/app.component.html"></code-example>
|
||||
|
||||
In the example above, Angular evaluates the `title` and `itemImageUrl` properties
|
||||
and fills in the blanks, first displaying some title text and then an image.
|
||||
|
||||
More generally, the text between the braces is a **template expression**
|
||||
that Angular first **evaluates** and then **converts to a string**.
|
||||
The following interpolation illustrates the point by adding two numbers:
|
||||
|
||||
<code-example path="interpolation/src/app/app.component.html" region="convert-string" header="src/app/app.component.html"></code-example>
|
||||
|
||||
The expression can invoke methods of the host component such as `getVal()` in
|
||||
the following example:
|
||||
|
||||
<code-example path="interpolation/src/app/app.component.html" region="invoke-method" header="src/app/app.component.html"></code-example>
|
||||
|
||||
Angular evaluates all expressions in double curly braces,
|
||||
converts the expression results to strings, and links them with neighboring literal strings. Finally,
|
||||
it assigns this composite interpolated result to an **element or directive property**.
|
||||
|
||||
You appear to be inserting the result between element tags and assigning it to attributes.
|
||||
However, interpolation is a special syntax that Angular converts into a *property binding*.
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
If you'd like to use something other than `{{` and `}}`, you can
|
||||
configure the interpolation delimiter via the
|
||||
[interpolation](api/core/Component#interpolation)
|
||||
option in the `Component` metadata.
|
||||
|
||||
</div>
|
||||
|
||||
## Template expressions
|
||||
|
||||
A template **expression** produces a value and appears within the double
|
||||
curly braces, `{{ }}`.
|
||||
Angular executes the expression and assigns it to a property of a binding target;
|
||||
the target could be an HTML element, a component, or a directive.
|
||||
|
||||
The interpolation braces in `{{1 + 1}}` surround the template expression `1 + 1`.
|
||||
In the property binding,
|
||||
a template expression appears in quotes to the right of the `=` symbol as in `[property]="expression"`.
|
||||
|
||||
In terms of syntax, template expressions are similar to JavaScript.
|
||||
Many JavaScript expressions are legal template expressions, with a few exceptions.
|
||||
|
||||
You can't use JavaScript expressions that have or promote side effects,
|
||||
including:
|
||||
|
||||
* Assignments (`=`, `+=`, `-=`, `...`)
|
||||
* Operators such as `new`, `typeof`, `instanceof`, etc.
|
||||
* Chaining expressions with <code>;</code> or <code>,</code>
|
||||
* The increment and decrement operators `++` and `--`
|
||||
* Some of the ES2015+ operators
|
||||
|
||||
Other notable differences from JavaScript syntax include:
|
||||
|
||||
* No support for the bitwise operators such as `|` and `&`
|
||||
* New [template expression operators](guide/template-expression-operators), such as `|`, `?.` and `!`
|
||||
|
||||
|
||||
## Expression context
|
||||
|
||||
The *expression context* is typically the _component_ instance.
|
||||
In the following snippets, the `recommended` within double curly braces and the
|
||||
`itemImageUrl2` in quotes refer to properties of the `AppComponent`.
|
||||
|
||||
<code-example path="interpolation/src/app/app.component.html" region="component-context" header="src/app/app.component.html"></code-example>
|
||||
|
||||
An expression may also refer to properties of the _template's_ context
|
||||
such as a template input variable,
|
||||
<!-- link to built-in-directives#template-input-variables -->
|
||||
`let customer`, or a template reference variable, `#customerInput`.
|
||||
<!-- link to guide/template-ref-variables -->
|
||||
|
||||
<code-example path="interpolation/src/app/app.component.html" region="template-input-variable" header="src/app/app.component.html (template input variable)"></code-example>
|
||||
|
||||
<code-example path="interpolation/src/app/app.component.html" region="template-reference-variable" header="src/app/app.component.html (template reference variable)"></code-example>
|
||||
|
||||
The context for terms in an expression is a blend of the _template variables_,
|
||||
the directive's _context_ object (if it has one), and the component's _members_.
|
||||
If you reference a name that belongs to more than one of these namespaces,
|
||||
the template variable name takes precedence, followed by a name in the directive's _context_,
|
||||
and, lastly, the component's member names.
|
||||
|
||||
The previous example presents such a name collision. The component has a `customer`
|
||||
property and the `*ngFor` defines a `customer` template variable.
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
The `customer` in `{{customer.name}}`
|
||||
refers to the template input variable, not the component's property.
|
||||
|
||||
Template expressions cannot refer to anything in
|
||||
the global namespace, except `undefined`. They can't refer to
|
||||
`window` or `document`. Additionally, they
|
||||
can't call `console.log()` or `Math.max()` and they are restricted to referencing
|
||||
members of the expression context.
|
||||
|
||||
</div>
|
||||
|
||||
## Expression guidelines
|
||||
|
||||
When using template expressions follow these guidelines:
|
||||
|
||||
* [Simplicity](guide/interpolation#simplicity)
|
||||
* [Quick execution](guide/interpolation#quick-execution)
|
||||
* [No visible side effects](guide/interpolation#no-visible-side-effects)
|
||||
|
||||
### Simplicity
|
||||
|
||||
Although it's possible to write complex template expressions, it's a better
|
||||
practice to avoid them.
|
||||
|
||||
A property name or method call should be the norm, but an occasional Boolean negation, `!`, is OK.
|
||||
Otherwise, confine application and business logic to the component,
|
||||
where it is easier to develop and test.
|
||||
|
||||
### Quick execution
|
||||
|
||||
Angular executes template expressions after every change detection cycle.
|
||||
Change detection cycles are triggered by many asynchronous activities such as
|
||||
promise resolutions, HTTP results, timer events, key presses and mouse moves.
|
||||
|
||||
Expressions should finish quickly or the user experience may drag, especially on slower devices.
|
||||
Consider caching values when their computation is expensive.
|
||||
|
||||
### No visible side effects
|
||||
|
||||
A template expression should not change any application state other than the value of the
|
||||
target property.
|
||||
|
||||
This rule is essential to Angular's "unidirectional data flow" policy.
|
||||
You should never worry that reading a component value might change some other displayed value.
|
||||
The view should be stable throughout a single rendering pass.
|
||||
|
||||
An [idempotent](https://en.wikipedia.org/wiki/Idempotence) expression is ideal because
|
||||
it is free of side effects and improves Angular's change detection performance.
|
||||
In Angular terms, an idempotent expression always returns
|
||||
*exactly the same thing* until one of its dependent values changes.
|
||||
|
||||
Dependent values should not change during a single turn of the event loop.
|
||||
If an idempotent expression returns a string or a number, it returns the same string or number when called twice in a row. If the expression returns an object, including an `array`, it returns the same object *reference* when called twice in a row.
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
There is one exception to this behavior that applies to `*ngFor`. `*ngFor` has `trackBy` functionality that can deal with referential inequality of objects when iterating over them. See [*ngFor with `trackBy`](guide/built-in-directives #ngfor-with-trackby) for details.
|
||||
|
||||
</div>
|
|
@ -2,13 +2,13 @@
|
|||
|
||||
Angular makes use of observables as an interface to handle a variety of common asynchronous operations. For example:
|
||||
|
||||
* You can define [custom events](guide/template-syntax#custom-events-with-eventemitter) that send observable output data from a child to a parent component.
|
||||
* You can define [custom events](guide/event-binding#custom-events-with-eventemitter) that send observable output data from a child to a parent component.
|
||||
* The HTTP module uses observables to handle AJAX requests and responses.
|
||||
* The Router and Forms modules use observables to listen for and respond to user-input events.
|
||||
|
||||
## Transmitting data between components
|
||||
|
||||
Angular provides an `EventEmitter` class that is used when publishing values from a component through the [`@Output()` decorator](guide/template-syntax#how-to-use-output).
|
||||
Angular provides an `EventEmitter` class that is used when publishing values from a component through the [`@Output()` decorator](guide/inputs-outputs#how-to-use-output).
|
||||
`EventEmitter` extends [RxJS `Subject`](https://rxjs.dev/api/index/class/Subject), adding an `emit()` method so it can send arbitrary values.
|
||||
When you call `emit()`, it passes the emitted value to the `next()` method of any subscribed observer.
|
||||
|
||||
|
|
|
@ -58,7 +58,7 @@ The tabs in the example show the following:
|
|||
</code-tabs>
|
||||
|
||||
The component's `birthday` value flows through the
|
||||
[pipe operator](guide/template-syntax#pipe) ( | ) to the [`date`](api/common/DatePipe)
|
||||
[pipe operator](guide/template-expression-operators#pipe) ( | ) to the [`date`](api/common/DatePipe)
|
||||
function.
|
||||
|
||||
{@a parameterizing-a-pipe}
|
||||
|
|
|
@ -0,0 +1,228 @@
|
|||
|
||||
# Property binding `[property]`
|
||||
|
||||
Use property binding to _set_ properties of target elements or
|
||||
directive `@Input()` decorators.
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
See the <live-example></live-example> for a working example containing the code snippets in this guide.
|
||||
|
||||
</div>
|
||||
|
||||
## One-way in
|
||||
|
||||
Property binding flows a value in one direction,
|
||||
from a component's property into a target element property.
|
||||
|
||||
You can't use property
|
||||
binding to read or pull values out of target elements. Similarly, you cannot use
|
||||
property binding to call a method on the target element.
|
||||
If the element raises events, you can listen to them with an [event binding](guide/event-binding).
|
||||
|
||||
If you must read a target element property or call one of its methods,
|
||||
see the API reference for [ViewChild](api/core/ViewChild) and
|
||||
[ContentChild](api/core/ContentChild).
|
||||
|
||||
## Examples
|
||||
|
||||
The most common property binding sets an element property to a component
|
||||
property value. An example is
|
||||
binding the `src` property of an image element to a component's `itemImageUrl` property:
|
||||
|
||||
<code-example path="property-binding/src/app/app.component.html" region="property-binding" header="src/app/app.component.html"></code-example>
|
||||
|
||||
Here's an example of binding to the `colSpan` property. Notice that it's not `colspan`,
|
||||
which is the attribute, spelled with a lowercase `s`.
|
||||
|
||||
<code-example path="property-binding/src/app/app.component.html" region="colSpan" header="src/app/app.component.html"></code-example>
|
||||
|
||||
For more details, see the [MDN HTMLTableCellElement](https://developer.mozilla.org/en-US/docs/Web/API/HTMLTableCellElement) documentation.
|
||||
|
||||
For more information about `colSpan` and `colspan`, see the [Attribute binding](guide/attribute-binding#colspan) guide.
|
||||
|
||||
Another example is disabling a button when the component says that it `isUnchanged`:
|
||||
|
||||
<code-example path="property-binding/src/app/app.component.html" region="disabled-button" header="src/app/app.component.html"></code-example>
|
||||
|
||||
Another is setting a property of a directive:
|
||||
|
||||
<code-example path="property-binding/src/app/app.component.html" region="class-binding" header="src/app/app.component.html"></code-example>
|
||||
|
||||
Yet another is setting the model property of a custom component—a great way
|
||||
for parent and child components to communicate:
|
||||
|
||||
<code-example path="property-binding/src/app/app.component.html" region="model-property-binding" header="src/app/app.component.html"></code-example>
|
||||
|
||||
## Binding targets
|
||||
|
||||
An element property between enclosing square brackets identifies the target property.
|
||||
The target property in the following code is the image element's `src` property.
|
||||
|
||||
<code-example path="property-binding/src/app/app.component.html" region="property-binding" header="src/app/app.component.html"></code-example>
|
||||
|
||||
There's also the `bind-` prefix alternative:
|
||||
|
||||
<code-example path="property-binding/src/app/app.component.html" region="bind-prefix" header="src/app/app.component.html"></code-example>
|
||||
|
||||
|
||||
In most cases, the target name is the name of a property, even
|
||||
when it appears to be the name of an attribute.
|
||||
So in this case, `src` is the name of the `<img>` element property.
|
||||
|
||||
Element properties may be the more common targets,
|
||||
but Angular looks first to see if the name is a property of a known directive,
|
||||
as it is in the following example:
|
||||
|
||||
<code-example path="property-binding/src/app/app.component.html" region="class-binding" header="src/app/app.component.html"></code-example>
|
||||
|
||||
Technically, Angular is matching the name to a directive `@Input()`,
|
||||
one of the property names listed in the directive's `inputs` array
|
||||
or a property decorated with `@Input()`.
|
||||
Such inputs map to the directive's own properties.
|
||||
|
||||
If the name fails to match a property of a known directive or element, Angular reports an “unknown directive” error.
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
Though the target name is usually the name of a property,
|
||||
there is an automatic attribute-to-property mapping in Angular for
|
||||
several common attributes. These include `class`/`className`, `innerHtml`/`innerHTML`, and
|
||||
`tabindex`/`tabIndex`.
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
## Avoid side effects
|
||||
|
||||
Evaluation of a template expression should have no visible side effects.
|
||||
The expression language itself, or the way you write template expressions,
|
||||
helps to a certain extent;
|
||||
you can't assign a value to anything in a property binding expression
|
||||
nor use the increment and decrement operators.
|
||||
|
||||
For example, you could have an expression that invoked a property or method that had
|
||||
side effects. The expression could call something like `getFoo()` where only you
|
||||
know what `getFoo()` does. If `getFoo()` changes something
|
||||
and you happen to be binding to that something,
|
||||
Angular may or may not display the changed value. Angular may detect the
|
||||
change and throw a warning error.
|
||||
As a best practice, stick to properties and to methods that return
|
||||
values and avoid side effects.
|
||||
|
||||
## Return the proper type
|
||||
|
||||
The template expression should evaluate to the type of value
|
||||
that the target property expects.
|
||||
Return a string if the target property expects a string, a number if it
|
||||
expects a number, an object if it expects an object, and so on.
|
||||
|
||||
In the following example, the `childItem` property of the `ItemDetailComponent` expects a string, which is exactly what you're sending in the property binding:
|
||||
|
||||
<code-example path="property-binding/src/app/app.component.html" region="model-property-binding" header="src/app/app.component.html"></code-example>
|
||||
|
||||
You can confirm this by looking in the `ItemDetailComponent` where the `@Input` type is set to a string:
|
||||
<code-example path="property-binding/src/app/item-detail/item-detail.component.ts" region="input-type" header="src/app/item-detail/item-detail.component.ts (setting the @Input() type)"></code-example>
|
||||
|
||||
As you can see here, the `parentItem` in `AppComponent` is a string, which the `ItemDetailComponent` expects:
|
||||
<code-example path="property-binding/src/app/app.component.ts" region="parent-data-type" header="src/app/app.component.ts"></code-example>
|
||||
|
||||
### Passing in an object
|
||||
|
||||
The previous simple example showed passing in a string. To pass in an object,
|
||||
the syntax and thinking are the same.
|
||||
|
||||
In this scenario, `ItemListComponent` is nested within `AppComponent` and the `items` property expects an array of objects.
|
||||
|
||||
<code-example path="property-binding/src/app/app.component.html" region="pass-object" header="src/app/app.component.html"></code-example>
|
||||
|
||||
The `items` property is declared in the `ItemListComponent` with a type of `Item` and decorated with `@Input()`:
|
||||
|
||||
<code-example path="property-binding/src/app/item-list/item-list.component.ts" region="item-input" header="src/app/item-list.component.ts"></code-example>
|
||||
|
||||
In this sample app, an `Item` is an object that has two properties; an `id` and a `name`.
|
||||
|
||||
<code-example path="property-binding/src/app/item.ts" region="item-class" header="src/app/item.ts"></code-example>
|
||||
|
||||
While a list of items exists in another file, `mock-items.ts`, you can
|
||||
specify a different item in `app.component.ts` so that the new item will render:
|
||||
|
||||
<code-example path="property-binding/src/app/app.component.ts" region="pass-object" header="src/app.component.ts"></code-example>
|
||||
|
||||
You just have to make sure, in this case, that you're supplying an array of objects because that's the type of `Item` and is what the nested component, `ItemListComponent`, expects.
|
||||
|
||||
In this example, `AppComponent` specifies a different `item` object
|
||||
(`currentItems`) and passes it to the nested `ItemListComponent`. `ItemListComponent` was able to use `currentItems` because it matches what an `Item` object is according to `item.ts`. The `item.ts` file is where
|
||||
`ItemListComponent` gets its definition of an `item`.
|
||||
|
||||
## Remember the brackets
|
||||
|
||||
The brackets, `[]`, tell Angular to evaluate the template expression.
|
||||
If you omit the brackets, Angular treats the string as a constant
|
||||
and *initializes the target property* with that string:
|
||||
|
||||
<code-example path="property-binding/src/app/app.component.html" region="no-evaluation" header="src/app.component.html"></code-example>
|
||||
|
||||
|
||||
Omitting the brackets will render the string
|
||||
`parentItem`, not the value of `parentItem`.
|
||||
|
||||
## One-time string initialization
|
||||
|
||||
You *should* omit the brackets when all of the following are true:
|
||||
|
||||
* The target property accepts a string value.
|
||||
* The string is a fixed value that you can put directly into the template.
|
||||
* This initial value never changes.
|
||||
|
||||
You routinely initialize attributes this way in standard HTML, and it works
|
||||
just as well for directive and component property initialization.
|
||||
The following example initializes the `prefix` property of the `StringInitComponent` to a fixed string,
|
||||
not a template expression. Angular sets it and forgets about it.
|
||||
|
||||
<code-example path="property-binding/src/app/app.component.html" region="string-init" header="src/app/app.component.html"></code-example>
|
||||
|
||||
The `[item]` binding, on the other hand, remains a live binding to the component's `currentItems` property.
|
||||
|
||||
## Property binding vs. interpolation
|
||||
|
||||
You often have a choice between interpolation and property binding.
|
||||
The following binding pairs do the same thing:
|
||||
|
||||
<code-example path="property-binding/src/app/app.component.html" region="property-binding-interpolation" header="src/app/app.component.html"></code-example>
|
||||
|
||||
Interpolation is a convenient alternative to property binding in
|
||||
many cases. When rendering data values as strings, there is no
|
||||
technical reason to prefer one form to the other, though readability
|
||||
tends to favor interpolation. However, *when setting an element
|
||||
property to a non-string data value, you must use property binding*.
|
||||
|
||||
## Content security
|
||||
|
||||
Imagine the following malicious content.
|
||||
|
||||
<code-example path="property-binding/src/app/app.component.ts" region="malicious-content" header="src/app/app.component.ts"></code-example>
|
||||
|
||||
In the component template, the content might be used with interpolation:
|
||||
|
||||
<code-example path="property-binding/src/app/app.component.html" region="malicious-interpolated" header="src/app/app.component.html"></code-example>
|
||||
|
||||
Fortunately, Angular data binding is on alert for dangerous HTML. In the above case,
|
||||
the HTML displays as is, and the Javascript does not execute. Angular **does not**
|
||||
allow HTML with script tags to leak into the browser, neither with interpolation
|
||||
nor property binding.
|
||||
|
||||
In the following example, however, Angular [sanitizes](guide/security#sanitization-and-security-contexts)
|
||||
the values before displaying them.
|
||||
|
||||
<code-example path="property-binding/src/app/app.component.html" region="malicious-content" header="src/app/app.component.html"></code-example>
|
||||
|
||||
Interpolation handles the `<script>` tags differently than
|
||||
property binding but both approaches render the
|
||||
content harmlessly. The following is the browser output
|
||||
of the `evilTitle` examples.
|
||||
|
||||
<code-example language="bash">
|
||||
"Template <script>alert("evil never sleeps")</script> Syntax" is the interpolated evil title.
|
||||
"Template alert("evil never sleeps")Syntax" is the property bound evil title.
|
||||
</code-example>
|
|
@ -1170,7 +1170,7 @@ The `ActivatedRoute.paramMap` property is an `Observable` map of route parameter
|
|||
The `paramMap` emits a new map of values that includes `id` when the user navigates to the component.
|
||||
In `ngOnInit()` you subscribe to those values, set the `selectedId`, and get the heroes.
|
||||
|
||||
Update the template with a [class binding](guide/template-syntax#class-binding).
|
||||
Update the template with a [class binding](guide/attribute-binding#class-binding).
|
||||
The binding adds the `selected` CSS class when the comparison returns `true` and removes it when `false`.
|
||||
Look for it within the repeated `<li>` tag as shown here:
|
||||
|
||||
|
|
|
@ -665,7 +665,7 @@ The router resolves that array into a complete URL.
|
|||
|
||||
The `RouterLinkActive` directive toggles CSS classes for active `RouterLink` bindings based on the current `RouterState`.
|
||||
|
||||
On each anchor tag, you see a [property binding](guide/template-syntax#property-binding) to the `RouterLinkActive` directive that looks like `routerLinkActive="..."`.
|
||||
On each anchor tag, you see a [property binding](guide/property-binding) to the `RouterLinkActive` directive that looks like `routerLinkActive="..."`.
|
||||
|
||||
The template expression to the right of the equal sign, `=`, contains a space-delimited string of CSS classes that the Router adds when this link is active (and removes when the link is inactive).
|
||||
You set the `RouterLinkActive` directive to a string of classes such as `[routerLinkActive]="'active fluffy'"` or bind it to a component property that returns such a string.
|
||||
|
|
|
@ -39,14 +39,14 @@ No brackets. No parentheses. Just `*ngIf` set to a string.
|
|||
|
||||
You'll learn in this guide that the [asterisk (*) is a convenience notation](guide/structural-directives#asterisk)
|
||||
and the string is a [_microsyntax_](guide/structural-directives#microsyntax) rather than the usual
|
||||
[template expression](guide/template-syntax#template-expressions).
|
||||
[template expression](guide/interpolation#template-expressions).
|
||||
Angular desugars this notation into a marked-up `<ng-template>` that surrounds the
|
||||
host element and its descendents.
|
||||
host element and its descendants.
|
||||
Each structural directive does something different with that template.
|
||||
|
||||
Three of the common, built-in structural directives—[NgIf](guide/template-syntax#ngIf),
|
||||
[NgFor](guide/template-syntax#ngFor), and [NgSwitch...](guide/template-syntax#ngSwitch)—are
|
||||
described in the [_Template Syntax_](guide/template-syntax) guide and seen in samples throughout the Angular documentation.
|
||||
Three of the common, built-in structural directives—[NgIf](guide/built-in-directives#ngIf),
|
||||
[NgFor](guide/built-in-directives#ngFor), and [NgSwitch...](guide/built-in-directives#ngSwitch)—are
|
||||
described in the [Built-in directives](guide/built-in-directives) guide and seen in samples throughout the Angular documentation.
|
||||
Here's an example of them in a template:
|
||||
|
||||
|
||||
|
@ -96,7 +96,7 @@ Technically it's a directive with a template.
|
|||
|
||||
An [*attribute* directive](guide/attribute-directives) changes the appearance or behavior
|
||||
of an element, component, or another directive.
|
||||
For example, the built-in [`NgStyle`](guide/template-syntax#ngStyle) directive
|
||||
For example, the built-in [`NgStyle`](guide/built-in-directives#ngStyle) directive
|
||||
changes several element styles at the same time.
|
||||
|
||||
You can apply many _attribute_ directives to one host element.
|
||||
|
@ -440,7 +440,7 @@ There are several such variables in this example: `hero`, `i`, and `odd`.
|
|||
All are preceded by the keyword `let`.
|
||||
|
||||
A _template input variable_ is **_not_** the same as a
|
||||
[template _reference_ variable](guide/template-syntax#ref-vars),
|
||||
[template _reference_ variable](guide/template-reference-variables),
|
||||
neither _semantically_ nor _syntactically_.
|
||||
|
||||
You declare a template _input_ variable using the `let` keyword (`let hero`).
|
||||
|
@ -786,7 +786,7 @@ That means the directive needs an `appUnless` property, decorated with `@Input`
|
|||
|
||||
|
||||
|
||||
Read about `@Input` in the [_Template Syntax_](guide/template-syntax#inputs-outputs) guide.
|
||||
Read about `@Input` in the [`@Input()` and `@Output()` properties](guide/inputs-outputs) guide.
|
||||
|
||||
|
||||
</div>
|
||||
|
|
|
@ -3286,7 +3286,7 @@ helps instantly identify which members of the component serve which purpose.
|
|||
|
||||
|
||||
|
||||
**Why?** Angular allows for an [alternative syntax](guide/template-syntax#binding-syntax) `on-*`. If the event itself was prefixed with `on` this would result in an `on-onEvent` binding expression.
|
||||
**Why?** Angular allows for an [alternative syntax](guide/binding-syntax) `on-*`. If the event itself was prefixed with `on` this would result in an `on-onEvent` binding expression.
|
||||
|
||||
|
||||
</div>
|
||||
|
|
|
@ -0,0 +1,27 @@
|
|||
# SVG in templates
|
||||
|
||||
It is possible to use SVG as valid templates in Angular. All of the template syntax below is
|
||||
applicable to both SVG and HTML. Learn more in the SVG [1.1](https://www.w3.org/TR/SVG11/) and
|
||||
[2.0](https://www.w3.org/TR/SVG2/) specifications.
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
See the <live-example name="template-syntax"></live-example> for a working example containing the code snippets in this guide.
|
||||
|
||||
</div>
|
||||
|
||||
Why would you use SVG as template, instead of simply adding it as image to your application?
|
||||
|
||||
When you use an SVG as the template, you are able to use directives and bindings just like with HTML
|
||||
templates. This means that you will be able to dynamically generate interactive graphics.
|
||||
|
||||
Refer to the sample code snippet below for a syntax example:
|
||||
|
||||
<code-example path="template-syntax/src/app/svg.component.ts" header="src/app/svg.component.ts"></code-example>
|
||||
|
||||
Add the following code to your `svg.component.svg` file:
|
||||
|
||||
<code-example path="template-syntax/src/app/svg.component.svg" header="src/app/svg.component.svg"></code-example>
|
||||
|
||||
Here you can see the use of a `click()` event binding and the property binding syntax
|
||||
(`[attr.fill]="fillColor"`).
|
|
@ -0,0 +1,144 @@
|
|||
<!-- {@a expression-operators} -->
|
||||
|
||||
# Template expression operators
|
||||
|
||||
The Angular template expression language employs a subset of JavaScript syntax supplemented with a few special operators
|
||||
for specific scenarios. The next sections cover three of these operators:
|
||||
|
||||
* [pipe](guide/template-expression-operators#pipe)
|
||||
* [safe navigation operator](guide/template-expression-operators#safe-navigation-operator)
|
||||
* [non-null assertion operator](guide/template-expression-operators#non-null-assertion-operator)
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
See the <live-example></live-example> for a working example containing the code snippets in this guide.
|
||||
|
||||
</div>
|
||||
|
||||
{@a pipe}
|
||||
|
||||
## The pipe operator (`|`)
|
||||
|
||||
The result of an expression might require some transformation before you're ready to use it in a binding.
|
||||
For example, you might display a number as a currency, change text to uppercase, or filter a list and sort it.
|
||||
|
||||
Pipes are simple functions that accept an input value and return a transformed value.
|
||||
They're easy to apply within template expressions, using the pipe operator (`|`):
|
||||
|
||||
<code-example path="template-expression-operators/src/app/app.component.html" region="uppercase-pipe" header="src/app/app.component.html"></code-example>
|
||||
|
||||
The pipe operator passes the result of an expression on the left to a pipe function on the right.
|
||||
|
||||
You can chain expressions through multiple pipes:
|
||||
|
||||
<code-example path="template-expression-operators/src/app/app.component.html" region="pipe-chain" header="src/app/app.component.html"></code-example>
|
||||
|
||||
And you can also [apply parameters](guide/pipes#parameterizing-a-pipe) to a pipe:
|
||||
|
||||
<code-example path="template-expression-operators/src/app/app.component.html" region="date-pipe" header="src/app/app.component.html"></code-example>
|
||||
|
||||
The `json` pipe is particularly helpful for debugging bindings:
|
||||
|
||||
<code-example path="template-expression-operators/src/app/app.component.html" region="json-pipe" header="src/app/app.component.html"></code-example>
|
||||
|
||||
The generated output would look something like this:
|
||||
|
||||
<code-example language="json">
|
||||
{ "name": "Telephone",
|
||||
"manufactureDate": "1980-02-25T05:00:00.000Z",
|
||||
"price": 98 }
|
||||
</code-example>
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
The pipe operator has a higher precedence than the ternary operator (`?:`),
|
||||
which means `a ? b : c | x` is parsed as `a ? b : (c | x)`.
|
||||
Nevertheless, for a number of reasons,
|
||||
the pipe operator cannot be used without parentheses in the first and second operands of `?:`.
|
||||
A good practice is to use parentheses in the third operand too.
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
<hr/>
|
||||
|
||||
{@a safe-navigation-operator}
|
||||
|
||||
## The safe navigation operator ( `?` ) and null property paths
|
||||
|
||||
The Angular safe navigation operator, `?`, guards against `null` and `undefined`
|
||||
values in property paths. Here, it protects against a view render failure if `item` is `null`.
|
||||
|
||||
<code-example path="template-expression-operators/src/app/app.component.html" region="safe" header="src/app/app.component.html"></code-example>
|
||||
|
||||
If `item` is `null`, the view still renders but the displayed value is blank; you see only "The item name is:" with nothing after it.
|
||||
|
||||
Consider the next example, with a `nullItem`.
|
||||
|
||||
<code-example language="html">
|
||||
The null item name is {{nullItem.name}}
|
||||
</code-example>
|
||||
|
||||
Since there is no safe navigation operator and `nullItem` is `null`, JavaScript and Angular would throw a `null` reference error and break the rendering process of Angular:
|
||||
|
||||
<code-example language="bash">
|
||||
TypeError: Cannot read property 'name' of null.
|
||||
</code-example>
|
||||
|
||||
Sometimes however, `null` values in the property
|
||||
path may be OK under certain circumstances,
|
||||
especially when the value starts out null but the data arrives eventually.
|
||||
|
||||
With the safe navigation operator, `?`, Angular stops evaluating the expression when it hits the first `null` value and renders the view without errors.
|
||||
|
||||
It works perfectly with long property paths such as `a?.b?.c?.d`.
|
||||
|
||||
|
||||
<hr/>
|
||||
|
||||
{@a non-null-assertion-operator}
|
||||
|
||||
## The non-null assertion operator ( `!` )
|
||||
|
||||
As of Typescript 2.0, you can enforce [strict null checking](http://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-0.html "Strict null checking in TypeScript") with the `--strictNullChecks` flag. TypeScript then ensures that no variable is unintentionally `null` or `undefined`.
|
||||
|
||||
In this mode, typed variables disallow `null` and `undefined` by default. The type checker throws an error if you leave a variable unassigned or try to assign `null` or `undefined` to a variable whose type disallows `null` and `undefined`.
|
||||
|
||||
The type checker also throws an error if it can't determine whether a variable will be `null` or `undefined` at runtime. You tell the type checker not to throw an error by applying the postfix
|
||||
[non-null assertion operator, !](http://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-0.html#non-null-assertion-operator "Non-null assertion operator").
|
||||
|
||||
The Angular non-null assertion operator, `!`, serves the same purpose in
|
||||
an Angular template. For example, you can assert that `item` properties are also defined.
|
||||
|
||||
<code-example path="template-expression-operators/src/app/app.component.html" region="non-null" header="src/app/app.component.html"></code-example>
|
||||
|
||||
When the Angular compiler turns your template into TypeScript code,
|
||||
it prevents TypeScript from reporting that `item.color` might be `null` or `undefined`.
|
||||
|
||||
Unlike the [_safe navigation operator_](guide/template-expression-operators#safe-navigation-operator "Safe navigation operator (?)"),
|
||||
the non-null assertion operator does not guard against `null` or `undefined`.
|
||||
Rather, it tells the TypeScript type checker to suspend strict `null` checks for a specific property expression.
|
||||
|
||||
The non-null assertion operator, `!`, is optional with the exception that you must use it when you turn on strict null checks.
|
||||
|
||||
{@a any-type-cast-function}
|
||||
|
||||
## The `$any()` type cast function
|
||||
|
||||
Sometimes a binding expression triggers a type error during [AOT compilation](guide/aot-compiler) and it is not possible or difficult to fully specify the type.
|
||||
To silence the error, you can use the `$any()` cast function to cast
|
||||
the expression to the [`any` type](http://www.typescriptlang.org/docs/handbook/basic-types.html#any) as in the following example:
|
||||
|
||||
<code-example path="built-in-template-functions/src/app/app.component.html" region="any-type-cast-function-1" header="src/app/app.component.html"></code-example>
|
||||
|
||||
When the Angular compiler turns this template into TypeScript code,
|
||||
it prevents TypeScript from reporting that `bestByDate` is not a member of the `item`
|
||||
object when it runs type checking on the template.
|
||||
|
||||
The `$any()` cast function also works with `this` to allow access to undeclared members of
|
||||
the component.
|
||||
|
||||
<code-example path="built-in-template-functions/src/app/app.component.html" region="any-type-cast-function-2" header="src/app/app.component.html"></code-example>
|
||||
|
||||
The `$any()` cast function works anywhere in a binding expression where a method call is valid.
|
||||
|
|
@ -0,0 +1,62 @@
|
|||
# Template reference variables (`#var`)
|
||||
|
||||
A **template reference variable** is often a reference to a DOM element within a template.
|
||||
It can also refer to a directive (which contains a component), an element, [TemplateRef](api/core/TemplateRef), or a <a href="https://developer.mozilla.org/en-US/docs/Web/Web_Components" title="MDN: Web Components">web component</a>.
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
See the <live-example></live-example> for a working example containing the code snippets in this guide.
|
||||
|
||||
</div>
|
||||
|
||||
Use the hash symbol (#) to declare a reference variable.
|
||||
The following reference variable, `#phone`, declares a `phone` variable on an `<input>` element.
|
||||
|
||||
<code-example path="template-reference-variables/src/app/app.component.html" region="ref-var" header="src/app/app.component.html"></code-example>
|
||||
|
||||
You can refer to a template reference variable anywhere in the component's template.
|
||||
Here, a `<button>` further down the template refers to the `phone` variable.
|
||||
|
||||
<code-example path="template-reference-variables/src/app/app.component.html" region="ref-phone" header="src/app/app.component.html"></code-example>
|
||||
|
||||
<h3 class="no-toc">How a reference variable gets its value</h3>
|
||||
|
||||
In most cases, Angular sets the reference variable's value to the element on which it is declared.
|
||||
In the previous example, `phone` refers to the phone number `<input>`.
|
||||
The button's click handler passes the `<input>` value to the component's `callPhone()` method.
|
||||
|
||||
The `NgForm` directive can change that behavior and set the value to something else. In the following example, the template reference variable, `itemForm`, appears three times separated
|
||||
by HTML.
|
||||
|
||||
<code-example path="template-reference-variables/src/app/app.component.html" region="ngForm" header="src/app/hero-form.component.html"></code-example>
|
||||
|
||||
The reference value of itemForm, without the ngForm attribute value, would be
|
||||
the [HTMLFormElement](https://developer.mozilla.org/en-US/docs/Web/API/HTMLFormElement).
|
||||
There is, however, a difference between a Component and a Directive in that a `Component`
|
||||
will be referenced without specifying the attribute value, and a `Directive` will not
|
||||
change the implicit reference (that is, the element).
|
||||
|
||||
|
||||
|
||||
However, with `NgForm`, `itemForm` is a reference to the [NgForm](api/forms/NgForm "API: NgForm")
|
||||
directive with the ability to track the value and validity of every control in the form.
|
||||
|
||||
The native `<form>` element doesn't have a `form` property, but the `NgForm` directive does, which allows disabling the submit button
|
||||
if the `itemForm.form.valid` is invalid and passing the entire form control tree
|
||||
to the parent component's `onSubmit()` method.
|
||||
|
||||
<h3 class="no-toc">Template reference variable considerations</h3>
|
||||
|
||||
A template _reference_ variable (`#phone`) is not the same as a template _input_ variable (`let phone`) such as in an [`*ngFor`](guide/built-in-directives#template-input-variable).
|
||||
See [_Structural directives_](guide/structural-directives#template-input-variable) for more information.
|
||||
|
||||
The scope of a reference variable is the entire template. So, don't define the same variable name more than once in the same template as the runtime value will be unpredictable.
|
||||
|
||||
### Alternative syntax
|
||||
|
||||
You can use the `ref-` prefix alternative to `#`.
|
||||
This example declares the `fax` variable as `ref-fax` instead of `#fax`.
|
||||
|
||||
|
||||
<code-example path="template-reference-variables/src/app/app.component.html" region="ref-fax" header="src/app/app.component.html"></code-example>
|
||||
|
|
@ -0,0 +1,65 @@
|
|||
# Template statements
|
||||
|
||||
A template **statement** responds to an **event** raised by a binding target
|
||||
such as an element, component, or directive.
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
See the <live-example name="template-syntax">Template syntax</live-example> for
|
||||
the syntax and code snippets in this guide.
|
||||
|
||||
</div>
|
||||
|
||||
The following template statement appears in quotes to the right of the `=` symbol as in `(event)="statement"`.
|
||||
|
||||
<code-example path="template-syntax/src/app/app.component.html" region="context-component-statement" header="src/app/app.component.html"></code-example>
|
||||
|
||||
A template statement *has a side effect*.
|
||||
That's the whole point of an event.
|
||||
It's how you update application state from user action.
|
||||
|
||||
Responding to events is the other side of Angular's "unidirectional data flow".
|
||||
You're free to change anything, anywhere, during this turn of the event loop.
|
||||
|
||||
Like template expressions, template *statements* use a language that looks like JavaScript.
|
||||
The template statement parser differs from the template expression parser and
|
||||
specifically supports both basic assignment (`=`) and chaining expressions with <code>;</code>.
|
||||
|
||||
However, certain JavaScript and template expression syntax is not allowed:
|
||||
|
||||
* <code>new</code>
|
||||
* increment and decrement operators, `++` and `--`
|
||||
* operator assignment, such as `+=` and `-=`
|
||||
* the bitwise operators, such as `|` and `&`
|
||||
* the [pipe operator](guide/template-expression-operators#pipe)
|
||||
|
||||
## Statement context
|
||||
|
||||
As with expressions, statements can refer only to what's in the statement context
|
||||
such as an event handling method of the component instance.
|
||||
|
||||
The *statement context* is typically the component instance.
|
||||
The *deleteHero* in `(click)="deleteHero()"` is a method of the data-bound component.
|
||||
|
||||
<code-example path="template-syntax/src/app/app.component.html" region="context-component-statement" header="src/app/app.component.html"></code-example>
|
||||
|
||||
The statement context may also refer to properties of the template's own context.
|
||||
In the following examples, the template `$event` object,
|
||||
a [template input variable](guide/built-in-directives#template-input-variable) (`let hero`),
|
||||
and a [template reference variable](guide/template-reference-variables) (`#heroForm`)
|
||||
are passed to an event handling method of the component.
|
||||
|
||||
<code-example path="template-syntax/src/app/app.component.html" region="context-var-statement" header="src/app/app.component.html"></code-example>
|
||||
|
||||
Template context names take precedence over component context names.
|
||||
In `deleteHero(hero)` above, the `hero` is the template input variable,
|
||||
not the component's `hero` property.
|
||||
|
||||
## Statement guidelines
|
||||
|
||||
Template statements cannot refer to anything in the global namespace. They
|
||||
can't refer to `window` or `document`.
|
||||
They can't call `console.log` or `Math.max`.
|
||||
|
||||
As with expressions, avoid writing complex template statements.
|
||||
A method call or simple property assignment should be the norm.
|
File diff suppressed because it is too large
Load Diff
|
@ -106,8 +106,8 @@ There can also be false positives when the typings of an Angular library are eit
|
|||
|
||||
In case of a false positive like these, there are a few options:
|
||||
|
||||
* Use the [`$any()` type-cast function](guide/template-syntax#any-type-cast-function) in certain contexts to opt out of type-checking for a part of the expression.
|
||||
* You can disable strict checks entirely by setting `strictTemplates: false` in the application's TypeScript configuration file.
|
||||
* Use the [`$any()` type-cast function](guide/template-expression-operators#any-type-cast-function) in certain contexts to opt out of type-checking for a part of the expression.
|
||||
* You can disable strict checks entirely by setting `strictTemplates: false` in the application's TypeScript configuration file, `tsconfig.json`.
|
||||
* You can disable certain type-checking operations individually, while maintaining strictness in other aspects, by setting a _strictness flag_ to `false`.
|
||||
* If you want to use `strictTemplates` and `strictNullChecks` together, you can opt out of strict null type checking specifically for input bindings via `strictNullInputTypes`.
|
||||
|
||||
|
@ -286,7 +286,7 @@ Care should be taken that if an `ngAcceptInputType_` override is present for a g
|
|||
|
||||
## Disabling type checking using `$any()`
|
||||
|
||||
Disable checking of a binding expression by surrounding the expression in a call to the [`$any()` cast pseudo-function](guide/template-syntax).
|
||||
Disable checking of a binding expression by surrounding the expression in a call to the [`$any()` cast pseudo-function](guide/template-expression-operators).
|
||||
The compiler treats it as a cast to the `any` type just like in TypeScript when a `<any>` or `as any` cast is used.
|
||||
|
||||
In the following example, casting `person` to the `any` type suppresses the error `Property address does not exist`.
|
||||
|
|
|
@ -0,0 +1,76 @@
|
|||
# Two-way binding `[(...)]`
|
||||
|
||||
Two-way binding gives your app a way to share data between a component class and
|
||||
its template.
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
See the <live-example></live-example> for a working example containing the code snippets in this guide.
|
||||
|
||||
</div>
|
||||
|
||||
## Basics of two-way binding
|
||||
|
||||
Two-way binding does two things:
|
||||
|
||||
1. Sets a specific element property.
|
||||
1. Listens for an element change event.
|
||||
|
||||
Angular offers a special _two-way data binding_ syntax for this purpose, `[()]`.
|
||||
The `[()]` syntax combines the brackets
|
||||
of property binding, `[]`, with the parentheses of event binding, `()`.
|
||||
|
||||
<div class="callout is-important">
|
||||
|
||||
<header>
|
||||
[( )] = banana in a box
|
||||
</header>
|
||||
|
||||
Visualize a *banana in a box* to remember that the parentheses go _inside_ the brackets.
|
||||
|
||||
</div>
|
||||
|
||||
The `[()]` syntax is easy to demonstrate when the element has a settable
|
||||
property called `x` and a corresponding event named `xChange`.
|
||||
Here's a `SizerComponent` that fits this pattern.
|
||||
It has a `size` value property and a companion `sizeChange` event:
|
||||
|
||||
<code-example path="two-way-binding/src/app/sizer/sizer.component.ts" header="src/app/sizer.component.ts"></code-example>
|
||||
|
||||
<code-example path="two-way-binding/src/app/sizer/sizer.component.html" header="src/app/sizer.component.html"></code-example>
|
||||
|
||||
The initial `size` is an input value from a property binding.
|
||||
Clicking the buttons increases or decreases the `size`, within
|
||||
min/max value constraints,
|
||||
and then raises, or emits, the `sizeChange` event with the adjusted size.
|
||||
|
||||
Here's an example in which the `AppComponent.fontSizePx` is two-way bound to the `SizerComponent`:
|
||||
|
||||
<code-example path="two-way-binding/src/app/app.component.html" header="src/app/app.component.html (two-way-1)" region="two-way-1"></code-example>
|
||||
|
||||
The `AppComponent.fontSizePx` establishes the initial `SizerComponent.size` value.
|
||||
|
||||
<code-example path="two-way-binding/src/app/app.component.ts" header="src/app/app.component.ts" region="font-size"></code-example>
|
||||
|
||||
Clicking the buttons updates the `AppComponent.fontSizePx` via the two-way binding.
|
||||
The revised `AppComponent.fontSizePx` value flows through to the _style_ binding,
|
||||
making the displayed text bigger or smaller.
|
||||
|
||||
The two-way binding syntax is really just syntactic sugar for a _property_ binding and an _event_ binding.
|
||||
Angular desugars the `SizerComponent` binding into this:
|
||||
|
||||
<code-example path="two-way-binding/src/app/app.component.html" header="src/app/app.component.html (two-way-2)" region="two-way-2"></code-example>
|
||||
|
||||
The `$event` variable contains the payload of the `SizerComponent.sizeChange` event.
|
||||
Angular assigns the `$event` value to the `AppComponent.fontSizePx` when the user clicks the buttons.
|
||||
|
||||
## Two-way binding in forms
|
||||
|
||||
The two-way binding syntax is a great convenience compared to
|
||||
separate property and event bindings. It would be convenient to
|
||||
use two-way binding with HTML form elements like `<input>` and
|
||||
`<select>`. However, no native HTML element follows the `x`
|
||||
value and `xChange` event pattern.
|
||||
|
||||
For more on how to use two-way binding in forms, see
|
||||
Angular [NgModel](guide/built-in-directives#ngModel).
|
|
@ -1567,7 +1567,7 @@ with Angular's two-way `[(ngModel)]` binding syntax:
|
|||
<code-example path="upgrade-phonecat-2-hybrid/app/phone-list/phone-list.template.html" region="controls" header="app/phone-list/phone-list.template.html (search controls)"></code-example>
|
||||
|
||||
Replace the list's `ng-repeat` with an `*ngFor` as
|
||||
[described in the Template Syntax page](guide/template-syntax#directives).
|
||||
[described in the Template Syntax page](guide/built-in-directives).
|
||||
Replace the image tag's `ng-src` with a binding to the native `src` property.
|
||||
|
||||
<code-example path="upgrade-phonecat-2-hybrid/app/phone-list/phone-list.template.html" region="list" header="app/phone-list/phone-list.template.html (phones)"></code-example>
|
||||
|
@ -1637,7 +1637,7 @@ There are several notable changes here:
|
|||
bindings for the standard `src` property.
|
||||
|
||||
* You're using the property binding syntax around `ng-class`. Though Angular
|
||||
does have [a very similar `ngClass`](guide/template-syntax#directives)
|
||||
does have [a very similar `ngClass`](guide/built-in-directives)
|
||||
as AngularJS does, its value is not magically evaluated as an expression.
|
||||
In Angular, you always specify in the template when an attribute's value is
|
||||
a property expression, as opposed to a literal string.
|
||||
|
|
|
@ -10,13 +10,13 @@ Run the <live-example></live-example>.
|
|||
|
||||
## Binding to user input events
|
||||
|
||||
You can use [Angular event bindings](guide/template-syntax#event-binding)
|
||||
You can use [Angular event bindings](guide/event-binding)
|
||||
to respond to any [DOM event](https://developer.mozilla.org/en-US/docs/Web/Events).
|
||||
Many DOM events are triggered by user input. Binding to these events provides a way to
|
||||
get input from the user.
|
||||
|
||||
To bind to a DOM event, surround the DOM event name in parentheses and assign a quoted
|
||||
[template statement](guide/template-syntax#template-statements) to it.
|
||||
[template statement](guide/template-statements) to it.
|
||||
|
||||
The following example shows an event binding that implements a click handler:
|
||||
|
||||
|
@ -70,7 +70,7 @@ In this case, `target` refers to the [`<input>` element](https://developer.mozil
|
|||
|
||||
After each call, the `onKey()` method appends the contents of the input box value to the list
|
||||
in the component's `values` property, followed by a separator character (|).
|
||||
The [interpolation](guide/template-syntax#interpolation)
|
||||
The [interpolation](guide/interpolation)
|
||||
displays the accumulating input box changes from the `values` property.
|
||||
|
||||
Suppose the user enters the letters "abc", and then backspaces to remove them one by one.
|
||||
|
@ -139,7 +139,7 @@ The next section shows how to use template reference variables to address this p
|
|||
|
||||
## Get user input from a template reference variable
|
||||
There's another way to get the user data: use Angular
|
||||
[**template reference variables**](guide/template-syntax#ref-vars).
|
||||
[**template reference variables**](guide/template-reference-variables).
|
||||
These variables provide direct access to an element from within the template.
|
||||
To declare a template reference variable, precede an identifier with a hash (or pound) character (#).
|
||||
|
||||
|
|
|
@ -189,9 +189,75 @@
|
|||
"tooltip": "Property binding helps show app data in the UI."
|
||||
},
|
||||
{
|
||||
"url": "guide/template-syntax",
|
||||
"title": "Template Syntax",
|
||||
"tooltip": "Learn how to write templates that display data and consume user events with the help of data binding."
|
||||
"tooltip": "Syntax to use in templates for binding, expressions, and directives.",
|
||||
"children": [
|
||||
{
|
||||
"url": "guide/template-syntax",
|
||||
"title": "Introduction",
|
||||
"tooltip": "Introduction to writing templates that display data and consume user events with the help of data binding."
|
||||
},
|
||||
{
|
||||
"url": "guide/interpolation",
|
||||
"title": "Interpolation",
|
||||
"tooltip": "An introduction to interpolation and expressions in HTML."
|
||||
},
|
||||
{
|
||||
"url": "guide/template-statements",
|
||||
"title": "Template statements",
|
||||
"tooltip": "Introductory guide to statements in templates that respond to events that components, directives, or elements raise."
|
||||
},
|
||||
{
|
||||
"url": "guide/binding-syntax",
|
||||
"title": "Binding syntax",
|
||||
"tooltip": "Introductory guide to coordinating app values."
|
||||
},
|
||||
{
|
||||
"url": "guide/property-binding",
|
||||
"title": "Property binding",
|
||||
"tooltip": "Introductory guide to setting element or input properties."
|
||||
},
|
||||
{
|
||||
"url": "guide/attribute-binding",
|
||||
"title": "Attribute, class, and style bindings",
|
||||
"tooltip": "Introductory guide to setting the value of HTML attributes."
|
||||
},
|
||||
{
|
||||
"url": "guide/event-binding",
|
||||
"title": "Event binding",
|
||||
"tooltip": "Introductory guide to listening for user interaction."
|
||||
},
|
||||
{
|
||||
"url": "guide/two-way-binding",
|
||||
"title": "Two-way binding",
|
||||
"tooltip": "Introductory guide to sharing data between a class and a template."
|
||||
},
|
||||
{
|
||||
"url": "guide/built-in-directives",
|
||||
"title": "Built-in directives",
|
||||
"tooltip": "Introductory guide to some of the most popular built-in directives."
|
||||
},
|
||||
{
|
||||
"url": "guide/template-reference-variables",
|
||||
"title": "Template reference variables",
|
||||
"tooltip": "Introductory guide to referring to DOM elements within a template."
|
||||
},
|
||||
{
|
||||
"url": "guide/inputs-outputs",
|
||||
"title": "Inputs and Outputs",
|
||||
"tooltip": "Introductory guide to sharing data between parent and child directives or components."
|
||||
},
|
||||
{
|
||||
"url": "guide/template-expression-operators",
|
||||
"title": "Template expression operators",
|
||||
"tooltip": "Introductory guide to transforming data, ensuring safe navigation, and guarding against null variables in templates."
|
||||
},
|
||||
{
|
||||
"url": "guide/svg-in-templates",
|
||||
"title": "SVG in templates",
|
||||
"tooltip": "Guide to using SVGs as templates to create interactive graphics."
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"url": "guide/user-input",
|
||||
|
|
|
@ -53,7 +53,7 @@ That shows one hero. To list them all, add an `*ngFor` to the `<li>` to iterate
|
|||
<code-example path="toh-pt2/src/app/heroes/heroes.component.1.html" region="li">
|
||||
</code-example>
|
||||
|
||||
The [`*ngFor`](guide/template-syntax#ngFor) is Angular's _repeater_ directive.
|
||||
The [`*ngFor`](guide/built-in-directives#ngFor) is Angular's _repeater_ directive.
|
||||
It repeats the host element for each element in a list.
|
||||
|
||||
The syntax in this example is as follows:
|
||||
|
@ -122,7 +122,7 @@ Add a click event binding to the `<li>` like this:
|
|||
|
||||
<code-example path="toh-pt2/src/app/heroes/heroes.component.1.html" region="selectedHero-click" header="heroes.component.html (template excerpt)"></code-example>
|
||||
|
||||
This is an example of Angular's [event binding](guide/template-syntax#event-binding) syntax.
|
||||
This is an example of Angular's [event binding](guide/event-binding) syntax.
|
||||
|
||||
The parentheses around `click` tell Angular to listen for the `<li>` element's `click` event.
|
||||
When the user clicks in the `<li>`, Angular executes the `onSelect(hero)` expression.
|
||||
|
@ -209,7 +209,7 @@ If the user clicks "Magneta", that hero should render with a distinctive but sub
|
|||
That _selected hero_ coloring is the work of the `.selected` CSS class in the [styles you added earlier](#styles).
|
||||
You just have to apply the `.selected` class to the `<li>` when the user clicks it.
|
||||
|
||||
The Angular [class binding](guide/template-syntax#class-binding) makes it easy to add and remove a CSS class conditionally.
|
||||
The Angular [class binding](guide/attribute-binding#class-binding) makes it easy to add and remove a CSS class conditionally.
|
||||
Just add `[class.some-css-class]="some-condition"` to the element you want to style.
|
||||
|
||||
Add the following `[class.selected]` binding to the `<li>` in the `HeroesComponent` template:
|
||||
|
|
|
@ -62,7 +62,7 @@ region="import-hero" header="src/app/hero-detail/hero-detail.component.ts (impor
|
|||
</code-example>
|
||||
|
||||
The `hero` property
|
||||
[must be an _Input_ property](guide/template-syntax#inputs-outputs "Input and Output properties"),
|
||||
[must be an _Input_ property](guide/inputs-outputs "Input and Output properties"),
|
||||
annotated with the `@Input()` decorator,
|
||||
because the _external_ `HeroesComponent` [will bind to it](#heroes-component-template) like this.
|
||||
|
||||
|
@ -107,7 +107,7 @@ Bind the `HeroesComponent.selectedHero` to the element's `hero` property like th
|
|||
|
||||
</code-example>
|
||||
|
||||
`[hero]="selectedHero"` is an Angular [property binding](guide/template-syntax#property-binding).
|
||||
`[hero]="selectedHero"` is an Angular [property binding](guide/property-binding).
|
||||
|
||||
It's a _one way_ data binding from
|
||||
the `selectedHero` property of the `HeroesComponent` to the `hero` property of the target element, which maps to the `hero` property of the `HeroDetailComponent`.
|
||||
|
@ -165,9 +165,9 @@ Here are the code files discussed on this page.
|
|||
* You created a separate, reusable `HeroDetailComponent`.
|
||||
|
||||
|
||||
* You used a [property binding](guide/template-syntax#property-binding) to give the parent `HeroesComponent` control over the child `HeroDetailComponent`.
|
||||
* You used a [property binding](guide/property-binding) to give the parent `HeroesComponent` control over the child `HeroDetailComponent`.
|
||||
|
||||
|
||||
* You used the [`@Input` decorator](guide/template-syntax#inputs-outputs)
|
||||
* You used the [`@Input` decorator](guide/inputs-outputs)
|
||||
to make the `hero` property available for binding
|
||||
by the external `HeroesComponent`.
|
||||
|
|
|
@ -369,7 +369,7 @@ This template binds directly to the component's `messageService`.
|
|||
* An `*ngFor` presents the list of messages in repeated `<div>` elements.
|
||||
|
||||
|
||||
* An Angular [event binding](guide/template-syntax#event-binding) binds the button's click event
|
||||
* An Angular [event binding](guide/event-binding) binds the button's click event
|
||||
to `MessageService.clear()`.
|
||||
|
||||
The messages will look better when you add the private CSS styles to `messages.component.css`
|
||||
|
|
|
@ -318,7 +318,7 @@ fix the dashboard hero links to navigate via the _parameterized_ dashboard route
|
|||
header="src/app/dashboard/dashboard.component.html (hero links)">
|
||||
</code-example>
|
||||
|
||||
You're using Angular [interpolation binding](guide/template-syntax#interpolation) within the `*ngFor` repeater
|
||||
You're using Angular [interpolation binding](guide/interpolation) within the `*ngFor` repeater
|
||||
to insert the current iteration's `hero.id` into each
|
||||
[`routerLink`](#routerlink).
|
||||
|
||||
|
|
|
@ -186,7 +186,7 @@ export class NgForOf<T, U extends NgIterable<T> = NgIterable<T>> implements DoCh
|
|||
|
||||
/**
|
||||
* A reference to the template that is stamped out for each item in the iterable.
|
||||
* @see [template reference variable](guide/template-syntax#template-reference-variables--var-)
|
||||
* @see [template reference variable](guide/template-reference-variables)
|
||||
*/
|
||||
@Input()
|
||||
set ngForTemplate(value: TemplateRef<NgForOfContext<T, U>>) {
|
||||
|
|
|
@ -100,7 +100,7 @@ import {Directive, EmbeddedViewRef, Input, TemplateRef, ViewContainerRef, ɵstri
|
|||
*
|
||||
* The conditional displays the data only if `userStream` returns a value,
|
||||
* so you don't need to use the
|
||||
* [safe-navigation-operator](guide/template-syntax#safe-navigation-operator) (`?.`)
|
||||
* [safe-navigation-operator](guide/template-expression-operators#safe-navigation-operator) (`?.`)
|
||||
* to guard against null values when accessing properties.
|
||||
* You can display an alternative template while waiting for the data.
|
||||
*
|
||||
|
|
|
@ -684,7 +684,7 @@ export interface InputDecorator {
|
|||
* class App {}
|
||||
* ```
|
||||
*
|
||||
* @see [Input and Output properties](guide/template-syntax#input-and-output-properties)
|
||||
* @see [Input and Output properties](guide/inputs-outputs)
|
||||
*/
|
||||
(bindingPropertyName?: string): any;
|
||||
new(bindingPropertyName?: string): any;
|
||||
|
@ -728,7 +728,7 @@ export interface OutputDecorator {
|
|||
*
|
||||
* See `Input` decorator for an example of providing a binding name.
|
||||
*
|
||||
* @see [Input and Output properties](guide/template-syntax#input-and-output-properties)
|
||||
* @see [Input and Output properties](guide/inputs-outputs)
|
||||
*
|
||||
*/
|
||||
(bindingPropertyName?: string): any;
|
||||
|
|
Loading…
Reference in New Issue