From 5b31a0a2942c50059cac4c7ccb92047a50473347 Mon Sep 17 00:00:00 2001 From: Kapunahele Wong Date: Tue, 28 Apr 2020 16:26:58 -0400 Subject: [PATCH] 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 --- .pullapprove.yml | 13 + aio/content/guide/accessibility.md | 4 +- aio/content/guide/ajs-quick-reference.md | 38 +- aio/content/guide/aot-compiler.md | 2 +- aio/content/guide/architecture-components.md | 8 +- aio/content/guide/attribute-binding.md | 303 +++ aio/content/guide/attribute-directives.md | 6 +- aio/content/guide/binding-syntax.md | 318 +++ aio/content/guide/built-in-directives.md | 435 +++ aio/content/guide/component-interaction.md | 4 +- aio/content/guide/displaying-data.md | 10 +- aio/content/guide/event-binding.md | 108 + aio/content/guide/forms.md | 4 +- aio/content/guide/glossary.md | 28 +- aio/content/guide/inputs-outputs.md | 342 +++ aio/content/guide/interpolation.md | 175 ++ aio/content/guide/observables-in-angular.md | 4 +- aio/content/guide/pipes.md | 4 +- aio/content/guide/property-binding.md | 228 ++ aio/content/guide/router-tutorial-toh.md | 2 +- aio/content/guide/router.md | 2 +- aio/content/guide/structural-directives.md | 16 +- aio/content/guide/styleguide.md | 2 +- aio/content/guide/svg-in-templates.md | 27 + .../guide/template-expression-operators.md | 144 + .../guide/template-reference-variables.md | 62 + aio/content/guide/template-statements.md | 65 + aio/content/guide/template-syntax.md | 2386 +---------------- aio/content/guide/template-typecheck.md | 6 +- aio/content/guide/two-way-binding.md | 76 + aio/content/guide/upgrade.md | 4 +- aio/content/guide/user-input.md | 8 +- aio/content/navigation.json | 70 +- aio/content/tutorial/toh-pt2.md | 6 +- aio/content/tutorial/toh-pt3.md | 8 +- aio/content/tutorial/toh-pt4.md | 2 +- aio/content/tutorial/toh-pt5.md | 2 +- packages/common/src/directives/ng_for_of.ts | 2 +- packages/common/src/directives/ng_if.ts | 2 +- packages/core/src/metadata/directives.ts | 4 +- 40 files changed, 2511 insertions(+), 2419 deletions(-) create mode 100644 aio/content/guide/attribute-binding.md create mode 100644 aio/content/guide/binding-syntax.md create mode 100644 aio/content/guide/built-in-directives.md create mode 100644 aio/content/guide/event-binding.md create mode 100644 aio/content/guide/inputs-outputs.md create mode 100644 aio/content/guide/interpolation.md create mode 100644 aio/content/guide/property-binding.md create mode 100644 aio/content/guide/svg-in-templates.md create mode 100644 aio/content/guide/template-expression-operators.md create mode 100644 aio/content/guide/template-reference-variables.md create mode 100644 aio/content/guide/template-statements.md create mode 100644 aio/content/guide/two-way-binding.md diff --git a/.pullapprove.yml b/.pullapprove.yml index 8b29c82bf6..66e105baec 100644 --- a/.pullapprove.yml +++ b/.pullapprove.yml @@ -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/**' diff --git a/aio/content/guide/accessibility.md b/aio/content/guide/accessibility.md index 6d6714ffb0..042d61ceca 100644 --- a/aio/content/guide/accessibility.md +++ b/aio/content/guide/accessibility.md @@ -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. diff --git a/aio/content/guide/ajs-quick-reference.md b/aio/content/guide/ajs-quick-reference.md index e0b1a512e4..23b6d61028 100644 --- a/aio/content/guide/ajs-quick-reference.md +++ b/aio/content/guide/ajs-quick-reference.md @@ -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. @@ -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. @@ -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. @@ -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. @@ -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. @@ -570,8 +566,7 @@ The following are some of the key AngularJS built-in directives and their equiva In this example, the `
` 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. @@ -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. @@ -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. @@ -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. diff --git a/aio/content/guide/aot-compiler.md b/aio/content/guide/aot-compiler.md index 0367adf8dd..df846a9209 100644 --- a/aio/content/guide/aot-compiler.md +++ b/aio/content/guide/aot-compiler.md @@ -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`. diff --git a/aio/content/guide/architecture-components.md b/aio/content/guide/architecture-components.md index bf7fda4691..c4f8e7f9de 100644 --- a/aio/content/guide/architecture-components.md +++ b/aio/content/guide/architecture-components.md @@ -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 `
  • ` 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 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)).
    diff --git a/aio/content/guide/attribute-binding.md b/aio/content/guide/attribute-binding.md new file mode 100644 index 0000000000..c73dbcdb03 --- /dev/null +++ b/aio/content/guide/attribute-binding.md @@ -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. + +
    + +See the for a working example containing the code snippets in this guide. + +
    + + +## 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: + + + +{@a colspan} + +
    + +#### `colspan` and `colSpan` + +Notice the difference between the `colspan` attribute and the `colSpan` property. + +If you wrote something like this: + + + <tr><td colspan="{{1 + 1}}">Three-Four</td></tr> + + +You'd get this error: + + + Template parse errors: + Can't bind to 'colspan' since it isn't a known native property + + +As the message says, the `` 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: + + + +
    + +
    + +{@a class-binding} + +## Class binding + +Here's how to set the `class` attribute without a binding in plain HTML: + +```html + +
    Some text
    +``` + +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). + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + Binding Type + + Syntax + + Input Type + + Example Input Values +
    Single class binding[class.foo]="hasFoo"boolean | undefined | nulltrue, false
    Multi-class binding[class]="classExpr"string"my-class-1 my-class-2 my-class-3"
    {[key: string]: boolean | undefined | null}{foo: true, bar: false}
    Array<string>['foo', 'bar']
    + + +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. + + +
    + +## Style binding + +Here's how to set the `style` attribute without a binding in plain HTML: + +```html + +
    Some text
    +``` + +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. + +
    + +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`. + +
    + +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). + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + Binding Type + + Syntax + + Input Type + + Example Input Values +
    Single style binding[style.width]="width"string | undefined | null"100px"
    Single style binding with units[style.width.px]="width"number | undefined | null100
    Multi-style binding[style]="styleExpr"string"width: 100px; height: 100px"
    {[key: string]: string | undefined | null}{width: '100px', height: '100px'}
    Array<string>['width', '100px']
    + +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. + + +
    + +{@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. + +
    +

    Styling precedence (highest to lowest)

    + +1. Template bindings + 1. Property binding (for example, `
    ` or `
    `) + 1. Map binding (for example, `
    ` or `
    `) + 1. Static value (for example, `
    ` or `
    `) +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'}`) + +
    + +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. + + + +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. + + + +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. + + + +{@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: + + + +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. diff --git a/aio/content/guide/attribute-directives.md b/aio/content/guide/attribute-directives.md index d6f0be7379..4724d277c7 100644 --- a/aio/content/guide/attribute-directives.md +++ b/aio/content/guide/attribute-directives.md @@ -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 diff --git a/aio/content/guide/binding-syntax.md b/aio/content/guide/binding-syntax.md new file mode 100644 index 0000000000..0bd41cf77d --- /dev/null +++ b/aio/content/guide/binding-syntax.md @@ -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. + +
    + +See the for a working example containing the code snippets in this guide. + +
    + +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_ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + Type + + Syntax + + Category +
    + Interpolation
    + Property
    + Attribute
    + Class
    + Style +
    + + + {{expression}} + [target]="expression" + bind-target="expression" + + + + One-way
    from data source
    to view target +
    + Event + + + (target)="statement" + on-target="statement" + + + One-way
    from view target
    to data source +
    + Two-way + + + [(target)]="expression" + bindon-target="expression" + + + Two-way +
    + +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 +
    Plain old HTML
    + + +``` + +With data-binding, you can control things like the state of a button: + + + +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. + +
    + +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. + +
    + +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 [`` attributes](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/td) attributes to the [`` 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 `` + +When the browser renders ``, it creates a +corresponding DOM node with a `value` property initialized to "Sarah". + +```html + +``` + +When the user enters "Sally" into the ``, 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 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 + +``` + +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 ``. + +To control the state of the button, set the `disabled` *property*, + +
    + +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 + + +``` + +Generally, use property binding over attribute binding as it is more intuitive (being a boolean value), has a shorter syntax, and is more performant. + +
    + + +To see the `disabled` button example in a functioning app, see the 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. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + Type + + Target + + Examples +
    + Property + + Element property
    + Component property
    + Directive property +
    + src, hero, and ngClass in the following: + + +
    + Event + + Element event
    + Component event
    + Directive event +
    + click, deleteRequest, and myClick in the following: + + + +
    + Two-way + + Event and property + + +
    + Attribute + + Attribute + (the exception) + + +
    + Class + + class property + + +
    + Style + + style property + + +
    + diff --git a/aio/content/guide/built-in-directives.md b/aio/content/guide/built-in-directives.md new file mode 100644 index 0000000000..f1a65922a3 --- /dev/null +++ b/aio/content/guide/built-in-directives.md @@ -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). + +
    + +See the for a working example containing the code snippets in this guide. + +
    + +For more detail, including how to build your own custom directives, see [Attribute Directives](guide/attribute-directives) and [Structural Directives](guide/structural-directives). + +
    + +{@a attribute-directives} + +## Built-in attribute directives + +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. + +
    + +{@a ngClass} + +## `NgClass` + +Add or remove several CSS classes simultaneously with `ngClass`. + + + +
    + +To add or remove a *single* class, use [class binding](guide/attribute-binding#class-binding) rather than `NgClass`. + +
    + +Consider a `setCurrentClasses()` component method that sets a component property, +`currentClasses`, with an object that adds or removes three classes based on the +`true`/`false` state of three other component properties. Each key of the object is a CSS class name; its value is `true` if the class should be added, +`false` if it should be removed. + + + +Adding an `ngClass` property binding to `currentClasses` sets the element's classes accordingly: + + + +
    + +Remember that in this situation you'd call `setCurrentClasses()`, +both initially and when the dependent properties change. + +
    + +
    + +{@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`. + + + +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: + + + +Adding an `ngStyle` property binding to `currentStyles` sets the element's styles accordingly: + + + +
    + +Remember to call `setCurrentStyles()`, both initially and when the dependent properties change. + +
    + + +
    + +{@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: + + + + +### 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: + + + + +You could achieve the same result with separate bindings to +the `` element's `value` property and `input` event: + + + +To streamline the syntax, the `ngModel` directive hides the details behind its own `ngModel` input and `ngModelChange` output properties: + + + +The `ngModel` data property sets the element's value property and the `ngModelChange` event property +listens for changes to the element's value. + +### `NgModel` and value accessors + +The details are specific to each kind of element and therefore the `NgModel` directive only works for an element +supported by a [ControlValueAccessor](api/forms/ControlValueAccessor) +that adapts an element to this protocol. +Angular provides *value accessors* for all of the basic HTML form elements and the +[Forms](guide/forms) guide shows how to bind to them. + +You can't apply `[(ngModel)]` to a non-form native element or a +third-party custom component until you write a suitable value accessor. For more information, see +the API documentation on [DefaultValueAccessor](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: + + + +This `[(ngModel)]` syntax can only _set_ a data-bound property. +If you need to do something more, you can write the expanded form; +for example, the following changes the `` value to uppercase: + + + +Here are all variations in action, including the uppercase version: + + + +
    + +{@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. + +
    + +The deep details of structural directives are covered in the +[Structural Directives](guide/structural-directives) guide, +which explains the following: + +* Why you +[prefix the directive name with an asterisk (\*)](guide/structural-directives#the-asterisk--prefix). +* Using [``](guide/structural-directives#ngcontainer "") +to group elements when there is no suitable host element for the directive. +* How to write your own structural directive. +* That you can only apply [one structural directive](guide/structural-directives#one-per-element "one per host element") to an element. + +
    + +
    + +{@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. + + + +
    + +Don't forget the asterisk (`*`) in front of `ngIf`. For more information +on the asterisk, see the [asterisk (*) prefix](guide/structural-directives#the-asterisk--prefix) section of +[Structural Directives](guide/structural-directives). + +
    + +When the `isActive` expression returns a truthy value, `NgIf` adds the +`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. + + + +When you hide an element, that element and all of its descendants remain in the DOM. +All components for those elements stay in memory and +Angular may continue to check for changes. +You could be holding onto considerable computing resources and degrading performance +unnecessarily. + +`NgIf` works differently. When `NgIf` is `false`, Angular removes the element and its descendants from the DOM. +It destroys their components, freeing up resources, which +results in a better user experience. + +If you are hiding large component trees, consider `NgIf` as a more +efficient alternative to showing/hiding. + +
    + +For more information on `NgIf` and `ngIfElse`, see the [API documentation about NgIf](api/common/NgIf). + +
    + +### Guard against null + +Another advantage of `ngIf` is that you can use it to guard against null. Show/hide +is best suited for very simple use cases, so when you need a guard, opt instead for `ngIf`. Angular will throw an error if a nested expression tries to access a property of `null`. + +The following shows `NgIf` guarding two `
    `s. +The `currentCustomer` name appears only when there is a `currentCustomer`. +The `nullCustomer` will not be displayed as long as it is `null`. + + + + + +
    + +See also the +[safe navigation operator](guide/template-expression-operators#safe-navigation-operator "Safe navigation operator (?.)") below. + +
    +
    + +{@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 `
    `. (Don't forget the asterisk (`*`) in front of `ngFor`.) + + + +
    + +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). + +
    + +You can also apply an `NgFor` to a component element, as in the following example. + + + +{@a microsyntax} + +
    +
    *ngFor microsyntax
    + +The string assigned to `*ngFor` is not a [template expression](guide/interpolation). Rather, +it's a *microsyntax*—a little language of its own that Angular interprets. +The string `"let item of items"` means: + +> *Take each item in the `items` array, store it in the local `item` looping variable, and +make it available to the templated HTML for each iteration.* + +Angular translates this instruction into an `` around the host element, +then uses this template repeatedly to create a new set of elements and bindings for each `item` +in the list. +For more information about microsyntax, see the [Structural Directives](guide/structural-directives#microsyntax) guide. + +
    + + +{@a template-input-variable} + +{@a template-input-variables} + +### Template input variables + +The `let` keyword before `item` creates a template input variable called `item`. +The `ngFor` directive iterates over the `items` array returned by the parent component's `items` property +and sets `item` to the current item from the array during each iteration. + +Reference `item` within the `ngFor` host element +as well as within its descendants to access the item's properties. +The following example references `item` first in an interpolation +and then passes in a binding to the `item` property of the `` component. + + + +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. + + + +
    + +`NgFor` is implemented by the `NgForOf` directive. Read more about the other `NgForOf` context values such as `last`, `even`, +and `odd` in the [NgForOf API reference](api/common/NgForOf). + +
    + +{@a 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`. + + + +In the microsyntax expression, set `trackBy` to the `trackByItems()` method. + + + +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. + + + + +
    + +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. + +
    + +
    + +{@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. + +`NgSwitch` is actually a set of three, cooperating directives: +`NgSwitch`, `NgSwitchCase`, and `NgSwitchDefault` as in the following example. + + + + + +`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 `` switch case with the following. + + diff --git a/aio/content/guide/component-interaction.md b/aio/content/guide/component-interaction.md index 368a7beb4b..5e1fd33122 100644 --- a/aio/content/guide/component-interaction.md +++ b/aio/content/guide/component-interaction.md @@ -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). @@ -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`: diff --git a/aio/content/guide/displaying-data.md b/aio/content/guide/displaying-data.md index 4c2fb65e54..e7e78b1bf5 100644 --- a/aio/content/guide/displaying-data.md +++ b/aio/content/guide/displaying-data.md @@ -153,14 +153,14 @@ It marks that `
  • ` element (and its children) as the "repeater template":
    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.
    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 `
  • ` 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:
    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.
    @@ -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).
    diff --git a/aio/content/guide/event-binding.md b/aio/content/guide/event-binding.md new file mode 100644 index 0000000000..40af4f6055 --- /dev/null +++ b/aio/content/guide/event-binding.md @@ -0,0 +1,108 @@ +# Event binding `(event)` + +Event binding allows you to listen for certain events such as +keystrokes, mouse movements, clicks, and touches. + +
    + +See the for a working example containing the code snippets in this guide. + +
    + +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: + + + +## Target event + +As above, the target is the button's click event. + + + +Alternatively, use the `on-` prefix, known as the canonical form: + + + +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: + + + +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: + + + +This code sets the `` `value` property by binding to the `name` property. +To listen for changes to the value, the code binds to the `input` +event of the `` 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`: + + + + + +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`. + + + +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. diff --git a/aio/content/guide/forms.md b/aio/content/guide/forms.md index 6fd30c28ab..2ce25ce295 100644 --- a/aio/content/guide/forms.md +++ b/aio/content/guide/forms.md @@ -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 `
    ` tag in the template (because `NgForm` has the selector `form` that matches `` 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`. diff --git a/aio/content/guide/glossary.md b/aio/content/guide/glossary.md index 8f7f45e359..06f1f157f7 100644 --- a/aio/content/guide/glossary.md +++ b/aio/content/guide/glossary.md @@ -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} diff --git a/aio/content/guide/inputs-outputs.md b/aio/content/guide/inputs-outputs.md new file mode 100644 index 0000000000..6841f7b714 --- /dev/null +++ b/aio/content/guide/inputs-outputs.md @@ -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. + +
    + +See the for a working example containing the code snippets in this guide. + +
    + +Consider this example of a child/parent relationship: + +```html + + + + +``` + +Here, the `` selector, or child directive, is embedded +within a ``, 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. + +
    + +#### `@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()`. + +
    + +{@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. + + + + +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()`: + + + + +In this case, `@Input()` decorates the property item, 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: + + + + + +### 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 ``, 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. + + + +Next, in the parent component class, `app.component.ts`, designate a value for `currentItem`: + + + +With `@Input()`, Angular passes the value for `currentItem` to the child so that `item` renders as `Television`. + +The following diagram shows this structure: + + + +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. + +
    + +### `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. + +
    + +{@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). + + + + +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 `` to an array in the +parent component. + +
    + +The HTML element `` 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 ``, see the [W3C Recommendation](https://www.w3.org/TR/html5/sec-forms.html#the-input-element). + +
    + +## In the child + +This example features an `` where a user can enter a value and click a `
    diff --git a/aio/content/guide/svg-in-templates.md b/aio/content/guide/svg-in-templates.md new file mode 100644 index 0000000000..a8af2836f7 --- /dev/null +++ b/aio/content/guide/svg-in-templates.md @@ -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. + +
    + +See the for a working example containing the code snippets in this guide. + +
    + +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: + + + +Add the following code to your `svg.component.svg` file: + + + +Here you can see the use of a `click()` event binding and the property binding syntax +(`[attr.fill]="fillColor"`). diff --git a/aio/content/guide/template-expression-operators.md b/aio/content/guide/template-expression-operators.md new file mode 100644 index 0000000000..ef58d02d66 --- /dev/null +++ b/aio/content/guide/template-expression-operators.md @@ -0,0 +1,144 @@ + + +# 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) + +
    + +See the for a working example containing the code snippets in this guide. + +
    + +{@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 (`|`): + + + +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: + + + +And you can also [apply parameters](guide/pipes#parameterizing-a-pipe) to a pipe: + + + +The `json` pipe is particularly helpful for debugging bindings: + + + +The generated output would look something like this: + + + { "name": "Telephone", + "manufactureDate": "1980-02-25T05:00:00.000Z", + "price": 98 } + + +
    + +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. + +
    + + +
    + +{@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`. + + + +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`. + + + The null item name is {{nullItem.name}} + + +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: + + + TypeError: Cannot read property 'name' of null. + + +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`. + + +
    + +{@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. + + + +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: + + + +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. + + + +The `$any()` cast function works anywhere in a binding expression where a method call is valid. + diff --git a/aio/content/guide/template-reference-variables.md b/aio/content/guide/template-reference-variables.md new file mode 100644 index 0000000000..144bbfcf1e --- /dev/null +++ b/aio/content/guide/template-reference-variables.md @@ -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 web component. + +
    + +See the for a working example containing the code snippets in this guide. + +
    + +Use the hash symbol (#) to declare a reference variable. +The following reference variable, `#phone`, declares a `phone` variable on an `` element. + + + +You can refer to a template reference variable anywhere in the component's template. +Here, a `