-
-
-
-
- ### ng-if
-
-
- <table ng-if="movies.length">
-
-
-
- In AngularJS, the `ng-if` directive removes or recreates a portion of the DOM,
- based on an expression. If the expression is false, the element is removed from the DOM.
-
- In this example, the `` element is removed from the DOM unless the `movies` array has a length greater than zero.
-
-
-
-
-
- ### *ngIf
-
-
-
-
- The `*ngIf` directive in Angular works the same as the `ng-if` directive in AngularJS. It removes
- or recreates a portion of the DOM based on an expression.
-
- In this example, the `` element is removed from the DOM unless the `movies` array has a length.
-
- The (*) before `ngIf` is required in this example.
- For more information, see [Structural Directives](guide/structural-directives).
-
-
-
-
-
-
-
-
-
- ### ng-model
-
-
- <input ng-model="vm.favoriteHero"/>
-
-
-
- In AngularJS, the `ng-model` directive binds a form control to a property in the controller associated with the template.
- This provides **two-way binding**, whereby any change made to the value in the view is synchronized with the model, and any change to the model is synchronized with the value in the view.
-
-
-
-
-
- ### ngModel
-
-
-
-
- In Angular, **two-way binding** is denoted by `[()]`, descriptively referred to as a "banana in a box". This syntax is a shortcut for defining both property binding (from the component to the view)
- 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/built-in-directives#ngModel)
- section of the [Built-in directives](guide/built-in-directives) page.
-
-
-
-
-
-
-
-
-
- ### ng-repeat
-
-
- <tr ng-repeat="movie in vm.movies">
-
-
-
- In AngularJS, the `ng-repeat` directive repeats the associated DOM element
- for each item in the specified collection.
-
- In this example, the table row (` `) element repeats for each movie object in the collection of movies.
-
-
-
-
-
- ### *ngFor
-
-
-
-
- The `*ngFor` directive in Angular is similar to the `ng-repeat` directive in AngularJS. It repeats
- the associated DOM element for each item in the specified collection.
- More accurately, it turns the defined element (` ` in this example) and its contents into a template and
- uses that template to instantiate a view for each item in the list.
-
- Notice the other syntax differences:
- The (*) before `ngFor` is required;
- the `let` keyword identifies `movie` as an input variable;
- the list preposition is `of`, not `in`.
-
- For more information, see [Structural Directives](guide/structural-directives).
-
-
-
-
-
-
-
-
-
- ### ng-show
-
-
- <h3 ng-show="vm.favoriteHero">
- Your favorite hero is: {{vm.favoriteHero}}
- </h3>
-
-
-
- In AngularJS, the `ng-show` directive shows or hides the associated DOM element, based on
- an expression.
-
- In this example, the `` element is shown if the `favoriteHero` variable is truthy.
-
-
-
-
-
- ### Bind to the `hidden` property
-
-
-
-
- Angular uses property binding; there is no built-in *show* directive.
- For hiding and showing elements, bind to the HTML `hidden` property.
-
- To conditionally display an element, place the element's `hidden` property in square brackets and
- set it to a quoted template expression that evaluates to the *opposite* of *show*.
-
- In this example, the `` element is hidden if the `favoriteHero` variable is not truthy.
+| AngularJS | Angular |
+|:--- |:--- |
+| <body ng-app="movieHunter"> The application startup process is called **bootstrapping**. Although you can bootstrap an AngularJS application in code, many applications bootstrap declaratively with the `ng-app` directive, giving it the name of the module \(`movieHunter`\) of the application. | Angular does not have a bootstrap directive. To launch the application in code, explicitly bootstrap the root module \(`AppModule`\) of the application in `main.ts` and the root component \(`AppComponent`\) of the application in `app.module.ts`. |
- For more information on property binding, see the [Property binding](guide/property-binding) page.
-
+### `ng-class` → `ngClass`
-
+| AngularJS | Angular |
+|:--- |:--- |
+| <div ng-class="{active: isActive}"> 
 <div ng-class="{active: isActive, shazam: isImportant}"> In AngularJS, the `ng-class` directive includes/excludes CSS classes based on an expression. That expression is often a key-value control object with each key of the object defined as a CSS class name, and each value defined as a template expression that evaluates to a Boolean value. In the first example, the `active` class is applied to the element if `isActive` is true. You can specify multiple classes, as shown in the second example. | In Angular, the `ngClass` directive works similarly. It includes/excludes CSS classes based on an expression. In the first example, the `active` class is applied to the element if `isActive` is true. You can specify multiple classes, as shown in the second example. 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 [Attribute, class, and style bindings][AioGuideAttributeBinding] page. |
-
+### `ng-click` → Bind to the `click` event
-
+| AngularJS | Angular |
+|:--- |:--- |
+| <button ng-click="vm.toggleImage()"> 
 <button ng-click="vm.toggleImage($event)"> In AngularJS, the `ng-click` directive allows you to specify custom behavior when an element is clicked. In the first example, when the user clicks the button, the `toggleImage()` method in the controller referenced by the `vm` `controller as` alias is executed. The second example demonstrates passing in the `$event` object, which provides details about the event to the controller. | AngularJS event-based directives do not exist in Angular. Rather, define one-way binding from the template view to the component using **event binding**. For event binding, define the name of the target event within parenthesis and specify a template statement, in quotes, to the right of the equals. Angular then sets up an event handler for the target event. When the event is raised, the handler executes the template statement. In the first example, when a user clicks the button, the `toggleImage()` method in the associated component is executed. The second example demonstrates passing in the `$event` object, which provides details about the event to the component. For a list of DOM events, see [Event reference][MdnDocsWebEvents]. For more information, see the [Event binding][AioGuideEventBinding] page. |
+### `ng-controller` → Component decorator
- ### ng-src
+| AngularJS | Angular |
+|:--- |:--- |
+| <div ng-controller="MovieListCtrl as vm"> In AngularJS, the `ng-controller` directive attaches a controller to the view. Using the `ng-controller` \(or defining the controller as part of the routing\) ties the view to the controller code associated with that view. | In Angular, the template no longer specifies its associated controller. Rather, the component specifies its associated template as part of the component class decorator. For more information, see [Architecture Overview][AioGuideArchitectureComponents]. |
-
- <img ng-src="{{movie.imageurl}}">
-
+### `ng-hide` → Bind to the `hidden` property
+| AngularJS | Angular |
+|:--- |:--- |
+| In AngularJS, the `ng-hide` directive shows or hides the associated HTML element based on an expression. For more information, see [ng-show][AioGuideAjsQuickReferenceTemplateDirectives]. | Bind to the hidden
property In Angular, you use property binding; there is no built-in *hide* directive. For more information, see [ng-show][AioGuideAjsQuickReferenceTemplateDirectives]. |
- The `ng-src` directive allows AngularJS to preprocess the `src` property so that it
- can replace the binding expression with the appropriate URL before the browser
- fetches from that URL.
-
+### `ng-href` → Bind to the `href` property
-
+| AngularJS | Angular |
+|:--- |:--- |
+| <a ng-href="{{ angularDocsUrl }}"> 
 Angular Docs 
 </a> The `ng-href` directive allows AngularJS to preprocess the `href` property so that it can replace the binding expression with the appropriate URL before the browser fetches from that URL. In AngularJS, the `ng-href` is often used to activate a route as part of navigation. <a ng-href="#{{ moviesHash }}"> 
 Movies 
</a> Routing is handled differently in Angular. | Bind to the href
property Angular uses property binding; there is no built-in *href* directive. Place the `href` property of the element in square brackets and set it to a quoted template expression. For more information see the [Property binding][AioGuidePropertyBinding] page. In Angular, `href` is no longer used for routing. Routing uses `routerLink`, as shown in the following example. For more information on routing, see [Defining a basic route][AioGuideRouterDefiningABasicRoute] in the [Routing & Navigation][AioGuideRouter] page. |
+### `ng-if` → `*ngIf`
- ### Bind to the `src` property
+| AngularJS | Angular |
+|:--- |:--- |
+| <table ng-if="movies.length"> In AngularJS, the `ng-if` directive removes or recreates a portion of the DOM, based on an expression. If the expression is false, the element is removed from the DOM. In this example, the `` element is removed from the DOM unless the `movies` array has a length greater than zero. | The `*ngIf` directive in Angular works the same as the `ng-if` directive in AngularJS. It removes or recreates a portion of the DOM based on an expression. In this example, the `` element is removed from the DOM unless the `movies` array has a length. The \(`*`\) before `ngIf` is required in this example. For more information, see [Structural Directives][AioGuideStructuralDirectives]. |
-
+### `ng-model` → `ngModel`
+| AngularJS | Angular |
+|:--- |:--- |
+| <input ng-model="vm.favoriteHero" /> In AngularJS, the `ng-model` directive binds a form control to a property in the controller associated with the template. This provides **two-way binding**, whereby any change made to the value in the view is synchronized with the model, and any change to the model is synchronized with the value in the view. | In Angular, **two-way binding** is indicatedr5t by `[()]`, descriptively referred to as a "banana in a box". This syntax is a shortcut for defining both property binding \(from the component to the view\) 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 [Displaying and updating properties with `ngModel`][AioGuideBuiltInDirectivesDisplayingAndUpdatingPropertiesWithNgmodel] section of [Built-in directives][AioGuideBuiltInDirectives]. |
- 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.
+### `ng-repeat` → `*ngFor`
- For more information on property binding, see the [Property binding](guide/property-binding) page.
-
+| AngularJS | Angular |
+|:--- |:--- |
+| <tr ng-repeat="movie in vm.movies"> In AngularJS, the `ng-repeat` directive repeats the associated DOM element for each item in the specified collection. In this example, the table row \(``\) element repeats for each movie object in the collection of movies. | The `*ngFor` directive in Angular is similar to the `ng-repeat` directive in AngularJS. It repeats the associated DOM element for each item in the specified collection. More accurately, it turns the defined element \(` ` in this example\) and its contents into a template and uses that template to instantiate a view for each item in the list. Notice the other syntax differences: The \(`*`\) before `ngFor` is required; the `let` keyword identifies `movie` as an input variable; the list preposition is `of`, not `in`. For more information, see [Structural Directives][AioGuideStructuralDirectives]. |
-
+### `ng-show` → Bind to the `hidden` property
-
+| AngularJS | Angular |
+|:--- |:--- |
+| <h3 ng-show="vm.favoriteHero"> 
 Your favorite hero is: {{vm.favoriteHero}} 
 </h3> In AngularJS, the `ng-show` directive shows or hides the associated DOM element, based on an expression. In this example, the `` element is shown if the `favoriteHero` variable is truthy. |
Bind to the hidden
property Angular uses property binding; there is no built-in *show* directive. For hiding and showing elements, bind to the HTML `hidden` property.
To conditionally display an element, place the `hidden` property of the element in square brackets and set it to a quoted template expression that evaluates to the *opposite* of *show*.
In this example, the `
` element is hidden if the `favoriteHero` variable is not truthy. For more information on property binding, see the [Property binding][AioGuidePropertyBinding] page. |
-
+### `ng-src` → Bind to the `src` property
+| AngularJS | Angular |
+|:--- |:--- |
+| <img ng-src="{{movie.imageurl}}"> The `ng-src` directive allows AngularJS to preprocess the `src` property so that it can replace the binding expression with the appropriate URL before the browser fetches from that URL. | 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][AioGuidePropertyBinding] page. |
- ### ng-style
+### `ng-style` → `ngStyle`
-
- <div ng-style="{color: colorPreference}">
-
-
-
- In AngularJS, the `ng-style` directive sets a CSS style on an HTML element
- based on an expression. That expression is often a key-value control object with each
- key of the object defined as a CSS property, and each value defined as an expression
- that evaluates to a value appropriate for the style.
-
- In the example, the `color` style is set to the current value of the `colorPreference` variable.
-
-
-
-
-
- ### ngStyle
-
-
-
-
- In Angular, the `ngStyle` directive works similarly. It sets a CSS style on an HTML element based on an expression.
-
- In the first example, the `color` style is set to the current value of the `colorPreference` variable.
-
- 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/attribute-binding#style-binding) section of the
- [Attribute binding](guide/attribute-binding) page.
-
- For more information on the `ngStyle` directive, see the [NgStyle](guide/built-in-directives#ngstyle)
- section of the [Built-in directives](guide/built-in-directives) page.
-
-
-
-
-
-
-
-
-
- ### ng-switch
-
-
- <div ng-switch="vm.favoriteHero &&
- vm.checkMovieHero(vm.favoriteHero)">
- <div ng-switch-when="true">
- Excellent choice!
- </div>
- <div ng-switch-when="false">
- No movie, sorry!
- </div>
- <div ng-switch-default>
- Please enter your favorite hero.
- </div>
- </div>
-
-
-
- In AngularJS, the `ng-switch` directive swaps the contents of
- an element by selecting one of the templates based on the current value of an expression.
-
- In this example, if `favoriteHero` is not set, the template displays "Please enter ...".
- If `favoriteHero` is set, it checks the movie hero by calling a controller method.
- If that method returns `true`, the template displays "Excellent choice!".
- If that methods returns `false`, the template displays "No movie, sorry!".
-
-
-
-
-
- ### ngSwitch
-
-
-
-
- In Angular, the `ngSwitch` directive works similarly.
- It displays an element whose `*ngSwitchCase` matches the current `ngSwitch` expression value.
-
- In this example, if `favoriteHero` is not set, the `ngSwitch` value is `null`
- and `*ngSwitchDefault` displays, "Please enter ...".
- If `favoriteHero` is set, the application checks the movie hero by calling a component method.
- If that method returns `true`, the application selects `*ngSwitchCase="true"` and displays: "Excellent choice!"
- If that methods returns `false`, the application selects `*ngSwitchCase="false"` and displays: "No movie, sorry!"
-
- The (*) before `ngSwitchCase` and `ngSwitchDefault` is required in this example.
-
- For more information, see [The NgSwitch directives](guide/built-in-directives#ngSwitch)
- section of the [Built-in directives](guide/built-in-directives) page.
-
-
-
-
-
-
-
-{@a filters-pipes}
+| AngularJS | Angular |
+|:--- |:--- |
+| <div ng-style="{color: colorPreference}"> In AngularJS, the `ng-style` directive sets a CSS style on an HTML element based on an expression. That expression is often a key-value control object with each key of the object defined as a CSS property, and each value defined as an expression that evaluates to a value appropriate for the style. In the example, the `color` style is set to the current value of the `colorPreference` variable. | In Angular, the `ngStyle` directive works similarly. It sets a CSS style on an HTML element based on an expression. In the first example, the `color` style is set to the current value of the `colorPreference` variable. 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][AioGuideAttributeBindingBindingToTheStyleAttribute] section of the [Attribute binding][AioGuideAttributeBinding] page. For more information on the `ngStyle` directive, see the [NgStyle][AioGuideBuiltInDirectivesSettingInlineStylesWithNgstyle] section of the [Built-in directives][AioGuideBuiltInDirectives] page. |
+### `ng-switch` → `ngSwitch`
+| AngularJS | Angular |
+|:--- |:--- |
+| <div ng-switch="vm.favoriteHero && vm.checkMovieHero(vm.favoriteHero)"> 
 <div ng-switch-when="true"> 
 Excellent choice. 
 </div> 
 <div ng-switch-when="false"> 
 No movie, sorry. 
 </div> 
 <div ng-switch-default> 
 Please enter your favorite hero. 
 </div> 
 </div> In AngularJS, the `ng-switch` directive swaps the contents of an element by selecting one of the templates based on the current value of an expression. In this example, if `favoriteHero` is not set, the template displays "Please enter …". If `favoriteHero` is set, it checks the movie hero by calling a controller method. If that method returns `true`, the template displays "Excellent choice!". If that methods returns `false`, the template displays "No movie, sorry!". | In Angular, the `ngSwitch` directive works similarly. It displays an element whose `*ngSwitchCase` matches the current `ngSwitch` expression value. In this example, if `favoriteHero` is not set, the `ngSwitch` value is `null` and `*ngSwitchDefault` displays, "Please enter …". If `favoriteHero` is set, the application checks the movie hero by calling a component method. If that method returns `true`, the application selects `*ngSwitchCase="true"` and displays: "Excellent choice!" If that methods returns `false`, the application selects `*ngSwitchCase="false"` and displays: "No movie, sorry!" The \(`*`\) before `ngSwitchCase` and `ngSwitchDefault` is required in this example. For more information, see [The NgSwitch directives][AioGuideBuiltInDirectivesSwitchingCasesWithNgswitch] section of the [Built-in directives][AioGuideBuiltInDirectives] page. |
## Filters/pipes
+
Angular **pipes** provide formatting and transformation for data in the template, similar to AngularJS **filters**.
Many of the built-in filters in AngularJS have corresponding pipes in Angular.
-For more information on pipes, see [Pipes](guide/pipes).
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- AngularJS
-
-
-
- Angular
-
-
-
-
-
-
-
-
-
- ### currency
-
-
- <td>{{movie.price | currency}}</td>
-
-
-
- Formats a number as currency.
-
-
-
-
-
- ### currency
-
-
-
-
- The Angular `currency` pipe is similar although some of the parameters have changed.
-
-
-
-
-
-
-
-
-
- ### date
-
-
- <td>{{movie.releaseDate | date}}</td>
-
-
-
- Formats a date to a string based on the requested format.
-
-
-
-
-
- ### date
-
-
-
-
- The Angular `date` pipe is similar.
-
-
-
-
-
-
-
-
-
-
- ### filter
-
-
- <tr ng-repeat="movie in movieList | filter: {title:listFilter}">
-
-
-
- Selects a subset of items from the defined collection, based on the filter criteria.
-
-
-
-
-
- ### none
- For performance reasons, no comparable pipe exists in Angular. Do all your filtering in the component. If you need the same filtering code in several templates, consider building a custom pipe.
-
-
-
-
-
-
-
-
-
-
- ### json
-
-
- <pre>{{movie | json}}</pre>
-
-
-
- Converts a JavaScript object into a JSON string. This is useful for debugging.
-
-
-
-
-
- ### json
-
-
-
-
- The Angular [`json`](api/common/JsonPipe) pipe does the same thing.
-
-
-
-
-
-
-
-
-
- ### limitTo
-
-
- <tr ng-repeat="movie in movieList | limitTo:2:0">
-
-
-
- Selects up to the first parameter (2) number of items from the collection
- starting (optionally) at the beginning index (0).
-
-
-
-
-
- ### slice
-
-
-
-
- The `SlicePipe` does the same thing but the *order of the parameters is reversed*, in keeping
- with the JavaScript `Slice` method.
- The first parameter is the starting index; the second is the limit.
- As in AngularJS, coding this operation within the component instead could improve performance.
-
-
-
-
-
-
-
-
-
- ### lowercase
+For more information on pipes, see [Pipes][AioGuidePipes].
-
- <td>{{movie.title | lowercase}}</td>
-
+### `currency` → `currency`
+| AngularJS | Angular |
+|:--- |:--- |
+| <td> 
 {{movie.price | currency}} 
 </td> Formats a number as currency. | The Angular `currency` pipe is similar although some of the parameters have changed. |
- Converts the string to lowercase.
-
+### `date` → `date`
-
+| AngularJS | Angular |
+|:--- |:--- |
+| <td> 
 {{movie.releaseDate | date}} 
 </td> Formats a date to a string based on the requested format. | The Angular `date` pipe is similar. |
+### `filter` → none
- ### lowercase
+| AngularJS | Angular |
+|:--- |:--- |
+| <tr ng-repeat="movie in movieList | filter: {title:listFilter}"> Selects a subset of items from the defined collection, based on the filter criteria. | For performance reasons, no comparable pipe exists in Angular. Do all your filtering in the component. If you need the same filtering code in several templates, consider building a custom pipe. |
-
+### `json` → `json`
+| AngularJS | Angular |
+|:--- |:--- |
+| <pre> 
 {{movie | json}} 
 </pre> Converts a JavaScript object into a JSON string. This is useful for debugging. | The Angular [`json`][AioApiCommonJsonpipe] pipe does the same thing. |
- The Angular `lowercase` pipe does the same thing.
-
+### `limitTo` → `slice`
-
+| AngularJS | Angular |
+|:--- |:--- |
+| <tr ng-repeat="movie in movieList | limitTo:2:0"> Selects up to the first parameter \(2\) number of items from the collection starting \(optionally\) at the beginning index \(0\). | The `SlicePipe` does the same thing but the *order of the parameters is reversed*, in keeping with the JavaScript `Slice` method. The first parameter is the starting index; the second is the limit. As in AngularJS, coding this operation within the component instead could improve performance. |
-
+### `lowercase` → `lowercase`
-
+| AngularJS | Angular |
+|:--- |:--- |
+| <td> 
 {{movie.title | lowercase}} 
 </td> Converts the string to lowercase. | The Angular `lowercase` pipe does the same thing. |
+### `number` → `number`
- ### number
-
-
- <td>{{movie.starRating | number}}</td>
-
-
-
- Formats a number as text.
-
-
-
-
-
- ### number
-
-
-
-
- The Angular [`number`](api/common/DecimalPipe) pipe is similar.
- It provides more functionality when defining
- the decimal places, as shown in the second example above.
-
- Angular also has a `percent` pipe, which formats a number as a local percentage
- as shown in the third example.
-
-
-
-
-
-
-
-
-
- ### orderBy
-
-
- <tr ng-repeat="movie in movieList | orderBy : 'title'">
-
-
-
- Displays the collection in the order specified by the expression.
- In this example, the movie title orders the `movieList`.
-
-
-
-
-
- ### none
- For performance reasons, no comparable pipe exists in Angular.
- Instead, use component code to order or sort results. If you need the same ordering or sorting code in several templates, consider building a custom pipe.
-
-
-
-
-
-
-
-
-
-{@a controllers-components}
+| AngularJS | Angular |
+|:--- |:--- |
+| <td> 
 {{movie.starRating | number}} 
 </td> Formats a number as text. | The Angular [`number`][AioApiCommonDecimalpipe] pipe is similar. It provides more functionality when defining the decimal places, as shown in the second example above. Angular also has a `percent` pipe, which formats a number as a local percentage as shown in the third example. |
+### `orderBy` → none
+| AngularJS | Angular |
+|:--- |:--- |
+| <tr ng-repeat="movie in movieList | orderBy : 'title'"> Displays the collection in the order specified by the expression. In this example, the movie title orders the `movieList`. | For performance reasons, no comparable pipe exists in Angular. Instead, use component code to order or sort results. If you need the same ordering or sorting code in several templates, consider building a custom pipe. |
## Modules/controllers/components
+
In both AngularJS and Angular, modules help you organize your application into cohesive blocks of functionality.
In AngularJS, you write the code that provides the model and the methods for the view in a **controller**.
@@ -985,282 +180,91 @@ In Angular, you build a **component**.
Because much AngularJS code is in JavaScript, JavaScript code is shown in the AngularJS column.
The Angular code is shown using TypeScript.
+### IIFE → none
-
-
-
-
-
-
-
-
-
-
-
-
-
- AngularJS
-
-
-
- Angular
-
-
-
-
-
-
-
-
-
- ### IIFE
-
-
- (function () {
- ...
- }());
-
-
-
- In AngularJS, an immediately invoked function expression (or IIFE) around controller code
- keeps it out of the global namespace.
-
-
-
-
-
-
- ### none
- This is a nonissue in Angular because ES 2015 modules
- handle the namespacing for you.
-
- For more information on modules, see the [Modules](guide/architecture#modules) section of the
- [Architecture Overview](guide/architecture).
-
-
-
-
-
-
-
-
-
- ### Angular modules
-
-
- angular.module("movieHunter", ["ngRoute"]);
-
-
-
- In AngularJS, an Angular module keeps track of controllers, services, and other code.
- The second argument defines the list of other modules that this module depends upon.
-
-
-
-
-
- ### NgModules
+| AngularJS | Angular |
+|:--- |:--- |
+| ( 
 function () { 
 … 
 }() 
); In AngularJS, an immediately invoked function expression \(or IIFE\) around controller code keeps it out of the global namespace. | This is a nonissue in Angular because ES 2015 modules handle the namespacing for you. For more information on modules, see the [Modules][AioGuideArchitectureModules] section of the [Architecture Overview][AioGuideArchitecture]. |
-
+### Angular modules → `NgModules`
+| AngularJS | Angular |
+|:--- |:--- |
+| angular .module( 
 "movieHunter", 
 [ 
 "ngRoute" 
 ] 
); In AngularJS, an Angular module keeps track of controllers, services, and other code. The second argument defines the list of other modules that this module depends upon. | NgModules, defined with the `NgModule` decorator, serve the same purpose: `imports`: specifies the list of other modules that this module depends upon `declaration`: keeps track of your components, pipes, and directives. For more information on modules, see [NgModules][AioGuideNgmodules]. |
- NgModules, defined with the `NgModule` decorator, serve the same purpose:
+### Controller registration → Component decorator
- * `imports`: specifies the list of other modules that this module depends upon
- * `declaration`: keeps track of your components, pipes, and directives.
+| AngularJS | Angular |
+|:--- |:--- |
+| angular .module( 
 "movieHunter" 
) .controller( 
 "MovieListCtrl", 
 [ 
 "movieService", 
 MovieListCtrl 
 ] 
); AngularJS has code in each controller that looks up an appropriate Angular module and registers the controller with that module. The first argument is the controller name. The second argument defines the string names of all dependencies injected into this controller, and a reference to the controller function. | Angular adds a decorator to the component class to provide any required metadata. The `@Component` decorator declares that the class is a component and provides metadata about that component such as its selector \(or tag\) and its template. This is how you associate a template with logic, which is defined in the component class. For more information, see the [Components][AioGuideArchitectureComponents] section of the [Architecture Overview][AioGuideArchitecture] page. |
- For more information on modules, see [NgModules](guide/ngmodules).
-
+### Controller function → Component class
-
-
-
-
-
-
-
- ### Controller registration
-
-
- angular
- .module("movieHunter")
- .controller("MovieListCtrl",
- ["movieService",
- MovieListCtrl]);
-
-
-
- AngularJS has code in each controller that looks up an appropriate Angular module
- and registers the controller with that module.
-
- The first argument is the controller name. The second argument defines the string names of
- all dependencies injected into this controller, and a reference to the controller function.
-
-
-
-
-
- ### Component decorator
-
-
-
-
- Angular adds a decorator to the component class to provide any required metadata.
- The `@Component` decorator declares that the class is a component and provides metadata about
- that component such as its selector (or tag) and its template.
-
- This is how you associate a template with logic, which is defined in the component class.
-
- For more information, see the [Components](guide/architecture#components)
- section of the [Architecture Overview](guide/architecture) page.
-
-
-
-
-
-
-
-
-
- ### Controller function
-
-
- function MovieListCtrl(movieService) {
- }
-
-
-
- In AngularJS, you write the code for the model and methods in a controller function.
-
-
-
-
-
- ### Component class
-
-
-
-
- In Angular, you create a component class to contain the data model and control methods. Use the TypeScript export
keyword to export the class so that the functionality can be imported into NgModules.
-
- For more information, see the [Components](guide/architecture#components)
- section of the [Architecture Overview](guide/architecture) page.
-
-
-
-
-
-
-
-
-
- ### Dependency injection
-
-
- MovieListCtrl.$inject = ['MovieService'];
- function MovieListCtrl(movieService) {
- }
-
-
-
- In AngularJS, you pass in any dependencies as controller function arguments.
- This example injects a `MovieService`.
-
- To guard against minification problems, tell Angular explicitly
- that it should inject an instance of the `MovieService` in the first parameter.
-
-
-
-
-
- ### Dependency injection
-
-
-
-
- In Angular, you pass in dependencies as arguments to the component class constructor.
- This example injects a `MovieService`.
- The first parameter's TypeScript type tells Angular what to inject, even after minification.
-
- For more information, see the [Dependency injection](guide/architecture#dependency-injection)
- section of the [Architecture Overview](guide/architecture).
-
-
-
-
-
-
-{@a style-sheets}
+| AngularJS | Angular |
+|:--- |:--- |
+| function MovieListCtrl(movieService) { 
 } In AngularJS, you write the code for the model and methods in a controller function. | In Angular, you create a component class to contain the data model and control methods. Use the TypeScript export
keyword to export the class so that the functionality can be imported into NgModules. For more information, see the [Components][AioGuideArchitectureComponents] section of the [Architecture Overview][AioGuideArchitecture] page. |
+### Dependency injection → Dependency injection
+| AngularJS | Angular |
+|:--- |:--- |
+| MovieListCtrl.$inject = [ 
 'MovieService' 
]; 
function MovieListCtrl(movieService) { 
} In AngularJS, you pass in any dependencies as controller function arguments. This example injects a `MovieService`. To guard against minification problems, tell Angular explicitly that it should inject an instance of the `MovieService` in the first parameter. | In Angular, you pass in dependencies as arguments to the component class constructor. This example injects a `MovieService`. The TypeScript type of the first parameter tells Angular what to inject, even after minification. For more information, see the [Dependency injection][AioGuideArchitectureServicesAndDependencyInjection] section of the [Architecture Overview][AioGuideArchitecture]. |
## Style sheets
+
Style sheets give your application a nice look.
In AngularJS, you specify the style sheets for your entire application.
-As the application grows over time, the styles for the many parts of the application
-merge, which can cause unexpected results.
-In Angular, you can still define style sheets for your entire application. But now you can
-also encapsulate a style sheet within a specific component.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- AngularJS
-
-
-
- Angular
-
+As the application grows over time, the styles for the many parts of the application merge, which can cause unexpected results.
+In Angular, you can still define style sheets for your entire application.
+But now you can also encapsulate a style sheet within a specific component.
-
+### `Link` tag → `styles` configuration or `styleUrls`
-
+| AngularJS | Angular |
+|:--- |:--- |
+| <link href="styles.css" 
 rel="stylesheet" /> AngularJS, uses a `link` tag in the head section of the `index.html` file to define the styles for the application. | With the Angular CLI, you can configure your global styles in the `angular.json` file. You can rename the extension to `.scss` to use sass. In Angular, you can use the `styles` or `styleUrls` property of the `@Component` metadata to define a style sheet for a particular component. This allows you to set appropriate styles for individual components that will not leak into other parts of the application. |
-
+
+[AioApiCommonDecimalpipe]: api/common/DecimalPipe "DecimalPipe | @angular/common - API | Angular"
+[AioApiCommonJsonpipe]: api/common/JsonPipe "JsonPipe | @angular/common - API | Angular"
- ### Link tag
+[AioGuideAjsQuickReferenceFiltersPipes]: guide/ajs-quick-reference#filterspipes "Filters/pipes - AngularJS to Angular concepts: Quick reference | Angular"
+[AioGuideAjsQuickReferenceTemplateDirectives]: guide/ajs-quick-reference#template-directives "Template directives - AngularJS to Angular concepts: Quick reference | Angular"
-
- <link href="styles.css" rel="stylesheet" />
-
+[AioGuideArchitecture]: guide/architecture "Introduction to Angular concepts | Angular"
+[AioGuideArchitectureComponents]: guide/architecture#components "Components - Introduction to Angular concepts | Angular"
+[AioGuideArchitectureModules]: guide/architecture#modules "Modules - Introduction to Angular concepts | Angular"
+[AioGuideArchitectureServicesAndDependencyInjection]: guide/architecture#services-and-dependency-injection "Services and dependency injection - Introduction to Angular concepts | Angular"
+[AioGuideAttributeBinding]: guide/attribute-binding "Attribute, class, and style bindings | Angular"
+[AioGuideAttributeBindingBindingToTheStyleAttribute]: guide/attribute-binding#binding-to-the-style-attribute "Binding to the style attribute - Attribute, class, and style bindings | Angular"
- AngularJS, uses a `link` tag in the head section of the `index.html` file
- to define the styles for the application.
-
+[AioGuideBuiltInDirectives]: guide/built-in-directives "Built-in directives | Angular"
+[AioGuideBuiltInDirectivesDisplayingAndUpdatingPropertiesWithNgmodel]: guide/built-in-directives#displaying-and-updating-properties-with-ngmodel "Displaying and updating properties with ngModel - Built-in directives | Angular"
+[AioGuideBuiltInDirectivesSettingInlineStylesWithNgstyle]: guide/built-in-directives#setting-inline-styles-with-ngstyle "Setting inline styles with NgStyle - Built-in directives | Angular"
+[AioGuideBuiltInDirectivesSwitchingCasesWithNgswitch]: guide/built-in-directives#switching-cases-with-ngswitch "Switching cases with NgSwitch - Built-in directives | Angular"
-
+[AioGuideEventBinding]: guide/event-binding "Event binding | Angular"
+[AioGuideInterpolation]: guide/interpolation "Text interpolation | Angular"
+[AioGuideNgmodules]: guide/ngmodules "NgModules | Angular"
- ### Styles configuration
-
+[AioGuidePipes]: guide/pipes "Transforming Data Using Pipes | Angular"
- With the Angular CLI, you can configure your global styles in the `angular.json` file.
- You can rename the extension to `.scss` to use sass.
+[AioGuidePropertyBinding]: guide/property-binding "Property binding | Angular"
- ### StyleUrls
- In Angular, you can use the `styles` or `styleUrls` property of the `@Component` metadata to define
- a style sheet for a particular component.
+[AioGuideRouter]: guide/router "Common Routing Tasks | Angular"
+[AioGuideRouterDefiningABasicRoute]: guide/router#defining-a-basic-route "Defining a basic route - Common Routing Tasks | Angular"
-
+[AioGuideStructuralDirectives]: guide/structural-directives "Writing structural directives | Angular"
+[AioGuideStructuralDirectivesStructuralDirectiveShorthand]: guide/structural-directives#structural-directive-shorthand "Structural directive shorthand - Writing structural directives | Angular"
+
- This allows you to set appropriate styles for individual components that won’t leak into
- other parts of the application.
-
+[MdnDocsWebEvents]: https://developer.mozilla.org/docs/Web/Events "Event reference | MDN"
-
+
-
+@reviewed 2022-02-28
diff --git a/aio/content/guide/angular-compiler-options.md b/aio/content/guide/angular-compiler-options.md
index b6d2a844dfc0b..9ee36e6961cb7 100644
--- a/aio/content/guide/angular-compiler-options.md
+++ b/aio/content/guide/angular-compiler-options.md
@@ -4,9 +4,9 @@ When you use [AOT compilation](guide/aot-compiler), you can control how your app
The template options object, `angularCompilerOptions`, is a sibling to the `compilerOptions` object that supplies standard options to the TypeScript compiler.
-
+
-{@a tsconfig-extends}
+
## Configuration inheritance with extends
@@ -18,7 +18,7 @@ The configuration options from the base file are loaded first, then overridden b
For example:
-
+
For more information, see the [TypeScript Handbook](https://www.typescriptlang.org/docs/handbook/tsconfig-json.html).
@@ -28,45 +28,66 @@ The following options are available for configuring the AOT template compiler.
### `allowEmptyCodegenFiles`
-When `true`, generate all possible files even if they are empty. Default is `false`. Used by the Bazel build rules to simplify how Bazel rules track file dependencies. Do not use this option outside of the Bazel rules.
+When `true`, generate all possible files even if they are empty.
+Default is `false`.
+Used by the Bazel build rules to simplify how Bazel rules track file dependencies.
+Do not use this option outside of the Bazel rules.
### `annotationsAs`
-Modifies how Angular-specific annotations are emitted to improve tree-shaking. Non-Angular annotations are not affected. One of `static fields` (the default) or `decorators`.
+Modifies how Angular-specific annotations are emitted to improve tree-shaking.
+Non-Angular annotations are not affected.
+One of `static fields` \(the default\) or `decorators`.
-* By default, the compiler replaces decorators with a static field in the class, which allows advanced tree-shakers like [Closure compiler](https://github.com/google/closure-compiler) to remove unused classes.
-* The `decorators` value leaves the decorators in place, which makes compilation faster. TypeScript emits calls to the `__decorate` helper. Use `--emitDecoratorMetadata` for runtime reflection (but note that the resulting code will not properly tree-shake.
+* By default, the compiler replaces decorators with a static field in the class, which allows advanced tree-shakers like [Closure compiler](https://github.com/google/closure-compiler) to remove unused classes
+* The `decorators` value leaves the decorators in place, which makes compilation faster.
+ TypeScript emits calls to the `__decorate` helper.
+ Use `--emitDecoratorMetadata` for runtime reflection.
+
+
+
+ **NOTE**:
+ That the resulting code will not properly tree-shake.
+
+
### `annotateForClosureCompiler`
-When `true`, use [Tsickle](https://github.com/angular/tsickle) to annotate the emitted JavaScript with [JSDoc](https://jsdoc.app/) comments needed by the
-[Closure Compiler](https://github.com/google/closure-compiler). Default is `false`.
+When `true`, use [Tsickle](https://github.com/angular/tsickle) to annotate the emitted JavaScript with [JSDoc](https://jsdoc.app) comments needed by the [Closure Compiler](https://github.com/google/closure-compiler).
+Default is `false`.
### `compilationMode`
-Specifies the compilation mode to use. The following modes are available:
+Specifies the compilation mode to use.
+The following modes are available:
-* `'full'`: generates fully AOT-compiled code according to the version of Angular that is currently being used.
-* `'partial'`: generates code in a stable, but intermediate form suitable for a published library.
+| Modes | Details |
+|:--- |:--- |
+| `'full'` | Generates fully AOT-compiled code according to the version of Angular that is currently being used. |
+| `'partial'` | Generates code in a stable, but intermediate form suitable for a published library. |
The default value is `'full'`.
### `disableExpressionLowering`
-When `true` (the default), transforms code that is or could be used in an annotation, to allow it to be imported from template factory modules. See [metadata rewriting](guide/aot-compiler#metadata-rewriting) for more information.
+When `true` \(the default\), transforms code that is or could be used in an annotation, to allow it to be imported from template factory modules.
+See [metadata rewriting](guide/aot-compiler#metadata-rewriting) for more information.
When `false`, disables this rewriting, requiring the rewriting to be done manually.
### `disableTypeScriptVersionCheck`
-When `true`, the compiler does not check the TypeScript version and does not report an error when an unsupported version of TypeScript is used. Not recommended, as unsupported versions of TypeScript might have undefined behavior. Default is `false`.
+When `true`, the compiler does not check the TypeScript version and does not report an error when an unsupported version of TypeScript is used.
+Not recommended, as unsupported versions of TypeScript might have undefined behavior.
+Default is `false`.
### `enableI18nLegacyMessageIdFormat`
Instructs the Angular template compiler to generate legacy ids for messages that are tagged in templates by the `i18n` attribute.
See [Mark text for translations][AioGuideI18nCommonPrepareMarkTextInComponentTemplate] for more information about marking messages for localization.
-Set this option to `false` unless your project relies upon translations that were previously generated using legacy IDs. Default is `true`.
+Set this option to `false` unless your project relies upon translations that were previously generated using legacy IDs.
+Default is `true`.
The pre-Ivy message extraction tooling generated a variety of legacy formats for extracted message IDs.
These message formats have a number of issues, such as whitespace handling and reliance upon information inside the original HTML of a template.
@@ -82,21 +103,28 @@ When enabled, the `.js` output of `ngc` does not include any lazy-loaded templat
For library projects generated with the CLI, the development configuration default is `true`.
-{@a enablelegacytemplate}
+
### `enableLegacyTemplate`
-When `true`, enables use of the `` element, which was deprecated in Angular 4.0, in favor of `` (to avoid colliding with the DOM's element of the same name). Default is `false`. Might be required by some third-party Angular libraries.
+When `true`, enables use of the `` element, which was deprecated in Angular 4.0, in favor of `` \(to avoid colliding with the DOM's element of the same name\).
+Default is `false`.
+Might be required by some third-party Angular libraries.
### `flatModuleId`
-The module ID to use for importing a flat module (when `flatModuleOutFile` is `true`). References generated by the template compiler use this module name when importing symbols from the flat module. Ignored if `flatModuleOutFile` is `false`.
+The module ID to use for importing a flat module \(when `flatModuleOutFile` is `true`\).
+References generated by the template compiler use this module name when importing symbols from the flat module.
+Ignored if `flatModuleOutFile` is `false`.
### `flatModuleOutFile`
-When `true`, generates a flat module index of the given file name and the corresponding flat module metadata. Use to create flat modules that are packaged similarly to `@angular/core` and `@angular/common`. When this option is used, the `package.json` for the library should refer to the generated flat module index instead of the library index file.
+When `true`, generates a flat module index of the given file name and the corresponding flat module metadata.
+Use to create flat modules that are packaged similarly to `@angular/core` and `@angular/common`.
+When this option is used, the `package.json` for the library should refer to the generated flat module index instead of the library index file.
-Produces only one `.metadata.json` file, which contains all the metadata necessary for symbols exported from the library index. In the generated `.ngfactory.js` files, the flat module index is used to import symbols that include both the public API from the library index as well as shrowded internal symbols.
+Produces only one `.metadata.json` file, which contains all the metadata necessary for symbols exported from the library index.
+In the generated `.ngfactory.js` files, the flat module index is used to import symbols that include both the public API from the library index as well as shrowded internal symbols.
By default the `.ts` file supplied in the `files` field is assumed to be the library index.
If more than one `.ts` file is specified, `libraryIndex` is used to select the file to use.
@@ -105,12 +133,13 @@ If more than one `.ts` file is supplied without a `libraryIndex`, an error is pr
A flat module index `.d.ts` and `.js` is created with the given `flatModuleOutFile` name in the same location as the library index `.d.ts` file.
For example, if a library uses the `public_api.ts` file as the library index of the module, the `tsconfig.json` `files` field would be `["public_api.ts"]`.
-The `flatModuleOutFile` option could then be set to (for example) `"index.js"`, which produces `index.d.ts` and `index.metadata.json` files.
+The `flatModuleOutFile` option could then be set to \(for example\) `"index.js"`, which produces `index.d.ts` and `index.metadata.json` files.
The `module` field of the library's `package.json` would be `"index.js"` and the `typings` field would be `"index.d.ts"`.
### `fullTemplateTypeCheck`
-When `true` (recommended), enables the [binding expression validation](guide/aot-compiler#binding-expression-validation) phase of the template compiler, which uses TypeScript to validate binding expressions. For more information, see [Template type checking](guide/template-typecheck).
+When `true` \(recommended\), enables the [binding expression validation](guide/aot-compiler#binding-expression-validation) phase of the template compiler, which uses TypeScript to validate binding expressions.
+For more information, see [Template type checking](guide/template-typecheck).
Default is `false`, but when you use the CLI command `ng new --strict`, it is set to `true` in the generated project's configuration.
@@ -122,28 +151,34 @@ The `fullTemplateTypeCheck` option has been deprecated in Angular 13 in favor of
### `generateCodeForLibraries`
-When `true` (the default), generates factory files (`.ngfactory.js` and `.ngstyle.js`) for `.d.ts` files with a corresponding `.metadata.json` file.
+When `true` \(the default\), generates factory files \(`.ngfactory.js` and `.ngstyle.js`\) for `.d.ts` files with a corresponding `.metadata.json` file.
-When `false`, factory files are generated only for `.ts` files. Do this when using factory summaries.
+When `false`, factory files are generated only for `.ts` files.
+Do this when using factory summaries.
### `preserveWhitespaces`
-When `false` (the default), removes blank text nodes from compiled templates, which results in smaller emitted template factory modules. Set to `true` to preserve blank text nodes.
+When `false` \(the default\), removes blank text nodes from compiled templates, which results in smaller emitted template factory modules.
+Set to `true` to preserve blank text nodes.
### `skipMetadataEmit`
-When `true`, does not produce `.metadata.json` files. Default is `false`.
+When `true`, does not produce `.metadata.json` files.
+Default is `false`.
The `.metadata.json` files contain information needed by the template compiler from a `.ts` file that is not included in the `.d.ts` file produced by the TypeScript compiler.
-This information includes, for example, the content of annotations (such as a component's template), which TypeScript emits to the `.js` file but not to the `.d.ts` file.
+This information includes, for example, the content of annotations \(such as a component's template\), which TypeScript emits to the `.js` file but not to the `.d.ts` file.
You can set to `true` when using factory summaries, because the factory summaries include a copy of the information that is in the `.metadata.json` file.
-Set to `true` if you are using TypeScript's `--outFile` option, because the metadata files are not valid for this style of TypeScript output. However, we do not recommend using `--outFile` with Angular. Use a bundler, such as [webpack](https://webpack.js.org/), instead.
+Set to `true` if you are using TypeScript's `--outFile` option, because the metadata files are not valid for this style of TypeScript output.
+However, we do not recommend using `--outFile` with Angular.
+Use a bundler, such as [webpack](https://webpack.js.org), instead.
### `skipTemplateCodegen`
-When `true`, does not emit `.ngfactory.js` and `.ngstyle.js` files. This turns off most of the template compiler and disables the reporting of template diagnostics.
+When `true`, does not emit `.ngfactory.js` and `.ngstyle.js` files.
+This turns off most of the template compiler and disables the reporting of template diagnostics.
Can be used to instruct the template compiler to produce `.metadata.json` files for distribution with an `npm` package while avoiding the production of `.ngfactory.js` and `.ngstyle.js` files that cannot be distributed to `npm`.
@@ -152,9 +187,12 @@ For library projects generated with the CLI, the development configuration defau
### `strictMetadataEmit`
When `true`, reports an error to the `.metadata.json` file if `"skipMetadataEmit"` is `false`.
-Default is `false`. Use only when `"skipMetadataEmit"` is `false` and `"skipTemplateCodegen"` is `true`.
+Default is `false`.
+Use only when `"skipMetadataEmit"` is `false` and `"skipTemplateCodegen"` is `true`.
-This option is intended to validate the `.metadata.json` files emitted for bundling with an `npm` package. The validation is strict and can emit errors for metadata that would never produce an error when used by the template compiler. You can choose to suppress the error emitted by this option for an exported symbol by including `@dynamic` in the comment documenting the symbol.
+This option is intended to validate the `.metadata.json` files emitted for bundling with an `npm` package.
+The validation is strict and can emit errors for metadata that would never produce an error when used by the template compiler.
+You can choose to suppress the error emitted by this option for an exported symbol by including `@dynamic` in the comment documenting the symbol.
It is valid for `.metadata.json` files to contain errors.
The template compiler reports these errors if the metadata is used to determine the contents of an annotation.
@@ -168,7 +206,8 @@ For library projects generated with the CLI, the development configuration defau
### `strictInjectionParameters`
-When `true` (recommended), reports an error for a supplied parameter whose injection type cannot be determined. When `false` (currently the default), constructor parameters of classes marked with `@Injectable` whose type cannot be resolved produce a warning.
+When `true` \(recommended\), reports an error for a supplied parameter whose injection type cannot be determined.
+When `false` \(currently the default\), constructor parameters of classes marked with `@Injectable` whose type cannot be resolved produce a warning.
When you use the CLI command `ng new --strict`, it is set to `true` in the generated project's configuration.
@@ -176,15 +215,17 @@ When you use the CLI command `ng new --strict`, it is set to `true` in the gener
When `true`, enables [strict template type checking](guide/template-typecheck#strict-mode).
-Additional strictness flags allow you to enable and disable specific types of strict template type checking. See [troubleshooting template errors](guide/template-typecheck#troubleshooting-template-errors).
+Additional strictness flags allow you to enable and disable specific types of strict template type checking.
+See [troubleshooting template errors](guide/template-typecheck#troubleshooting-template-errors).
When you use the CLI command `ng new --strict`, it is set to `true` in the generated project's configuration.
### `trace`
-When `true`, prints extra information while compiling templates. Default is `false`.
+When `true`, prints extra information while compiling templates.
+Default is `false`.
-{@a cli-options}
+
## Command Line Options
@@ -201,4 +242,4 @@ In addition to the configuration file, you can also use [`tsc` command line opti
-@reviewed 2021-10-13
+@reviewed 2022-02-28
diff --git a/aio/content/guide/angular-package-format.md b/aio/content/guide/angular-package-format.md
index bd7b4d92656f5..c1e6065c0fcb6 100644
--- a/aio/content/guide/angular-package-format.md
+++ b/aio/content/guide/angular-package-format.md
@@ -1,7 +1,7 @@
# Angular Package Format
-This document describes the Angular Package Format (APF).
-APF is an Angular specific specification for the structure and format of npm packages that is used by all first-party Angular packages (`@angular/core`, `@angular/material`, etc.) and most third-party Angular libraries.
+This document describes the Angular Package Format \(APF\).
+APF is an Angular specific specification for the structure and format of npm packages that is used by all first-party Angular packages \(`@angular/core`, `@angular/material`, etc.\) and most third-party Angular libraries.
APF enables a package to work seamlessly under most common scenarios that use Angular.
Packages that use APF are compatible with the tooling offered by the Angular team as well as wider JavaScript ecosystem.
@@ -16,46 +16,133 @@ You can find the versions of the specification prior to v13 in this [google doc]
## Why specify a package format?
-In today's JavaScript landscape, developers will consume packages in many different ways, using many different toolchains (Webpack, rollup, esbuild, etc). These tools may understand and require different inputs - some tools may be able to process the latest ES language version, while others may benefit from directly consuming an older ES version.
+In today's JavaScript landscape, developers will consume packages in many different ways, using many different toolchains \(Webpack, rollup, esbuild, etc.\).
+These tools may understand and require different inputs - some tools may be able to process the latest ES language version, while others may benefit from directly consuming an older ES version.
-The Angular distribution format supports all of the commonly used development tools and workflows, and adds emphasis on optimizations that result either in smaller application payload size or faster development iteration cycle (build time).
+The Angular distribution format supports all of the commonly used development tools and workflows, and adds emphasis on optimizations that result either in smaller application payload size or faster development iteration cycle \(build time\).
-Developers can rely on Angular CLI and [ng-packagr](https://github.com/ng-packagr/ng-packagr) (a build tool Angular CLI uses) to produce packages in the Angular package format. See the [Creating Libraries](/guide/creating-libraries) guide for more details.
+Developers can rely on Angular CLI and [ng-packagr](https://github.com/ng-packagr/ng-packagr) \(a build tool Angular CLI uses\) to produce packages in the Angular package format.
+See the [Creating Libraries](guide/creating-libraries) guide for more details.
## File layout
-The following example shows a simplified version of the `@angular/core` package's file layout, with an explanation for each file in the package. This table describes the file layout under `node_modules/@angular/core` annotated to describe the purpose of files and directories:
-
-| FILES | PURPOSE |
-| :---------------------------------------------------------------------------------------------------------------------------------------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| `README.md` | Package README, used by npmjs web UI. |
-| `package.json` | Primary package.json, describing the package itself as well as all available entrypoints and code formats. This file contains the "exports" mapping used by runtimes and tools to perform module resolution. |
-| `core.d.ts` | Bundled `.d.ts` for the primary entrypoint `@angular/core`. |
-| `esm2020/` ─ `core.mjs` ─ `index.mjs` ─ `public_api.mjs` | Tree of @angular/core's sources in unflattened ES2020 format. |
-| `esm2020/testing/` | Tree of the `@angular/core/testing` entrypoint in unflattened ES2020 format. |
-| `fesm2015/` ─ `core.mjs` ─ `core.mjs.map` ─ `testing.mjs` ─ `testing.mjs.map` | Code for all entrypoints in a flattened (FESM) ES2015 format, along with sourcemaps. |
-| `fesm2020/` ─ `core.mjs` ─ `core.mjs.map` ─ `testing.mjs` ─ `testing.mjs.map` | Code for all entrypoints in flattened (FESM) ES2020 format, along with sourcemaps. |
-| `testing/` | Directory representing the "testing" entrypoint. |
-| `testing/package.json` | Defines the @angular/core/testing entrypoint with its typings for TypeScript, which does not support the top level "exports" based module resolution. |
-| `testing/testing.d.ts` | Actual `.d.ts` for the `@angular/core/testing` entrypoint |
+The following example shows a simplified version of the `@angular/core` package's file layout, with an explanation for each file in the package.
+
+
+
+ node_modules/@angular/core
+
+
+
+ README.md
+
+
+ package.json
+
+
+ core.d.ts
+
+
+ esm2020
+
+
+
+ core.mjs
+
+
+ index.mjs
+
+
+ public_api.mjs
+
+
+ testing
+
+
+
+ fesm2015
+
+
+
+ core.mjs
+
+
+ core.mjs.map
+
+
+ testing.mjs
+
+
+ testing.mjs.map
+
+
+
+ fesm2020
+
+
+
+ core.mjs
+
+
+ core.mjs.map
+
+
+ testing.mjs
+
+
+ testing.mjs.map
+
+
+
+ testing
+
+
+
+ package.json
+
+
+ testing.d.ts
+
+
+
+
+
+This table describes the file layout under `node_modules/@angular/core` annotated to describe the purpose of files and directories:
+
+| Files | Purpose |
+|:--- |:--- |
+| `README.md` | Package README, used by npmjs web UI. |
+| `package.json` | Primary `package.json`, describing the package itself as well as all available entrypoints and code formats. This file contains the "exports" mapping used by runtimes and tools to perform module resolution. |
+| `core.d.ts` | Bundled `.d.ts` for the primary entrypoint `@angular/core`. |
+| `esm2020/` ─ `core.mjs` ─ `index.mjs` ─ `public_api.mjs` | Tree of `@angular/core` sources in unflattened ES2020 format. |
+| `esm2020/testing/` | Tree of the `@angular/core/testing` entrypoint in unflattened ES2020 format. |
+| `fesm2015/` ─ `core.mjs` ─ `core.mjs.map` ─ `testing.mjs` ─ `testing.mjs.map` | Code for all entrypoints in a flattened \(FESM\) ES2015 format, along with sourcemaps. |
+| `fesm2020/` ─ `core.mjs` ─ `core.mjs.map` ─ `testing.mjs` ─ `testing.mjs.map` | Code for all entrypoints in flattened \(FESM\) ES2020 format, along with sourcemaps. |
+| `testing/` | Directory representing the "testing" entrypoint. |
+| `testing/package.json` | Defines the `@angular/core/testing` entrypoint with its typings for TypeScript, which does not support the top level "exports" based module resolution. |
+| `testing/testing.d.ts` | Actual `.d.ts` for the `@angular/core/testing` entrypoint. |
## `package.json`
The primary `package.json` contains important package metadata, including the following:
-* It [declares](#esm-declaration) the package to be in EcmaScript Module (ESM) format.
-* It contains an [`"exports"` field](#exports) which defines the available source code formats of all entrypoints.
-* It contains [keys](#legacy-resolution-keys) which define the available source code formats of the primary `@angular/core` entrypoint, for tools which do not understand `"exports"`. These keys are considered deprecated, and will be removed as the support for `"exports"` rolls out across the ecosystem.
-* It declares whether the package contains [side-effects](#side-effects).
+* It [declares](#esm-declaration) the package to be in EcmaScript Module \(ESM\) format
+* It contains an [`"exports"` field](#exports) which defines the available source code formats of all entrypoints
+* It contains [keys](#legacy-resolution-keys) which define the available source code formats of the primary `@angular/core` entrypoint, for tools which do not understand `"exports"`.
+ These keys are considered deprecated, and will be removed as the support for `"exports"` rolls out across the ecosystem.
+
+* It declares whether the package contains [side-effects](#side-effects)
### ESM declaration
The top-level `package.json` contains the key:
-
+
+
{
"type": "module"
}
+
This informs resolvers that code within the package is using EcmaScript Modules as opposed to CommonJS modules.
@@ -64,7 +151,8 @@ This informs resolvers that code within the package is using EcmaScript Modules
The `"exports"` field has the following structure:
-
+
+
"exports": {
"./schematics/*": {
"default": "./schematics/*.js"
@@ -89,33 +177,40 @@ The `"exports"` field has the following structure:
"default": "./fesm2020/testing.mjs"
}
}
+
-Of primary interest are the `"."` and the `"./testing"` keys, which define the available code formats for the `@angular/core` primary entrypoint and the `@angular/core/testing` secondary entrypoint, respectively. For each entrypoint, the available formats are:
+Of primary interest are the `"."` and the `"./testing"` keys, which define the available code formats for the `@angular/core` primary entrypoint and the `@angular/core/testing` secondary entrypoint, respectively.
+For each entrypoint, the available formats are:
-* Typings (`.d.ts` files)
-`.d.ts` files are used by TypeScript when depending on a given package.
-* `es2020` - ES2020 code flattened into a single source file.
-* `es2015` - ES2015 code flattened into a single source file.
-* `esm2020` - ES2020 code in unflattened source files (this format is included for experimentation - see [this discussion of defaults](#note-about-the-defaults-in-packagejson) for details).
+| Formats | Details |
+|:--- |:--- |
+| Typings \(`.d.ts` files\) | `.d.ts` files are used by TypeScript when depending on a given package. |
+| `es2020` | ES2020 code flattened into a single source file. |
+| `es2015` | ES2015 code flattened into a single source file. |
+| `esm2020` | ES2020 code in unflattened source files \(this format is included for experimentation - see [this discussion of defaults](#note-about-the-defaults-in-packagejson) for details\). |
-Tooling that is aware of these keys may preferentially select a desirable code format from `"exports"`. The remaining 2 keys control the default behavior of tooling:
+Tooling that is aware of these keys may preferentially select a desirable code format from `"exports"`.
+The remaining 2 keys control the default behavior of tooling:
-* `"node"` selects flattened ES2015 code when the package is loaded in Node.
+* `"node"` selects flattened ES2015 code when the package is loaded in Node.
- This format is used due to the requirements of `zone.js`, which does not support native async
/`await` ES2017 syntax. Therefore, Node is instructed to use ES2015 code, where async
/`await` structures have been downleveled into Promises.
+ This format is used due to the requirements of `zone.js`, which does not support native `async`/`await` ES2017 syntax.
+ Therefore, Node is instructed to use ES2015 code, where `async`/`await` structures have been downleveled into Promises.
-* `"default"` selects flattened ES2020 code for all other consumers.
+* `"default"` selects flattened ES2020 code for all other consumers.
Libraries may want to expose additional static files which are not captured by the exports of the JavaScript-based entry-points such as Sass mixins or pre-compiled CSS.
-For more information, see [Managing assets in a library](/guide/creating-libraries#managing-assets-in-a-library).
+For more information, see [Managing assets in a library](guide/creating-libraries#managing-assets-in-a-library).
### Legacy resolution keys
-In addition to `"exports"`, the top-level `package.json` also defines legacy module resolution keys for resolvers that don't support `"exports"`. For `@angular/core` these are:
+In addition to `"exports"`, the top-level `package.json` also defines legacy module resolution keys for resolvers that don't support `"exports"`.
+For `@angular/core` these are:
+
+
-
{
"fesm2020": "./fesm2020/core.mjs",
"fesm2015": "./fesm2015/core.mjs",
@@ -124,77 +219,101 @@ In addition to `"exports"`, the top-level `package.json` also defines legacy mod
"module": "./fesm2015/core.mjs",
"es2020": "./fesm2020/core.mjs",
}
+
-As above, a module resolver can use these keys to load a specific code format. Note that instead of `"default"`, `"module"` selects the format both for Node as well as any tooling not configured to use a specific key. As with `"node"`, ES2015 code is selected due to the constraints of ZoneJS.
+As above, a module resolver can use these keys to load a specific code format.
+
+
+
+**NOTE**:
+Instead of `"default"`, `"module"` selects the format both for Node as well as any tooling not configured to use a specific key.
+As with `"node"`, ES2015 code is selected due to the constraints of ZoneJS.
+
+
### Side effects
The last function of `package.json` is to declare whether the package has [side-effects](#sideeffects-flag).
-
+
+
{
"sideEffects": false
}
+
Most Angular packages should not depend on top-level side effects, and thus should include this declaration.
### Secondary `package.json`s
-In addition to the top-level `package.json`, secondary entrypoints have a corresponding directory with its own `package.json`. For example, in `@angular/core` the `@angular/core/testing` entrypoint is represented by `testing/package.json`.
+In addition to the top-level `package.json`, secondary entrypoints have a corresponding directory with its own `package.json`.
+For example, in `@angular/core` the `@angular/core/testing` entrypoint is represented by `testing/package.json`.
-This secondary `package.json` is required for legacy resolvers which do not support `"exports"`. We expect these files to be removed in a future version of the Angular Package Format, once support for `"exports"` is consistent across the ecosystem.
+This secondary `package.json` is required for legacy resolvers which do not support `"exports"`.
+We expect these files to be removed in a future version of the Angular Package Format, once support for `"exports"` is consistent across the ecosystem.
## Entrypoints and Code Splitting
-Packages in the Angular Package Format contain one primary entrypoint and zero or more secondary entrypoints (e.g. `@angular/common/http`). Entrypoints serve several functions.
+Packages in the Angular Package Format contain one primary entrypoint and zero or more secondary entrypoints \(for example, `@angular/common/http`\).
+Entrypoints serve several functions.
-1. They define the module specifiers from which users import code (for example, `@angular/core` and `@angular/core/testing`).
+1. They define the module specifiers from which users import code \(for example, `@angular/core` and `@angular/core/testing`\).
-Users typically perceive these entrypoints as distinct groups of symbols, with different purposes or functionality.
+ Users typically perceive these entrypoints as distinct groups of symbols, with different purposes or functionality.
-Specific entrypoints might only be used for special purposes, such as testing. Such APIs can be separated out from the primary entrypoint to reduce the chance of them being used accidentally or incorrectly.
+ Specific entrypoints might only be used for special purposes, such as testing.
+ Such APIs can be separated out from the primary entrypoint to reduce the chance of them being used accidentally or incorrectly.
-2. They define the granularity at which code can be lazily loaded.
+1. They define the granularity at which code can be lazily loaded.
-Many modern build tools are only capable of "code splitting" (aka lazy loading) at the ES Module level. Since the Angular Package Format uses primarily a single "flat" ES Module per entrypoint, this means that most build tooling will not be able to split code in a single entrypoint into multiple output chunks.
+ Many modern build tools are only capable of "code splitting" \(aka lazy loading\) at the ES Module level.
+ Since the Angular Package Format uses primarily a single "flat" ES Module per entrypoint, this means that most build tooling will not be able to split code in a single entrypoint into multiple output chunks.
-The general rule for APF packages is to use entrypoints for the smallest sets of logically connected code possible. For example, the Angular Material package publishes each logical component or set of components as a separate entrypoint - one for Button, one for Tabs, etc. This allows each Material component to be lazily loaded separately, if desired.
+The general rule for APF packages is to use entrypoints for the smallest sets of logically connected code possible.
+For example, the Angular Material package publishes each logical component or set of components as a separate entrypoint - one for Button, one for Tabs, etc.
+This allows each Material component to be lazily loaded separately, if desired.
-Not all libraries require such granularity. Most libraries with a single logical purpose should be published as a single entrypoint. `@angular/core` for example uses a single entrypoint for the runtime, because the Angular runtime is generally used as a single entity.
+Not all libraries require such granularity.
+Most libraries with a single logical purpose should be published as a single entrypoint.
+`@angular/core` for example uses a single entrypoint for the runtime, because the Angular runtime is generally used as a single entity.
### Resolution of Secondary Entrypoints
Secondary entrypoints may be resolved by tooling in one of two ways:
-* via the `"exports"` field of the primary `package.json` for the package
-* by Node Module Resolution rules, via a `package.json` in a subdirectory corresponding to the entrypoint's module ID. For example, the `testing/package.json` file for the `@angular/core/testing` secondary entrypoint.
+* Via the `"exports"` field of the primary `package.json` for the package
+* By Node Module Resolution rules, via a `package.json` in a subdirectory corresponding to the entrypoint's module ID.
+ For example, the `testing/package.json` file for the `@angular/core/testing` secondary entrypoint.
## README.md
The readme file in the markdown format that is used to display description of a package on npm and github.
-Example readme content of @angular/core package:
+Example readme content of @angular/core package:
+
Angular
-=======
+=======
-The sources for this package are in the main [Angular](https://github.com/angular/angular) repo. Please file issues and pull requests against that repo.
+The sources for this package are in the main [Angular](https://github.com/angular/angular) repo.Please file issues and pull requests against that repo.
License: MIT
+
## Partial Compilation
-Libraries in the Angular Package Format must be published in "partial compilation" mode. This is a compilation mode for `ngc` which produces compiled Angular code that is not tied to a specific Angular runtime version, in contrast to the full compilation used for applications, where the Angular compiler and runtime versions must match exactly.
+Libraries in the Angular Package Format must be published in "partial compilation" mode.
+This is a compilation mode for `ngc` which produces compiled Angular code that is not tied to a specific Angular runtime version, in contrast to the full compilation used for applications, where the Angular compiler and runtime versions must match exactly.
To partially compile Angular code, use the `"compilationMode"` flag in `"angularCompilerOptions"` in your `tsconfig.json`:
-
+
{
- ...
+ …
"angularCompilerOptions": {
"compilationMode": "partial",
}
@@ -203,123 +322,187 @@ To partially compile Angular code, use the `"compilationMode"` flag in `"angular
Partially compiled library code is then converted to fully compiled code during the application build process by the Angular CLI.
-If your build pipeline does not use the Angular CLI then refer to the [Consuming partial ivy code outside the Angular CLI](/guide/creating-libraries#consuming-partial-ivy-code-outside-the-angular-cli) guide.
+If your build pipeline does not use the Angular CLI then refer to the [Consuming partial ivy code outside the Angular CLI](guide/creating-libraries#consuming-partial-ivy-code-outside-the-angular-cli) guide.
## Optimizations
### Flattening of ES Modules
-The Angular Package Format specifies that code be published in "flattened" ES module format. This significantly reduces the build time of Angular applications as well as download and parse time of the final application bundle. Please check out the excellent post ["The cost of small modules"](https://nolanlawson.com/2016/08/15/the-cost-of-small-modules/) by Nolan Lawson.
+The Angular Package Format specifies that code be published in "flattened" ES module format.
+This significantly reduces the build time of Angular applications as well as download and parse time of the final application bundle.
+Please check out the excellent post ["The cost of small modules"](https://nolanlawson.com/2016/08/15/the-cost-of-small-modules) by Nolan Lawson.
The Angular compiler has support for generating index ES module files that can then be used to generate flattened modules using tools like Rollup, resulting in a file format we call Flattened ES Module or FESM.
-FESM is a file format created by flattening all ES Modules accessible from an entrypoint into a single ES Module. It’s formed by following all imports from a package and copying that code into a single file while preserving all public ES exports and removing all private imports.
+FESM is a file format created by flattening all ES Modules accessible from an entrypoint into a single ES Module.
+It's formed by following all imports from a package and copying that code into a single file while preserving all public ES exports and removing all private imports.
-The shortened name “FESM” (pronounced “phesom”) can have a number after it such as “FESM5” or “FESM2015”. The number refers to the language level of the JavaScript inside the module. So a FESM5 file would be ESM+ES5 (import/export statements and ES5 source code).
+The shortened name "FESM" \(pronounced "phesom"\) can have a number after it such as "FESM5" or "FESM2015".
+The number refers to the language level of the JavaScript inside the module.
+So a FESM5 file would be ESM+ES5 \(import/export statements and ES5 source code\).
To generate a flattened ES Module index file, use the following configuration options in your tsconfig.json file:
-
+
+
{
"compilerOptions": {
- ...
+ …
"module": "esnext",
"target": "es2020",
- ...
+ …
},
"angularCompilerOptions": {
- ...
+ …
"flatModuleOutFile": "my-ui-lib.js",
"flatModuleId": "my-ui-lib"
}
}
+
-Once the index file (e.g. `my-ui-lib.js`) is generated by ngc, bundlers and optimizers like Rollup can be used to produce the flattened ESM file.
+Once the index file \(for example, `my-ui-lib.js`\) is generated by ngc, bundlers and optimizers like Rollup can be used to produce the flattened ESM file.
#### Note about the defaults in package.json
-As of webpack v4 the flattening of ES modules optimization should not be necessary for webpack users, and in fact theoretically we should be able to get better code-splitting without flattening of modules in webpack. In practice we still see size regressions when using unflattened modules as input for webpack v4. This is why `"module"` and `"es2020"` package.json entries still point to fesm files. We are investigating this issue and expect that we'll switch the `"module"` and `"es2020"` package.json entry points to unflattened files when the size regression issue is resolved. The APF currently includes unflattened ESM2020 code for the purpose of validating such a future change.
+As of webpack v4 the flattening of ES modules optimization should not be necessary for webpack users, and in fact theoretically we should be able to get better code-splitting without flattening of modules in webpack.
+In practice we still see size regressions when using unflattened modules as input for webpack v4.
+This is why `"module"` and `"es2020"` package.json entries still point to fesm files.
+We are investigating this issue and expect that we'll switch the `"module"` and `"es2020"` package.json entry points to unflattened files when the size regression issue is resolved.
+The APF currently includes unflattened ESM2020 code for the purpose of validating such a future change.
### "sideEffects" flag
-By default, EcmaScript Modules are side-effectful: importing from a module ensures that any code at the top level of that module will execute. This is often undesirable, as most side-effectful code in typical modules is not truly side-effectful, but instead only affects specific symbols. If those symbols are not imported and used, it's often desirable to remove them in an optimization process known as tree-shaking, and the side-effectful code can prevent this.
+By default, EcmaScript Modules are side-effectful: importing from a module ensures that any code at the top level of that module will execute.
+This is often undesirable, as most side-effectful code in typical modules is not truly side-effectful, but instead only affects specific symbols.
+If those symbols are not imported and used, it's often desirable to remove them in an optimization process known as tree-shaking, and the side-effectful code can prevent this.
-Build tools such as Webpack support a flag which allows packages to declare that they do not depend on side-effectful code at the top level of their modules, giving the tools more freedom to tree-shake code from the package. The end result of these optimizations should be smaller bundle size and better code distribution in bundle chunks after code-splitting. This optimization can break your code if it contains non-local side-effects - this is however not common in Angular applications and it's usually a sign of bad design. Our recommendation is for all packages to claim the side-effect free status by setting the `sideEffects` property to `false`, and that developers follow the [Angular Style Guide](https://angular.io/guide/styleguide) which naturally results in code without non-local side-effects.
+Build tools such as Webpack support a flag which allows packages to declare that they do not depend on side-effectful code at the top level of their modules, giving the tools more freedom to tree-shake code from the package.
+The end result of these optimizations should be smaller bundle size and better code distribution in bundle chunks after code-splitting.
+This optimization can break your code if it contains non-local side-effects - this is however not common in Angular applications and it's usually a sign of bad design.
+Our recommendation is for all packages to claim the side-effect free status by setting the `sideEffects` property to `false`, and that developers follow the [Angular Style Guide](https://angular.io/guide/styleguide) which naturally results in code without non-local side-effects.
More info: [webpack docs on side-effects](https://github.com/webpack/webpack/tree/master/examples/side-effects)
-
+
### ES2020 Language Level
-ES2020 Language level is now the default language level that is consumed by Angular CLI and other tooling. The Angular CLI will downlevel the bundle to a language level that is supported by all targeted browsers at application build time.
+ES2020 Language level is now the default language level that is consumed by Angular CLI and other tooling.
+The Angular CLI will downlevel the bundle to a language level that is supported by all targeted browsers at application build time.
### d.ts bundling / type definition flattening
-As of APF v8 we now prefer to run [API Extractor](https://api-extractor.com/), to bundle TypeScript definitions so that the entire API appears in a single file.
+As of APF v8 we now prefer to run [API Extractor](https://api-extractor.com), to bundle TypeScript definitions so that the entire API appears in a single file.
-In prior APF versions each entry point would have a `src` directory next to the .d.ts entry point and this directory contained individual d.ts files matching the structure of the original source code. While this distribution format is still allowed and supported, it is highly discouraged because it confuses tools like IDEs that then offer incorrect autocompletion, and allows users to depend on deep-import paths which are typically not considered to be public API of a library or a package.
+In prior APF versions each entry point would have a `src` directory next to the .d.ts entry point and this directory contained individual d.ts files matching the structure of the original source code.
+While this distribution format is still allowed and supported, it is highly discouraged because it confuses tools like IDEs that then offer incorrect autocompletion, and allows users to depend on deep-import paths which are typically not considered to be public API of a library or a package.
### Tslib
-As of APF v10, we recommend adding tslib as a direct dependency of your primary entry-point. This is because the tslib version is tied to the TypeScript version used to compile your library.
+As of APF v10, we recommend adding tslib as a direct dependency of your primary entry-point.
+This is because the tslib version is tied to the TypeScript version used to compile your library.
## Examples
-* [@angular/core package](https://unpkg.com/browse/@angular/core@13.0.0-rc.0/)
-* [@angular/material package](https://unpkg.com/browse/@angular/material@13.0.0-rc.0/)
+* [@angular/core package](https://unpkg.com/browse/@angular/core@13.0.0-rc.0)
+* [@angular/material package](https://unpkg.com/browse/@angular/material@13.0.0-rc.0)
## Definition of Terms
-The following terms are used throughout this document very intentionally. In this section we define all of them to provide additional clarity.
+The following terms are used throughout this document very intentionally.
+In this section we define all of them to provide additional clarity.
#### Package
-The smallest set of files that are published to NPM and installed together, for example `@angular/core`. This package includes a manifest called package.json, compiled source code, typescript definition files, source maps, metadata, etc. The package is installed with `npm install @angular/core`.
+
+The smallest set of files that are published to NPM and installed together, for example `@angular/core`.
+This package includes a manifest called package.json, compiled source code, typescript definition files, source maps, metadata, etc.
+The package is installed with `npm install @angular/core`.
#### Symbol
+
A class, function, constant or variable contained in a module and optionally made visible to the external world via a module export.
#### Module
-Short for ECMAScript Modules. A file containing statements that import and export symbols. This is identical to the definition of modules in the ECMAScript spec.
+
+Short for ECMAScript Modules.
+A file containing statements that import and export symbols.
+This is identical to the definition of modules in the ECMAScript spec.
+
#### ESM
-Short for ECMAScript Modules (see above).
+
+Short for ECMAScript Modules \(see above\).
#### FESM
+
Short for Flattened ES Modules and consists of a file format created by flattening all ES Modules accessible from an entry point into a single ES Module.
#### Module ID
-The identifier of a module used in the import statements, e.g. `@angular/core`. The ID often maps directly to a path on the filesystem, but this is not always the case due to various module resolution strategies.
+
+The identifier of a module used in the import statements \(for example, `@angular/core`\).
+The ID often maps directly to a path on the filesystem, but this is not always the case due to various module resolution strategies.
#### Module Specifier
-A module identifier (see above).
+
+A module identifier \(see above\).
#### Module Resolution Strategy
-Algorithm used to convert Module IDs to paths on the filesystem. Node.js has one that is well specified and widely used, TypeScript supports several module resolution strategies, [Closure Compiler](https://developers.google.com/closure/compiler) has yet another strategy.
+
+Algorithm used to convert Module IDs to paths on the filesystem.
+Node.js has one that is well specified and widely used, TypeScript supports several module resolution strategies, [Closure Compiler](https://developers.google.com/closure/compiler) has yet another strategy.
#### Module Format
-Specification of the module syntax that covers at minimum the syntax for the importing and exporting from a file. Common module formats are CommonJS (CJS, typically used for Node.js applications) or ECMAScript Modules (ESM). The module format indicates only the packaging of the individual modules, but not the JavaScript language features used to make up the module content. Because of this, the Angular team often uses the language level specifier as a suffix to the module format, e.g. ESM+ES2015 specifies that the module is in ESM format and contains code down-leveled to ES2015.
+
+Specification of the module syntax that covers at minimum the syntax for the importing and exporting from a file.
+Common module formats are CommonJS \(CJS, typically used for Node.js applications\) or ECMAScript Modules \(ESM\).
+The module format indicates only the packaging of the individual modules, but not the JavaScript language features used to make up the module content.
+Because of this, the Angular team often uses the language level specifier as a suffix to the module format, \(for example, ESM+ES2015 specifies that the module is in ESM format and contains code down-leveled to ES2015\).
#### Bundle
-An artifact in the form of a single JS file, produced by a build tool, e.g. [Webpack](https://webpack.js.org/) or [Rollup](https://rollupjs.org/), that contains symbols originating in one or more modules. Bundles are a browser-specific workaround that reduce network strain that would be caused if browsers were to start downloading hundreds if not tens of thousands of files. Node.js typically doesn't use bundles. Common bundle formats are UMD and System.register.
+
+An artifact in the form of a single JS file, produced by a build tool \(for example, [Webpack](https://webpack.js.org) or [Rollup](https://rollupjs.org)\) that contains symbols originating in one or more modules.
+Bundles are a browser-specific workaround that reduce network strain that would be caused if browsers were to start downloading hundreds if not tens of thousands of files.
+Node.js typically doesn't use bundles.
+Common bundle formats are UMD and System.register.
#### Language Level
-The language of the code (ES2015 or ES2020). Independent of the module format.
+
+The language of the code \(ES2015 or ES2020\).
+Independent of the module format.
#### Entry Point
-A module intended to be imported by the user. It is referenced by a unique module ID and exports the public API referenced by that module ID. An example is `@angular/core` or `@angular/core/testing`. Both entry points exist in the `@angular/core` package, but they export different symbols. A package can have many entry points.
+
+A module intended to be imported by the user.
+It is referenced by a unique module ID and exports the public API referenced by that module ID.
+An example is `@angular/core` or `@angular/core/testing`.
+Both entry points exist in the `@angular/core` package, but they export different symbols.
+A package can have many entry points.
#### Deep Import
-A process of retrieving symbols from modules that are not Entry Points. These module IDs are usually considered to be private APIs that can change over the lifetime of the project or while the bundle for the given package is being created.
+
+A process of retrieving symbols from modules that are not Entry Points.
+These module IDs are usually considered to be private APIs that can change over the lifetime of the project or while the bundle for the given package is being created.
#### Top-Level Import
-An import coming from an entry point. The available top-level imports are what define the public API and are exposed in “@angular/name” modules, such as `@angular/core` or `@angular/common`.
+
+An import coming from an entry point.
+The available top-level imports are what define the public API and are exposed in "@angular/name" modules, such as `@angular/core` or `@angular/common`.
#### Tree-shaking
-The process of identifying and removing code not used by an application - also known as dead code elimination. This is a global optimization performed at the application level using tools like [Rollup](https://rollupjs.org/), [Closure Compiler](https://developers.google.com/closure/compiler), or [Terser](https://github.com/terser/terser/).
+
+The process of identifying and removing code not used by an application - also known as dead code elimination.
+This is a global optimization performed at the application level using tools like [Rollup](https://rollupjs.org), [Closure Compiler](https://developers.google.com/closure/compiler), or [Terser](https://github.com/terser/terser).
#### AOT Compiler
+
The Ahead of Time Compiler for Angular.
#### Flattened Type Definitions
-The bundled TypeScript definitions generated from [API Extractor](https://api-extractor.com/).
-@reviewed 2021-11-04
+The bundled TypeScript definitions generated from [API Extractor](https://api-extractor.com).
+
+
+
+
+
+
+
+@reviewed 2022-02-28
diff --git a/aio/content/guide/animations.md b/aio/content/guide/animations.md
index c22e9ad34d5e1..cb6a4c10d5781 100644
--- a/aio/content/guide/animations.md
+++ b/aio/content/guide/animations.md
@@ -1,35 +1,38 @@
# Introduction to Angular animations
-Animation provides the illusion of motion: HTML elements change styling over time. Well-designed animations can make your application more fun and straightforward to use, but they aren't just cosmetic. Animations can improve your application and user experience in a number of ways:
+Animation provides the illusion of motion: HTML elements change styling over time.
+Well-designed animations can make your application more fun and straightforward to use, but they aren't just cosmetic.
+Animations can improve your application and user experience in a number of ways:
-* Without animations, web page transitions can seem abrupt and jarring.
+* Without animations, web page transitions can seem abrupt and jarring
+* Motion greatly enhances the user experience, so animations give users a chance to detect the application's response to their actions
+* Good animations intuitively call the user's attention to where it is needed
-* Motion greatly enhances the user experience, so animations give users a chance to detect the application's response to their actions.
-
-* Good animations intuitively call the user's attention to where it is needed.
-
-Typically, animations involve multiple style *transformations* over time. An HTML element can move, change color, grow or shrink, fade, or slide off the page. These changes can occur simultaneously or sequentially. You can control the timing of each transformation.
-
-Angular's animation system is built on CSS functionality, which means you can animate any property that the browser considers animatable. This includes positions, sizes, transforms, colors, borders, and more. The W3C maintains a list of animatable properties on its [CSS Transitions](https://www.w3.org/TR/css-transitions-1/) page.
+Typically, animations involve multiple style *transformations* over time.
+An HTML element can move, change color, grow or shrink, fade, or slide off the page.
+These changes can occur simultaneously or sequentially.You can control the timing of each transformation.
+Angular's animation system is built on CSS functionality, which means you can animate any property that the browser considers animatable.
+This includes positions, sizes, transforms, colors, borders, and more.
+The W3C maintains a list of animatable properties on its [CSS Transitions](https://www.w3.org/TR/css-transitions-1) page.
## About this guide
This guide covers the basic Angular animation features to get you started on adding Angular animations to your project.
-The features described in this guide — and the more advanced features described in the related Angular animations guides — are demonstrated in an example application available as a .
+The features described in this guide —and the more advanced features described in the related Angular animations guides— are demonstrated in an example application available as a .
-#### Prerequisites
+## Prerequisites
The guide assumes that you're familiar with building basic Angular apps, as described in the following sections:
-* [Tutorial](tutorial)
-* [Architecture Overview](guide/architecture)
-
+* [Tutorial](tutorial)
+* [Architecture Overview](guide/architecture)
## Getting started
-The main Angular modules for animations are `@angular/animations` and `@angular/platform-browser`. When you create a new project using the CLI, these dependencies are automatically added to your project.
+The main Angular modules for animations are `@angular/animations` and `@angular/platform-browser`.
+When you create a new project using the CLI, these dependencies are automatically added to your project.
To get started with adding Angular animations to your project, import the animation-specific modules along with standard Angular functionality.
@@ -37,174 +40,236 @@ To get started with adding Angular animations to your project, import the animat
Import `BrowserAnimationsModule`, which introduces the animation capabilities into your Angular root application module.
-
+
-**Note:** When you use the CLI to create your app, the root application module `app.module.ts` is placed in the `src/app` folder.
+**NOTE**:
+When you use the CLI to create your app, the root application module `app.module.ts` is placed in the `src/app` folder.
+
### Step 2: Importing animation functions into component files
If you plan to use specific animation functions in component files, import those functions from `@angular/animations`.
-
-
+
-**Note:** See a [summary of available animation functions](guide/animations#animation-api-summary) at the end of this guide.
+**NOTE**:
+See a [summary of available animation functions](guide/animations#animation-api-summary) at the end of this guide.
+
### Step 3: Adding the animation metadata property
-In the component file, add a metadata property called `animations:` within the `@Component()` decorator. You put the trigger that defines an animation within the `animations` metadata property.
+In the component file, add a metadata property called `animations:` within the `@Component()` decorator.
+You put the trigger that defines an animation within the `animations` metadata property.
-
-
+
## Animating a transition
-Let's animate a transition that changes a single HTML element from one state to another. For example, you can specify that a button displays either **Open** or **Closed** based on the user's last action. When the button is in the `open` state, it's visible and yellow. When it's the `closed` state, it's translucent and blue.
+Let's animate a transition that changes a single HTML element from one state to another.
+For example, you can specify that a button displays either **Open** or **Closed** based on the user's last action.
+When the button is in the `open` state, it's visible and yellow.
+When it's the `closed` state, it's translucent and blue.
-In HTML, these attributes are set using ordinary CSS styles such as color and opacity. In Angular, use the `style()` function to specify a set of CSS styles for use with animations. Collect a set of styles in an animation state, and give the state a name, such as `open` or `closed`.
+In HTML, these attributes are set using ordinary CSS styles such as color and opacity.
+In Angular, use the `style()` function to specify a set of CSS styles for use with animations.
+Collect a set of styles in an animation state, and give the state a name, such as `open` or `closed`.
- Let's create a new `open-close` component to animate with simple transitions.
+Let's create a new `open-close` component to animate with simple transitions.
+
+Run the following command in terminal to generate the component:
- Run the following command in terminal to generate the component:
+
- `ng g component open-close`
+ng g component open-close
+
+
+
+This will create the component at `src/app/open-close.component.ts`.
- This will create the component at `src/app/open-close.component.ts`.
### Animation state and styles
-Use Angular's [state](api/animations/state)()
function to define different states to call at the end of each transition. This function takes two arguments: a unique name like `open` or `closed` and a `style()` function.
+Use Angular's [`state()`](api/animations/state) function to define different states to call at the end of each transition.
+This function takes two arguments:
+A unique name like `open` or `closed` and a `style()` function.
-Use the `style()` function to define a set of styles to associate with a given state name. You must use [*camelCase*](guide/glossary#case-conventions) for style attributes that contain dashes, such as `backgroundColor` or wrap them in quotes, such as `'background-color'`.
+Use the `style()` function to define a set of styles to associate with a given state name.
+You must use [*camelCase*](guide/glossary#case-conventions) for style attributes that contain dashes, such as `backgroundColor` or wrap them in quotes, such as `'background-color'`.
-Let's see how Angular's [state](api/animations/state)()
function works with the `style()` function to set CSS style attributes. In this code snippet, multiple style attributes are set at the same time for the state. In the `open` state, the button has a height of 200 pixels, an opacity of 1, and a yellow background color.
+Let's see how Angular's [`state()`](api/animations/state) function works with the `style()` function to set CSS style attributes.
+In this code snippet, multiple style attributes are set at the same time for the state.
+In the `open` state, the button has a height of 200 pixels, an opacity of 1, and a yellow background color.
-
-
+
In the following `closed` state, the button has a height of 100 pixels, an opacity of 0.8, and a background color of blue.
-
-
+
### Transitions and timing
-In Angular, you can set multiple styles without any animation. However, without further refinement, the button instantly transforms with no fade, no shrinkage, or other visible indicator that a change is occurring.
+In Angular, you can set multiple styles without any animation.
+However, without further refinement, the button instantly transforms with no fade, no shrinkage, or other visible indicator that a change is occurring.
-To make the change less abrupt, you need to define an animation *transition* to specify the changes that occur between one state and another over a period of time. The `transition()` function accepts two arguments: the first argument accepts an expression that defines the direction between two transition states, and the second argument accepts one or a series of `animate()` steps.
+To make the change less abrupt, you need to define an animation *transition* to specify the changes that occur between one state and another over a period of time.
+The `transition()` function accepts two arguments:
+The first argument accepts an expression that defines the direction between two transition states, and the second argument accepts one or a series of `animate()` steps.
-
-Use the `animate()` function to define the length, delay, and easing of a transition, and to designate the style function for defining styles while transitions are taking place. Use the `animate()` function to define the `keyframes()` function for multi-step animations. These definitions are placed in the second argument of the `animate()` function.
+Use the `animate()` function to define the length, delay, and easing of a transition, and to designate the style function for defining styles while transitions are taking place.
+Use the `animate()` function to define the `keyframes()` function for multi-step animations.
+These definitions are placed in the second argument of the `animate()` function.
#### Animation metadata: duration, delay, and easing
-The `animate()` function (second argument of the transition function) accepts the `timings` and `styles` input parameters.
+The `animate()` function \(second argument of the transition function\) accepts the `timings` and `styles` input parameters.
The `timings` parameter takes either a number or a string defined in three parts.
->`animate (duration)` or `animate ('duration delay easing')`
+
+
+animate (duration)
+
+
+
+or
+
+
+
+animate ('duration delay easing')
-The first part, `duration`, is required. The duration can be expressed in milliseconds as a number without quotes, or in seconds with quotes and a time specifier. For example, a duration of a tenth of a second can be expressed as follows:
+
+
+The first part, `duration`, is required.
+The duration can be expressed in milliseconds as a number without quotes, or in seconds with quotes and a time specifier.
+For example, a duration of a tenth of a second can be expressed as follows:
-* As a plain number, in milliseconds: `100`
+* As a plain number, in milliseconds:
+ `100`
-* In a string, as milliseconds: `'100ms'`
+* In a string, as milliseconds:
+ `'100ms'`
-* In a string, as seconds: `'0.1s'`
+* In a string, as seconds:
+ `'0.1s'`
-The second argument, `delay`, has the same syntax as `duration`. For example:
+The second argument, `delay`, has the same syntax as `duration`.
+For example:
-* Wait for 100ms and then run for 200ms: `'0.2s 100ms'`
+* Wait for 100ms and then run for 200ms: `'0.2s 100ms'`
-The third argument, `easing`, controls how the animation [accelerates and decelerates](https://easings.net/) during its runtime. For example, `ease-in` causes the animation to begin slowly, and to pick up speed as it progresses.
+The third argument, `easing`, controls how the animation [accelerates and decelerates](https://easings.net) during its runtime.
+For example, `ease-in` causes the animation to begin slowly, and to pick up speed as it progresses.
-* Wait for 100ms, run for 200ms. Use a deceleration curve to start out fast and slowly decelerate to a resting point: `'0.2s 100ms ease-out'`
+* Wait for 100ms, run for 200ms.
+ Use a deceleration curve to start out fast and slowly decelerate to a resting point:
+ `'0.2s 100ms ease-out'`
-* Run for 200ms, with no delay. Use a standard curve to start slow, accelerate in the middle, and then decelerate slowly at the end: `'0.2s ease-in-out'`
+* Run for 200ms, with no delay.
+ Use a standard curve to start slow, accelerate in the middle, and then decelerate slowly at the end:
+ `'0.2s ease-in-out'`
-* Start immediately, run for 200ms. Use an acceleration curve to start slow and end at full velocity: `'0.2s ease-in'`
+* Start immediately, run for 200ms.
+ Use an acceleration curve to start slow and end at full velocity:
+ `'0.2s ease-in'`
-**Note:** See the Material Design website's topic on [Natural easing curves](https://material.io/design/motion/speed.html#easing) for general information on easing curves.
+**NOTE**:
+See the Material Design website's topic on [Natural easing curves](https://material.io/design/motion/speed.html#easing) for general information on easing curves.
+
This example provides a state transition from `open` to `closed` with a 1-second transition between states.
-
-
+
-In the preceding code snippet, the `=>` operator indicates unidirectional transitions, and `<=>` is bidirectional. Within the transition, `animate()` specifies how long the transition takes. In this case, the state change from `open` to `closed` takes 1 second, expressed here as `1s`.
+In the preceding code snippet, the `=>` operator indicates unidirectional transitions, and `<=>` is bidirectional.
+Within the transition, `animate()` specifies how long the transition takes.
+In this case, the state change from `open` to `closed` takes 1 second, expressed here as `1s`.
This example adds a state transition from the `closed` state to the `open` state with a 0.5-second transition animation arc.
-
-
+
-**Note:** Some additional notes on using styles within [`state`](api/animations/state) and `transition` functions.
+**NOTE**:
+Some additional notes on using styles within [`state`](api/animations/state) and `transition` functions.
+
+* Use [`state()`](api/animations/state) to define styles that are applied at the end of each transition, they persist after the animation completes
+* Use `transition()` to define intermediate styles, which create the illusion of motion during the animation
+* When animations are disabled, `transition()` styles can be skipped, but [`state()`](api/animations/state) styles can't
+* Include multiple state pairs within the same `transition()` argument:
-* Use [state](api/animations/state)()
to define styles that are applied at the end of each transition, they persist after the animation completes.
+
-* Use `transition()` to define intermediate styles, which create the illusion of motion during the animation.
+ transition( 'on => off, off => void' )
-* When animations are disabled, `transition()` styles can be skipped, but [state](api/animations/state)()
styles can't.
+
-* Include multiple state pairs within the same `transition()` argument: `transition( 'on => off, off => void' )`.
### Triggering the animation
-An animation requires a *trigger*, so that it knows when to start. The `trigger()` function collects the states and transitions, and gives the animation a name, so that you can attach it to the triggering element in the HTML template.
+An animation requires a *trigger*, so that it knows when to start.
+The `trigger()` function collects the states and transitions, and gives the animation a name, so that you can attach it to the triggering element in the HTML template.
-The `trigger()` function describes the property name to watch for changes. When a change occurs, the trigger initiates the actions included in its definition. These actions can be transitions or other functions, as we'll see later on.
+The `trigger()` function describes the property name to watch for changes.
+When a change occurs, the trigger initiates the actions included in its definition.
+These actions can be transitions or other functions, as we'll see later on.
-In this example, we'll name the trigger `openClose`, and attach it to the `button` element. The trigger describes the open and closed states, and the timings for the two transitions.
+In this example, we'll name the trigger `openClose`, and attach it to the `button` element.
+The trigger describes the open and closed states, and the timings for the two transitions.
-**Note:** Within each `trigger()` function call, an element can only be in one state at any given time. However, it's possible for multiple triggers to be active at once.
+**NOTE**:
+Within each `trigger()` function call, an element can only be in one state at any given time.
+However, it's possible for multiple triggers to be active at once.
+
### Defining animations and attaching them to the HTML template
-Animations are defined in the metadata of the component that controls the HTML element to be animated. Put the code that defines your animations under the `animations:` property within the `@Component()` decorator.
+Animations are defined in the metadata of the component that controls the HTML element to be animated.
+Put the code that defines your animations under the `animations:` property within the `@Component()` decorator.
+
+
-
+When you've defined an animation trigger for a component, attach it to an element in that component's template by wrapping the trigger name in brackets and preceding it with an `@` symbol.
+Then, you can bind the trigger to a template expression using standard Angular property binding syntax as shown below, where `triggerName` is the name of the trigger, and `expression` evaluates to a defined animation state.
-When you've defined an animation trigger for a component, attach it to an element in that component's template by wrapping the trigger name in brackets and preceding it with an `@` symbol. Then, you can bind the trigger to a template expression using standard Angular property binding syntax as shown below, where `triggerName` is the name of the trigger, and `expression` evaluates to a defined animation state.
+
-```
-...
;
-```
+<div [@triggerName]="expression">…</div>;
+
+
The animation is executed or triggered when the expression value changes to a new state.
The following code snippet binds the trigger to the value of the `isOpen` property.
-
-
+
-In this example, when the `isOpen` expression evaluates to a defined state of `open` or `closed`, it notifies the trigger `openClose` of a state change. Then it's up to the `openClose` code to handle the state change and kick off a state change animation.
+In this example, when the `isOpen` expression evaluates to a defined state of `open` or `closed`, it notifies the trigger `openClose` of a state change.
+Then it's up to the `openClose` code to handle the state change and kick off a state change animation.
-For elements entering or leaving a page (inserted or removed from the DOM), you can make the animations conditional. For example, use `*ngIf` with the animation trigger in the HTML template.
+For elements entering or leaving a page \(inserted or removed from the DOM\), you can make the animations conditional.
+For example, use `*ngIf` with the animation trigger in the HTML template.
-**Note:** In the component file, set the trigger that defines the animations as the value of the `animations:` property in the `@Component()` decorator.
+**NOTE**:
+In the component file, set the trigger that defines the animations as the value of the `animations:` property in the `@Component()` decorator.
In the HTML template file, use the trigger name to attach the defined animations to the HTML element to be animated.
@@ -215,107 +280,39 @@ In the HTML template file, use the trigger name to attach the defined animations
Here are the code files discussed in the transition example.
-
-
-
-
-
-
-
-
-
-
+
+
+
### Summary
-You learned to add animation to a transition between two states, using `style()` and
[state](api/animations/state)()
along with `animate()` for the timing.
+You learned to add animation to a transition between two states, using `style()` and [`state()`](api/animations/state) along with `animate()` for the timing.
Learn about more advanced features in Angular animations under the Animation section, beginning with advanced techniques in [transition and triggers](guide/transition-and-triggers).
-{@a animation-api-summary}
+
+
## Animations API summary
-The functional API provided by the `@angular/animations` module provides a domain-specific language (DSL) for creating and controlling animations in Angular applications. See the [API reference](api/animations) for a complete listing and syntax details of the core functions and related data structures.
-
-
-
-
-
-Function name
-
-
-
-What it does
-
-
-
-
-trigger()
-Kicks off the animation and serves as a container for all other animation function calls. HTML template binds to triggerName
. Use the first argument to declare a unique trigger name. Uses array syntax.
-
-
-
-style()
-Defines one or more CSS styles to use in animations. Controls the visual appearance of HTML elements during animations. Uses object syntax.
-
-
-
-state ()
-Creates a named set of CSS styles that should be applied on successful transition to a given state. The state can then be referenced by name within other animation functions.
-
-
-
-animate()
-Specifies the timing information for a transition. Optional values for delay
and easing
. Can contain style()
calls within.
-
-
-
-transition()
-Defines the animation sequence between two named states. Uses array syntax.
-
-
-
-keyframes()
-Allows a sequential change between styles within a specified time interval. Use within animate()
. Can include multiple style()
calls within each keyframe()
. Uses array syntax.
-
-
-
-group ()
-Specifies a group of animation steps (inner animations ) to be run in parallel. Animation continues only after all inner animation steps have completed. Used within sequence()
or transition()
.
-
-
-
-query()
-Finds one or more inner HTML elements within the current element.
-
-
-
-sequence()
-Specifies a list of animation steps that are run sequentially, one by one.
-
-
-
-stagger()
-Staggers the starting time for animations for multiple elements.
-
-
-
-animation()
-Produces a reusable animation that can be invoked from elsewhere. Used together with useAnimation()
.
-
-
-
-useAnimation()
-Activates a reusable animation. Used with animation()
.
-
-
-
-animateChild()
-Allows animations on child components to be run within the same timeframe as the parent.
-
+The functional API provided by the `@angular/animations` module provides a domain-specific language \(DSL\) for creating and controlling animations in Angular applications.
+See the [API reference](api/animations) for a complete listing and syntax details of the core functions and related data structures.
+
+| Function name | What it does |
+|:--- |:--- |
+| `trigger()` | Kicks off the animation and serves as a container for all other animation function calls. HTML template binds to `triggerName`. Use the first argument to declare a unique trigger name. Uses array syntax. |
+| `style()` | Defines one or more CSS styles to use in animations. Controls the visual appearance of HTML elements during animations. Uses object syntax. |
+| [`state()`](api/animations/state) | Creates a named set of CSS styles that should be applied on successful transition to a given state. The state can then be referenced by name within other animation functions. |
+| `animate()` | Specifies the timing information for a transition. Optional values for `delay` and `easing`. Can contain `style()` calls within. |
+| `transition()` | Defines the animation sequence between two named states. Uses array syntax. |
+| `keyframes()` | Allows a sequential change between styles within a specified time interval. Use within `animate()`. Can include multiple `style()` calls within each `keyframe()`. Uses array syntax. |
+| [`group()`](api/animations/group) | Specifies a group of animation steps \(*inner animations*\) to be run in parallel. Animation continues only after all inner animation steps have completed. Used within `sequence()` or `transition()`. |
+| `query()` | Finds one or more inner HTML elements within the current element. |
+| `sequence()` | Specifies a list of animation steps that are run sequentially, one by one. |
+| `stagger()` | Staggers the starting time for animations for multiple elements. |
+| `animation()` | Produces a reusable animation that can be invoked from elsewhere. Used together with `useAnimation()`. |
+| `useAnimation()` | Activates a reusable animation. Used with `animation()`. |
+| `animateChild()` | Allows animations on child components to be run within the same timeframe as the parent. |
@@ -323,12 +320,21 @@ What it does
You might also be interested in the following:
-* [Transition and triggers](guide/transition-and-triggers)
-* [Complex animation sequences](guide/complex-animation-sequences)
-* [Reusable animations](guide/reusable-animations)
-* [Route transition animations](guide/route-animations)
+* [Transition and triggers](guide/transition-and-triggers)
+* [Complex animation sequences](guide/complex-animation-sequences)
+* [Reusable animations](guide/reusable-animations)
+* [Route transition animations](guide/route-animations)
Check out this [presentation](https://www.youtube.com/watch?v=rnTK9meY5us), shown at the AngularConnect conference in November 2017, and the accompanying [source code](https://github.com/matsko/animationsftw.in).
+
+
+
+
+
+
+
+
+@reviewed 2022-02-28
diff --git a/aio/content/guide/aot-compiler.md b/aio/content/guide/aot-compiler.md
index e724605a65390..d7ea1477e3402 100644
--- a/aio/content/guide/aot-compiler.md
+++ b/aio/content/guide/aot-compiler.md
@@ -1,52 +1,44 @@
# Ahead-of-time (AOT) compilation
-An Angular application consists mainly of components and their HTML templates. Because the components and templates provided by Angular cannot be understood by the browser directly, Angular applications require a compilation process before they can run in a browser.
+An Angular application consists mainly of components and their HTML templates.
+Because the components and templates provided by Angular cannot be understood by the browser directly, Angular applications require a compilation process before they can run in a browser.
-The Angular [ahead-of-time (AOT) compiler](guide/glossary#aot) converts your Angular HTML and TypeScript code into efficient JavaScript code during the build phase _before_ the browser downloads and runs that code. Compiling your application during the build process provides a faster rendering in the browser.
+The Angular [ahead-of-time (AOT) compiler](guide/glossary#aot) converts your Angular HTML and TypeScript code into efficient JavaScript code during the build phase *before* the browser downloads and runs that code.
+Compiling your application during the build process provides a faster rendering in the browser.
This guide explains how to specify metadata and apply available compiler options to compile your applications efficiently using the AOT compiler.
-{@a why-aot}
+
Here are some reasons you might want to use AOT.
-* *Faster rendering*
- With AOT, the browser downloads a pre-compiled version of the application.
- The browser loads executable code so it can render the application immediately, without waiting to compile the application first.
+| Reasons | Details |
+|:--- |:--- |
+| Faster rendering | With AOT, the browser downloads a pre-compiled version of the application. The browser loads executable code so it can render the application immediately, without waiting to compile the application first. |
+| Fewer asynchronous requests | The compiler *inlines* external HTML templates and CSS style sheets within the application JavaScript, eliminating separate ajax requests for those source files. |
+| Smaller Angular framework download size | There's no need to download the Angular compiler if the application is already compiled. The compiler is roughly half of Angular itself, so omitting it dramatically reduces the application payload. |
+| Detect template errors earlier | The AOT compiler detects and reports template binding errors during the build step before users can see them. |
+| Better security | AOT compiles HTML templates and components into JavaScript files long before they are served to the client. With no templates to read and no risky client-side HTML or JavaScript evaluation, there are fewer opportunities for injection attacks. |
-* *Fewer asynchronous requests*
- The compiler _inlines_ external HTML templates and CSS style sheets within the application JavaScript,
- eliminating separate ajax requests for those source files.
-
-* *Smaller Angular framework download size*
- There's no need to download the Angular compiler if the application is already compiled.
- The compiler is roughly half of Angular itself, so omitting it dramatically reduces the application payload.
-
-* *Detect template errors earlier*
- The AOT compiler detects and reports template binding errors during the build step
- before users can see them.
-
-* *Better security*
- AOT compiles HTML templates and components into JavaScript files long before they are served to the client.
- With no templates to read and no risky client-side HTML or JavaScript evaluation,
- there are fewer opportunities for injection attacks.
-
-{@a overview}
+
## Choosing a compiler
Angular offers two ways to compile your application:
-* **_Just-in-Time_ (JIT)**, which compiles your application in the browser at runtime. This was the default until Angular 8.
-* **_Ahead-of-Time_ (AOT)**, which compiles your application and libraries at build time. This is the default since Angular 9.
+| Angular compile | Details |
+|:--- |:--- |
+| Just-in-Time \(JIT\) | Compiles your application in the browser at runtime. This was the default until Angular 8. |
+| Ahead-of-Time \(AOT\) | Compiles your application and libraries at build time. This is the default starting in Angular 9. |
-When you run the [`ng build`](cli/build) (build only) or [`ng serve`](cli/serve) (build and serve locally) CLI commands, the type of compilation (JIT or AOT) depends on the value of the `aot` property in your build configuration specified in `angular.json`. By default, `aot` is set to `true` for new CLI applications.
+When you run the [`ng build`](cli/build) \(build only\) or [`ng serve`](cli/serve) \(build and serve locally\) CLI commands, the type of compilation \(JIT or AOT\) depends on the value of the `aot` property in your build configuration specified in `angular.json`.
+By default, `aot` is set to `true` for new CLI applications.
See the [CLI command reference](cli) and [Building and serving Angular apps](guide/build) for more information.
@@ -58,361 +50,257 @@ The metadata tells Angular how to construct instances of your application classe
In the following example, the `@Component()` metadata object and the class constructor tell Angular how to create and display an instance of `TypicalComponent`.
-```typescript
-@Component({
+
+
+@Component({
selector: 'app-typical',
- template: 'A typical component for {{data.name}}
'
+ template: '<div>A typical component for {{data.name}}</div>'
})
export class TypicalComponent {
- @Input() data: TypicalData;
- constructor(private someService: SomeService) { ... }
+ @Input() data: TypicalData;
+ constructor(private someService: SomeService) { … }
}
-```
-The Angular compiler extracts the metadata _once_ and generates a _factory_ for `TypicalComponent`.
+
+
+The Angular compiler extracts the metadata *once* and generates a *factory* for `TypicalComponent`.
When it needs to create a `TypicalComponent` instance, Angular calls the factory, which produces a new visual element, bound to a new instance of the component class with its injected dependency.
### Compilation phases
There are three phases of AOT compilation.
-* Phase 1 is *code analysis*.
- In this phase, the TypeScript compiler and *AOT collector* create a representation of the source. The collector does not attempt to interpret the metadata it collects. It represents the metadata as best it can and records errors when it detects a metadata syntax violation.
-
-* Phase 2 is *code generation*.
- In this phase, the compiler's `StaticReflector` interprets the metadata collected in phase 1, performs additional validation of the metadata, and throws an error if it detects a metadata restriction violation.
-
-* Phase 3 is *template type checking*.
- In this optional phase, the Angular *template compiler* uses the TypeScript compiler to validate the binding expressions in templates. You can enable this phase explicitly by setting the `fullTemplateTypeCheck` configuration option; see [Angular compiler options](guide/angular-compiler-options).
+| | Phase | Details |
+|:--- |:--- |:--- |
+| 1 | code analysis | In this phase, the TypeScript compiler and *AOT collector* create a representation of the source. The collector does not attempt to interpret the metadata it collects. It represents the metadata as best it can and records errors when it detects a metadata syntax violation. |
+| 2 | code generation | In this phase, the compiler's `StaticReflector` interprets the metadata collected in phase 1, performs additional validation of the metadata, and throws an error if it detects a metadata restriction violation. |
+| 3 | template type checking | In this optional phase, the Angular *template compiler* uses the TypeScript compiler to validate the binding expressions in templates. You can enable this phase explicitly by setting the `fullTemplateTypeCheck` configuration option; see [Angular compiler options](guide/angular-compiler-options). |
### Metadata restrictions
-You write metadata in a _subset_ of TypeScript that must conform to the following general constraints:
+You write metadata in a *subset* of TypeScript that must conform to the following general constraints:
-* Limit [expression syntax](#expression-syntax) to the supported subset of JavaScript.
-* Only reference exported symbols after [code folding](#code-folding).
-* Only call [functions supported](#supported-functions) by the compiler.
-* Decorated and data-bound class members must be public.
+* Limit [expression syntax](#expression-syntax) to the supported subset of JavaScript
+* Only reference exported symbols after [code folding](#code-folding)
+* Only call [functions supported](#supported-functions) by the compiler
+* Decorated and data-bound class members must be public
For additional guidelines and instructions on preparing an application for AOT compilation, see [Angular: Writing AOT-friendly applications](https://medium.com/sparkles-blog/angular-writing-aot-friendly-applications-7b64c8afbe3f).
-Errors in AOT compilation commonly occur because of metadata that does not conform to the compiler's requirements (as described more fully below).
+Errors in AOT compilation commonly occur because of metadata that does not conform to the compiler's requirements \(as described more fully below\).
For help in understanding and resolving these problems, see [AOT Metadata Errors](guide/aot-metadata-errors).
### Configuring AOT compilation
-You can provide options in the [TypeScript configuration file](guide/typescript-configuration) that controls the compilation process. See [Angular compiler options](guide/angular-compiler-options) for a complete list of available options.
+You can provide options in the [TypeScript configuration file](guide/typescript-configuration) that controls the compilation process.
+See [Angular compiler options](guide/angular-compiler-options) for a complete list of available options.
## Phase 1: Code analysis
-The TypeScript compiler does some of the analytic work of the first phase. It emits the `.d.ts` _type definition files_ with type information that the AOT compiler needs to generate application code.
+The TypeScript compiler does some of the analytic work of the first phase.
+It emits the `.d.ts` *type definition files* with type information that the AOT compiler needs to generate application code.
At the same time, the AOT **collector** analyzes the metadata recorded in the Angular decorators and outputs metadata information in **`.metadata.json`** files, one per `.d.ts` file.
You can think of `.metadata.json` as a diagram of the overall structure of a decorator's metadata, represented as an [abstract syntax tree (AST)](https://en.wikipedia.org/wiki/Abstract_syntax_tree).
-Angular's [schema.ts](https://github.com/angular/angular/blob/master/packages/compiler-cli/src/metadata/schema.ts)
-describes the JSON format as a collection of TypeScript interfaces.
+Angular's [schema.ts](https://github.com/angular/angular/blob/master/packages/compiler-cli/src/metadata/schema.ts) describes the JSON format as a collection of TypeScript interfaces.
-{@a expression-syntax}
+
+
### Expression syntax limitations
The AOT collector only understands a subset of JavaScript.
Define metadata objects with the following limited syntax:
-
-
-
-
- Syntax
- Example
-
-
- Literal object
- {cherry: true, apple: true, mincemeat: false}
-
-
- Literal array
- ['cherries', 'flour', 'sugar']
-
-
- Spread in literal array
- ['apples', 'flour', ...the_rest]
-
-
- Calls
- bake(ingredients)
-
-
- New
- new Oven()
-
-
- Property access
- pie.slice
-
-
- Array index
- ingredients[0]
-
-
- Identity reference
- Component
-
-
- A template string
- `pie is ${multiplier} times better than cake`
-
- Literal string
- 'pi'
-
-
- Literal number
- 3.14153265
-
-
- Literal boolean
- true
-
-
- Literal null
- null
-
-
- Supported prefix operator
- !cake
-
-
- Supported binary operator
- a+b
-
-
- Conditional operator
- a ? b : c
-
-
- Parentheses
- (a+b)
-
-
-
+| Syntax | Example |
+|:--- |:--- |
+| Literal object | `{cherry: true, apple: true, mincemeat: false}` |
+| Literal array | `['cherries', 'flour', 'sugar']` |
+| Spread in literal array | `['apples', 'flour', …the_rest]` |
+| Calls | `bake(ingredients)` |
+| New | `new Oven()` |
+| Property access | `pie.slice` |
+| Array index | `ingredients[0]` |
+| Identity reference | `Component` |
+| A template string |
`pie is ${multiplier} times better than cake` |
+| Literal string | `'pi'` |
+| Literal number | `3.14153265` |
+| Literal boolean | `true` |
+| Literal null | `null` |
+| Supported prefix operator | `!cake` |
+| Supported binary operator | `a+b` |
+| Conditional operator | `a ? b : c` |
+| Parentheses | `(a+b)` |
If an expression uses unsupported syntax, the collector writes an error node to the `.metadata.json` file.
The compiler later reports the error if it needs that piece of metadata to generate the application code.
- If you want `ngc` to report syntax errors immediately rather than produce a `.metadata.json` file with errors, set the `strictMetadataEmit` option in the TypeScript configuration file.
+If you want `ngc` to report syntax errors immediately rather than produce a `.metadata.json` file with errors, set the `strictMetadataEmit` option in the TypeScript configuration file.
-```
- "angularCompilerOptions": {
- ...
- "strictMetadataEmit" : true
- }
- ```
+
+
+"angularCompilerOptions": {
+ …
+ "strictMetadataEmit" : true
+}
+
+
Angular libraries have this option to ensure that all Angular `.metadata.json` files are clean and it is a best practice to do the same when building your own libraries.
-{@a function-expression}
-{@a arrow-functions}
+
+
+
### No arrow functions
-The AOT compiler does not support [function expressions](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/function)
-and [arrow functions](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions), also called _lambda_ functions.
+The AOT compiler does not support [function expressions](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Operators/function)
+and [arrow functions](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Functions/Arrow_functions), also called *lambda* functions.
Consider the following component decorator:
-```typescript
-@Component({
- ...
- providers: [{provide: server, useFactory: () => new Server()}]
+
+
+@Component({
+ …
+ providers: [{provide: server, useFactory: () => new Server()}]
})
-```
+
+
The AOT collector does not support the arrow function, `() => new Server()`, in a metadata expression.
It generates an error node in place of the function.
-When the compiler later interprets this node, it reports an error that invites you to turn the arrow function into an _exported function_.
+When the compiler later interprets this node, it reports an error that invites you to turn the arrow function into an *exported function*.
You can fix the error by converting to this:
-```typescript
+
+
export function serverFactory() {
return new Server();
}
-@Component({
- ...
+@Component({
+ …
providers: [{provide: server, useFactory: serverFactory}]
})
-```
+
+
In version 5 and later, the compiler automatically performs this rewriting while emitting the `.js` file.
-{@a exported-symbols}
-{@a code-folding}
+
+
+
### Code folding
-The compiler can only resolve references to **_exported_** symbols.
+The compiler can only resolve references to ***exported*** symbols.
The collector, however, can evaluate an expression during collection and record the result in the `.metadata.json`, rather than the original expression.
This allows you to make limited use of non-exported symbols within expressions.
For example, the collector can evaluate the expression `1 + 2 + 3 + 4` and replace it with the result, `10`.
-This process is called _folding_. An expression that can be reduced in this manner is _foldable_.
+This process is called *folding*.
+An expression that can be reduced in this manner is *foldable*.
+
+
-{@a var-declaration}
The collector can evaluate references to module-local `const` declarations and initialized `var` and `let` declarations, effectively removing them from the `.metadata.json` file.
Consider the following component definition:
-```typescript
-const template = '
{{hero.name}}
';
+
-@Component({
+const template = '<div>{{hero.name}}</div>';
+
+@Component({
selector: 'app-hero',
template: template
})
export class HeroComponent {
- @Input() hero: Hero;
+ @Input() hero: Hero;
}
-```
+
+
The compiler could not refer to the `template` constant because it isn't exported.
The collector, however, can fold the `template` constant into the metadata definition by in-lining its contents.
The effect is the same as if you had written:
-```typescript
-@Component({
+
+
+@Component({
selector: 'app-hero',
- template: '{{hero.name}}
'
+ template: '<div>{{hero.name}}</div>'
})
export class HeroComponent {
- @Input() hero: Hero;
+ @Input() hero: Hero;
}
-```
-There is no longer a reference to `template` and, therefore, nothing to trouble the compiler when it later interprets the _collector's_ output in `.metadata.json`.
+
+
+There is no longer a reference to `template` and, therefore, nothing to trouble the compiler when it later interprets the *collector's* output in `.metadata.json`.
You can take this example a step further by including the `template` constant in another expression:
-```typescript
-const template = '
{{hero.name}}
';
+
+
+const template = '<div>{{hero.name}}</div>';
-@Component({
+@Component({
selector: 'app-hero',
- template: template + '{{hero.title}}
'
+ template: template + '<div>{{hero.title}}</div>'
})
export class HeroComponent {
- @Input() hero: Hero;
+ @Input() hero: Hero;
}
-```
-The collector reduces this expression to its equivalent _folded_ string:
+
-```
-'
{{hero.name}}
{{hero.title}}
'
-```
+The collector reduces this expression to its equivalent *folded* string:
+
+
+
+'<div>{{hero.name}}</div><div>{{hero.title}}</div>'
+
+
#### Foldable syntax
The following table describes which expressions the collector can and cannot fold:
-
-
-
-
- Syntax
- Foldable
-
-
- Literal object
- yes
-
-
- Literal array
- yes
-
-
- Spread in literal array
- no
-
-
- Calls
- no
-
-
- New
- no
-
-
- Property access
- yes, if target is foldable
-
-
- Array index
- yes, if target and index are foldable
-
-
- Identity reference
- yes, if it is a reference to a local
-
-
- A template with no substitutions
- yes
-
-
- A template with substitutions
- yes, if the substitutions are foldable
-
-
- Literal string
- yes
-
-
- Literal number
- yes
-
-
- Literal boolean
- yes
-
-
- Literal null
- yes
-
-
- Supported prefix operator
- yes, if operand is foldable
-
-
- Supported binary operator
- yes, if both left and right are foldable
-
-
- Conditional operator
- yes, if condition is foldable
-
-
- Parentheses
- yes, if the expression is foldable
-
-
-
-
-If an expression is not foldable, the collector writes it to `.metadata.json` as an [AST](https://en.wikipedia.org/wiki/Abstract_syntax_tree) for the compiler to resolve.
-
+| Syntax | Foldable |
+|:--- |:--- |
+| Literal object | yes |
+| Literal array | yes |
+| Spread in literal array | no |
+| Calls | no |
+| New | no |
+| Property access | yes, if target is foldable |
+| Array index | yes, if target and index are foldable |
+| Identity reference | yes, if it is a reference to a local |
+| A template with no substitutions | yes |
+| A template with substitutions | yes, if the substitutions are foldable |
+| Literal string | yes |
+| Literal number | yes |
+| Literal boolean | yes |
+| Literal null | yes |
+| Supported prefix operator | yes, if operand is foldable |
+| Supported binary operator | yes, if both left and right are foldable |
+| Conditional operator | yes, if condition is foldable |
+| Parentheses | yes, if the expression is foldable |
+
+If an expression is not foldable, the collector writes it to `.metadata.json` as an [AST](https://en.wikipedia.org/wiki/Abstract*syntax*tree) for the compiler to resolve.
## Phase 2: code generation
@@ -420,48 +308,47 @@ The collector makes no attempt to understand the metadata that it collects and o
It represents the metadata as best it can and records errors when it detects a metadata syntax violation.
It's the compiler's job to interpret the `.metadata.json` in the code generation phase.
-The compiler understands all syntax forms that the collector supports, but it may reject _syntactically_ correct metadata if the _semantics_ violate compiler rules.
+The compiler understands all syntax forms that the collector supports, but it may reject *syntactically* correct metadata if the *semantics* violate compiler rules.
### Public symbols
-The compiler can only reference _exported symbols_.
+The compiler can only reference *exported symbols*.
+
+* Decorated component class members must be public.
+ You cannot make an `@Input()` property private or protected.
-* Decorated component class members must be public. You cannot make an `@Input()` property private or protected.
-* Data bound properties must also be public.
+* Data bound properties must also be public
+
+
+
+
### Supported classes and functions
The collector can represent a function call or object creation with `new` as long as the syntax is valid.
-The compiler, however, can later refuse to generate a call to a _particular_ function or creation of a _particular_ object.
-
-The compiler can only create instances of certain classes, supports only core decorators, and only supports calls to macros (functions or static methods) that return expressions.
-* New instances
-
- The compiler only allows metadata that create instances of the class `InjectionToken` from `@angular/core`.
-
-* Supported decorators
+The compiler, however, can later refuse to generate a call to a *particular* function or creation of a *particular* object.
- The compiler only supports metadata for the [Angular decorators in the `@angular/core` module](api/core#decorators).
+The compiler can only create instances of certain classes, supports only core decorators, and only supports calls to macros \(functions or static methods\) that return expressions.
-* Function calls
+| Compiler action | Details |
+|:--- |:--- |
+| New instances | The compiler only allows metadata that create instances of the class `InjectionToken` from `@angular/core`. |
+| Supported decorators | The compiler only supports metadata for the [Angular decorators in the `@angular/core` module](api/core#decorators). |
+| Function calls | Factory functions must be exported, named functions. The AOT compiler does not support lambda expressions \("arrow functions"\) for factory functions. |
- Factory functions must be exported, named functions.
- The AOT compiler does not support lambda expressions ("arrow functions") for factory functions.
+
-{@a function-calls}
### Functions and static method calls
The collector accepts any function or static method that contains a single `return` statement.
@@ -469,79 +356,90 @@ The compiler, however, only supports macros in the form of functions or static m
For example, consider the following function:
-```typescript
-export function wrapInArray
(value: T): T[] {
+
+
+export function wrapInArray<T>(value: T): T[] {
return [value];
}
-```
+
+
You can call the `wrapInArray` in a metadata definition because it returns the value of an expression that conforms to the compiler's restrictive JavaScript subset.
You might use `wrapInArray()` like this:
-```typescript
-@NgModule({
+
+
+@NgModule({
declarations: wrapInArray(TypicalComponent)
})
export class TypicalModule {}
-```
+
+
The compiler treats this usage as if you had written:
-```typescript
-@NgModule({
+
+
+@NgModule({
declarations: [TypicalComponent]
})
export class TypicalModule {}
-```
+
+
+
The Angular [`RouterModule`](api/router/RouterModule) exports two macro static methods, `forRoot` and `forChild`, to help declare root and child routes.
Review the [source code](https://github.com/angular/angular/blob/master/packages/router/src/router_module.ts#L139 "RouterModule.forRoot source code")
for these methods to see how macros can simplify configuration of complex [NgModules](guide/ngmodules).
-{@a metadata-rewriting}
+
### Metadata rewriting
The compiler treats object literals containing the fields `useClass`, `useValue`, `useFactory`, and `data` specially, converting the expression initializing one of these fields into an exported variable that replaces the expression.
This process of rewriting these expressions removes all the restrictions on what can be in them because
-the compiler doesn't need to know the expression's value—it just needs to be able to generate a reference to the value.
+the compiler doesn't need to know the expression's value —it just needs to be able to generate a reference to the value.
You might write something like:
-```typescript
+
+
class TypicalServer {
}
-@NgModule({
- providers: [{provide: SERVER, useFactory: () => TypicalServer}]
+@NgModule({
+ providers: [{provide: SERVER, useFactory: () => TypicalServer}]
})
export class TypicalModule {}
-```
+
+
Without rewriting, this would be invalid because lambdas are not supported and `TypicalServer` is not exported.
To allow this, the compiler automatically rewrites this to something like:
-```typescript
+
+
class TypicalServer {
}
-export const ɵ0 = () => new TypicalServer();
+export const θ0 = () => new TypicalServer();
-@NgModule({
- providers: [{provide: SERVER, useFactory: ɵ0}]
+@NgModule({
+ providers: [{provide: SERVER, useFactory: θ0}]
})
export class TypicalModule {}
-```
-This allows the compiler to generate a reference to `ɵ0` in the factory without having to know what the value of `ɵ0` contains.
+
-The compiler does the rewriting during the emit of the `.js` file.
-It does not, however, rewrite the `.d.ts` file, so TypeScript doesn't recognize it as being an export. and it does not interfere with the ES module's exported API.
+This allows the compiler to generate a reference to `θ0` in the factory without having to know what the value of `θ0` contains.
+The compiler does the rewriting during the emit of the `.js` file.
+It does not, however, rewrite the `.d.ts` file, so TypeScript doesn't recognize it as being an export.
+And it does not interfere with the ES module's exported API.
-{@a binding-expression-validation}
+
## Phase 3: Template type checking
@@ -557,21 +455,25 @@ file.
For example, consider the following component:
-```typescript
- @Component({
- selector: 'my-component',
- template: '{{person.addresss.street}}'
- })
- class MyComponent {
- person?: Person;
- }
-```
+
+
+@Component({
+ selector: 'my-component',
+ template: '{{person.addresss.street}}'
+})
+class MyComponent {
+ person?: Person;
+}
+
+
This produces the following error:
-```
- my.component.ts.MyComponent.html(1,1): : Property 'addresss' does not exist on type 'Person'. Did you mean 'address'?
- ```
+
+
+my.component.ts.MyComponent.html(1,1): : Property 'addresss' does not exist on type 'Person'. Did you mean 'address'?
+
+
The file name reported in the error message, `my.component.ts.MyComponent.html`, is a synthetic file
generated by the template compiler that holds contents of the `MyComponent` class template.
@@ -585,7 +487,13 @@ location is the location of the attribute that contains the error.
The validation uses the TypeScript type checker and the options supplied to the TypeScript compiler to control how detailed the type validation is.
For example, if the `strictTypeChecks` is specified, the error
-```my.component.ts.MyComponent.html(1,1): : Object is possibly 'undefined'```
+
+
+
+my.component.ts.MyComponent.html(1,1): : Object is possibly 'undefined'
+
+
+
is reported as well as the above error message.
### Type narrowing
@@ -594,15 +502,17 @@ The expression used in an `ngIf` directive is used to narrow type unions in the
template compiler, the same way the `if` expression does in TypeScript.
For example, to avoid `Object is possibly 'undefined'` error in the template above, modify it to only emit the interpolation if the value of `person` is initialized as shown below:
-```typescript
- @Component({
- selector: 'my-component',
- template: ' {{person.address.street}} '
- })
- class MyComponent {
- person?: Person;
- }
-```
+
+
+@Component({
+ selector: 'my-component',
+ template: ' {{person.address.street}} '
+})
+class MyComponent {
+ person?: Person;
+}
+
+
Using `*ngIf` allows the TypeScript compiler to infer that the `person` used in the binding expression will never be `undefined`.
@@ -615,38 +525,50 @@ Use the [non-null type assertion operator](guide/template-expression-operators#n
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`.
-```typescript
- @Component({
- selector: 'my-component',
- template: ' {{person.name}} lives on {{address!.street}} '
- })
- class MyComponent {
- person?: Person;
- address?: Address;
-
- setData(person: Person, address: Address) {
- this.person = person;
- this.address = address;
- }
+
+
+@Component({
+ selector: 'my-component',
+ template: '<span *ngIf="person"> {{person.name}} lives on {{address!.street}} </span>'
+})
+class MyComponent {
+ person?: Person;
+ address?: Address;
+
+ setData(person: Person, address: Address) {
+ this.person = person;
+ this.address = address;
}
-```
+}
+
+
The non-null assertion operator should be used sparingly as refactoring of the component might break this constraint.
In this example it is recommended to include the checking of `address` in the `*ngIf` as shown below:
-```typescript
- @Component({
- selector: 'my-component',
- template: ' {{person.name}} lives on {{address.street}} '
- })
- class MyComponent {
- person?: Person;
- address?: Address;
-
- setData(person: Person, address: Address) {
- this.person = person;
- this.address = address;
- }
+
+
+@Component({
+ selector: 'my-component',
+ template: '<span *ngIf="person && address"> {{person.name}} lives on {{address.street}} </span>'
+})
+class MyComponent {
+ person?: Person;
+ address?: Address;
+
+ setData(person: Person, address: Address) {
+ this.person = person;
+ this.address = address;
}
-```
+}
+
+
+
+
+
+
+
+
+
+@reviewed 2022-02-28
diff --git a/aio/content/guide/aot-metadata-errors.md b/aio/content/guide/aot-metadata-errors.md
index 143199e71b5ea..e57c3a9e864e5 100644
--- a/aio/content/guide/aot-metadata-errors.md
+++ b/aio/content/guide/aot-metadata-errors.md
@@ -2,20 +2,21 @@
The following are metadata errors you may encounter, with explanations and suggested corrections.
-[Expression form not supported](#expression-form-not-supported)
-[Reference to a local (non-exported) symbol](#reference-to-a-local-symbol)
-[Only initialized variables and constants](#only-initialized-variables)
-[Reference to a non-exported class](#reference-to-a-non-exported-class)
-[Reference to a non-exported function](#reference-to-a-non-exported-function)
-[Function calls are not supported](#function-calls-not-supported)
-[Destructured variable or constant not supported](#destructured-variable-not-supported)
-[Could not resolve type](#could-not-resolve-type)
-[Name expected](#name-expected)
-[Unsupported enum member name](#unsupported-enum-member-name)
-[Tagged template expressions are not supported](#tagged-template-expressions-not-supported)
-[Symbol reference expected](#symbol-reference-expected)
-
-{@a expression-form-not-supported}
+[Expression form not supported](#expression-form-not-supported)
+[Reference to a local (non-exported) symbol](#reference-to-a-local-symbol)
+[Only initialized variables and constants](#only-initialized-variables)
+[Reference to a non-exported class](#reference-to-a-non-exported-class)
+[Reference to a non-exported function](#reference-to-a-non-exported-function)
+[Function calls are not supported](#function-calls-not-supported)
+[Destructured variable or constant not supported](#destructured-variable-not-supported)
+[Could not resolve type](#could-not-resolve-type)
+[Name expected](#name-expected)
+[Unsupported enum member name](#unsupported-enum-member-name)
+[Tagged template expressions are not supported](#tagged-template-expressions-not-supported)
+[Symbol reference expected](#symbol-reference-expected)
+
+
+
## Expression form not supported
@@ -27,16 +28,18 @@ The following are metadata errors you may encounter, with explanations and sugge
Language features outside of the compiler's [restricted expression syntax](guide/aot-compiler#expression-syntax)
can produce this error, as seen in the following example:
-```ts
+
+
// ERROR
-export class Fooish { ... }
-...
+export class Fooish { … }
+…
const prop = typeof Fooish; // typeof is not valid in metadata
- ...
+ …
// bracket notation is not valid in metadata
{ provide: 'token', useValue: { [prop]: 'value' } };
- ...
-```
+ …
+
+
You can use `typeof` and bracket notation in normal application code.
You just can't use those features within expressions that define Angular metadata.
@@ -45,12 +48,13 @@ Avoid this error by sticking to the compiler's [restricted expression syntax](gu
when writing Angular metadata
and be wary of new or unusual TypeScript features.
-{@a reference-to-a-local-symbol}
+
+
## Reference to a local (non-exported) symbol
-_Reference to a local (non-exported) symbol 'symbol name'. Consider exporting the symbol._
+*Reference to a local \(non-exported\) symbol 'symbol name'. Consider exporting the symbol.*
@@ -58,170 +62,191 @@ The compiler encountered a referenced to a locally defined symbol that either wa
Here's a `provider` example of the problem.
-```ts
+
+
// ERROR
let foo: number; // neither exported nor initialized
-@Component({
+@Component({
selector: 'my-component',
- template: ... ,
+ template: … ,
providers: [
{ provide: Foo, useValue: foo }
]
})
export class MyComponent {}
-```
-The compiler generates the component factory, which includes the `useValue` provider code, in a separate module. _That_ factory module can't reach back to _this_ source module to access the local (non-exported) `foo` variable.
+
+
+
+The compiler generates the component factory, which includes the `useValue` provider code, in a separate module.
+*That* factory module can't reach back to *this* source module to access the local \(non-exported\) `foo` variable.
You could fix the problem by initializing `foo`.
-```ts
+
+
let foo = 42; // initialized
-```
+
+
The compiler will [fold](guide/aot-compiler#code-folding) the expression into the provider as if you had written this.
-```ts
- providers: [
- { provide: Foo, useValue: 42 }
- ]
-```
+
+
+providers: [
+ { provide: Foo, useValue: 42 }
+]
+
+
Alternatively, you can fix it by exporting `foo` with the expectation that `foo` will be assigned at runtime when you actually know its value.
-```ts
+
+
// CORRECTED
export let foo: number; // exported
-@Component({
+@Component({
selector: 'my-component',
- template: ... ,
+ template: … ,
providers: [
{ provide: Foo, useValue: foo }
]
})
export class MyComponent {}
-```
-Adding `export` often works for variables referenced in metadata such as `providers` and `animations` because the compiler can generate _references_ to the exported variables in these expressions. It doesn't need the _values_ of those variables.
+
-Adding `export` doesn't work when the compiler needs the _actual value_
-in order to generate code.
+Adding `export` often works for variables referenced in metadata such as `providers` and `animations` because the compiler can generate *references* to the exported variables in these expressions.
+It doesn't need the *values* of those variables.
+
+Adding `export` doesn't work when the compiler needs the *actual value* in order to generate code.
For example, it doesn't work for the `template` property.
-```ts
+
+
// ERROR
export let someTemplate: string; // exported but not initialized
-@Component({
+@Component({
selector: 'my-component',
template: someTemplate
})
export class MyComponent {}
-```
-The compiler needs the value of the `template` property _right now_ to generate the component factory.
+
+
+The compiler needs the value of the `template` property *right now* to generate the component factory.
The variable reference alone is insufficient.
Prefixing the declaration with `export` merely produces a new error, "[`Only initialized variables and constants can be referenced`](#only-initialized-variables)".
-{@a only-initialized-variables}
+
+
## Only initialized variables and constants
-_Only initialized variables and constants can be referenced because the value of this variable is needed by the template compiler._
+*Only initialized variables and constants can be referenced because the value of this variable is needed by the template compiler.*
The compiler found a reference to an exported variable or static field that wasn't initialized.
It needs the value of that variable to generate code.
-The following example tries to set the component's `template` property to the value of
-the exported `someTemplate` variable which is declared but _unassigned_.
+The following example tries to set the component's `template` property to the value of the exported `someTemplate` variable which is declared but *unassigned*.
+
+
-```ts
// ERROR
export let someTemplate: string;
-@Component({
+@Component({
selector: 'my-component',
template: someTemplate
})
export class MyComponent {}
-```
+
+
You'd also get this error if you imported `someTemplate` from some other module and neglected to initialize it there.
-```ts
+
+
// ERROR - not initialized there either
import { someTemplate } from './config';
-@Component({
+@Component({
selector: 'my-component',
template: someTemplate
})
export class MyComponent {}
-```
+
+
The compiler cannot wait until runtime to get the template information.
-It must statically derive the value of the `someTemplate` variable from the source code
-so that it can generate the component factory, which includes
-instructions for building the element based on the template.
+It must statically derive the value of the `someTemplate` variable from the source code so that it can generate the component factory, which includes instructions for building the element based on the template.
+
+To correct this error, provide the initial value of the variable in an initializer clause *on the same line*.
-To correct this error, provide the initial value of the variable in an initializer clause _on the same line_.
+
-```ts
// CORRECTED
-export let someTemplate = 'Greetings from Angular ';
+export let someTemplate = '<h1>Greetings from Angular</h1>';
-@Component({
+@Component({
selector: 'my-component',
template: someTemplate
})
export class MyComponent {}
-```
-{@a reference-to-a-non-exported-class}
+
+
+
+
## Reference to a non-exported class
-_Reference to a non-exported class . Consider exporting the class._
+*Reference to a non-exported class ``.*
+*Consider exporting the class.*
Metadata referenced a class that wasn't exported.
-For example, you may have defined a class and used it as an injection token in a providers array
-but neglected to export that class.
+For example, you may have defined a class and used it as an injection token in a providers array but neglected to export that class.
+
+
-```ts
// ERROR
abstract class MyStrategy { }
- ...
+ …
providers: [
- { provide: MyStrategy, useValue: ... }
+ { provide: MyStrategy, useValue: … }
]
- ...
-```
+ …
+
+
-Angular generates a class factory in a separate module and that
-factory [can only access exported classes](guide/aot-compiler#exported-symbols).
+Angular generates a class factory in a separate module and that factory [can only access exported classes](guide/aot-compiler#exported-symbols).
To correct this error, export the referenced class.
-```ts
+
+
// CORRECTED
export abstract class MyStrategy { }
- ...
+ …
providers: [
- { provide: MyStrategy, useValue: ... }
+ { provide: MyStrategy, useValue: … }
]
- ...
-```
+ …
+
+
+
+
-{@a reference-to-a-non-exported-function}
## Reference to a non-exported function
@@ -232,92 +257,104 @@ export abstract class MyStrategy { }
For example, you may have set a providers `useFactory` property to a locally defined function that you neglected to export.
-```ts
+
+
// ERROR
-function myStrategy() { ... }
+function myStrategy() { … }
- ...
+ …
providers: [
{ provide: MyStrategy, useFactory: myStrategy }
]
- ...
-```
+ …
-Angular generates a class factory in a separate module and that
-factory [can only access exported functions](guide/aot-compiler#exported-symbols).
+
+
+Angular generates a class factory in a separate module and that factory [can only access exported functions](guide/aot-compiler#exported-symbols).
To correct this error, export the function.
-```ts
+
+
// CORRECTED
-export function myStrategy() { ... }
+export function myStrategy() { … }
- ...
+ …
providers: [
{ provide: MyStrategy, useFactory: myStrategy }
]
- ...
-```
+ …
+
+
+
+
-{@a function-calls-not-supported}
## Function calls are not supported
-_Function calls are not supported. Consider replacing the function or lambda with a reference to an exported function._
+*Function calls are not supported. Consider replacing the function or lambda with a reference to an exported function.*
The compiler does not currently support [function expressions or lambda functions](guide/aot-compiler#function-expression).
For example, you cannot set a provider's `useFactory` to an anonymous function or arrow function like this.
-```ts
+
+
// ERROR
- ...
+ …
providers: [
- { provide: MyStrategy, useFactory: function() { ... } },
- { provide: OtherStrategy, useFactory: () => { ... } }
+ { provide: MyStrategy, useFactory: function() { … } },
+ { provide: OtherStrategy, useFactory: () => { … } }
]
- ...
-```
+ …
+
+
+
You also get this error if you call a function or method in a provider's `useValue`.
-```ts
+
+
// ERROR
import { calculateValue } from './utilities';
- ...
+ …
providers: [
{ provide: SomeValue, useValue: calculateValue() }
]
- ...
-```
+ …
+
+
To correct this error, export a function from the module and refer to the function in a `useFactory` provider instead.
-```ts
+
+
// CORRECTED
import { calculateValue } from './utilities';
-export function myStrategy() { ... }
-export function otherStrategy() { ... }
+export function myStrategy() { … }
+export function otherStrategy() { … }
export function someValueFactory() {
return calculateValue();
}
- ...
+ …
providers: [
{ provide: MyStrategy, useFactory: myStrategy },
{ provide: OtherStrategy, useFactory: otherStrategy },
{ provide: SomeValue, useFactory: someValueFactory }
]
- ...
-```
+ …
+
+
+
+
-{@a destructured-variable-not-supported}
## Destructured variable or constant not supported
-_Referencing an exported destructured variable or constant is not supported by the template compiler. Consider simplifying this to avoid destructuring._
+*Referencing an exported destructured variable or constant is not supported by the template compiler. Consider simplifying this to avoid destructuring.*
@@ -325,34 +362,39 @@ The compiler does not support references to variables assigned by [destructuring
For example, you cannot write something like this:
-```ts
+
+
// ERROR
import { configuration } from './configuration';
// destructured assignment to foo and bar
const {foo, bar} = configuration;
- ...
+ …
providers: [
{provide: Foo, useValue: foo},
{provide: Bar, useValue: bar},
]
- ...
-```
+ …
+
+
To correct this error, refer to non-destructured values.
-```ts
+
+
// CORRECTED
import { configuration } from './configuration';
- ...
+ …
providers: [
{provide: Foo, useValue: configuration.foo},
{provide: Bar, useValue: configuration.bar},
]
- ...
-```
+ …
+
+
+
+
-{@a could-not-resolve-type}
## Could not resolve type
@@ -364,16 +406,18 @@ import { configuration } from './configuration';
This can happen if you refer to an ambient type.
For example, the `Window` type is an ambient type declared in the global `.d.ts` file.
-You'll get an error if you reference it in the component constructor,
-which the compiler must statically analyze.
+You'll get an error if you reference it in the component constructor, which the compiler must statically analyze.
+
+
-```ts
// ERROR
-@Component({ })
+@Component({ })
export class MyComponent {
- constructor (private win: Window) { ... }
+ constructor (private win: Window) { … }
}
-```
+
+
+
TypeScript understands ambient types so you don't import them.
The Angular compiler does not understand a type that you neglect to export or import.
@@ -384,47 +428,51 @@ Do not refer to ambient types in metadata expressions.
If you must inject an instance of an ambient type,
you can finesse the problem in four steps:
-1. Create an injection token for an instance of the ambient type.
-1. Create a factory function that returns that instance.
-1. Add a `useFactory` provider with that factory function.
-1. Use `@Inject` to inject the instance.
+1. Create an injection token for an instance of the ambient type.
+1. Create a factory function that returns that instance.
+1. Add a `useFactory` provider with that factory function.
+1. Use `@Inject` to inject the instance.
Here's an illustrative example.
-```ts
+
+
// CORRECTED
-import { Inject } from '@angular/core';
+import { Inject } from '@angular/core';
export const WINDOW = new InjectionToken('Window');
export function _window() { return window; }
-@Component({
- ...
+@Component({
+ …
providers: [
{ provide: WINDOW, useFactory: _window }
]
})
export class MyComponent {
- constructor (@Inject(WINDOW) private win: Window) { ... }
+ constructor (@Inject(WINDOW) private win: Window) { … }
}
-```
-The `Window` type in the constructor is no longer a problem for the compiler because it
-uses the `@Inject(WINDOW)` to generate the injection code.
+
+
+The `Window` type in the constructor is no longer a problem for the compiler because it uses the `@Inject(WINDOW)` to generate the injection code.
-Angular does something similar with the `DOCUMENT` token so you can inject the browser's `document` object (or an abstraction of it, depending upon the platform in which the application runs).
+Angular does something similar with the `DOCUMENT` token so you can inject the browser's `document` object \(or an abstraction of it, depending upon the platform in which the application runs\).
-```ts
-import { Inject } from '@angular/core';
-import { DOCUMENT } from '@angular/common';
+
-@Component({ ... })
+import { Inject } from '@angular/core';
+import { DOCUMENT } from '@angular/common';
+
+@Component({ … })
export class MyComponent {
- constructor (@Inject(DOCUMENT) private doc: Document) { ... }
+ constructor (@Inject(DOCUMENT) private doc: Document) { … }
}
-```
-{@a name-expected}
+
+
+
+
## Name expected
@@ -435,19 +483,24 @@ export class MyComponent {
This can happen if you use a number as a property name as in the following example.
-```ts
+
+
// ERROR
provider: [{ provide: Foo, useValue: { 0: 'test' } }]
-```
+
+
Change the name of the property to something non-numeric.
-```ts
+
+
// CORRECTED
provider: [{ provide: Foo, useValue: { '0': 'test' } }]
-```
-{@a unsupported-enum-member-name}
+
+
+
+
## Unsupported enum member name
@@ -458,7 +511,8 @@ provider: [{ provide: Foo, useValue: { '0': 'test' } }]
The compiler can understand simple enum values but not complex values such as those derived from computed properties.
-```ts
+
+
// ERROR
enum Colors {
Red = 1,
@@ -466,42 +520,47 @@ enum Colors {
Blue = "Blue".length // computed
}
- ...
+ …
providers: [
{ provide: BaseColor, useValue: Colors.White } // ok
{ provide: DangerColor, useValue: Colors.Red } // ok
{ provide: StrongColor, useValue: Colors.Blue } // bad
]
- ...
-```
+ …
+
+
Avoid referring to enums with complicated initializers or computed properties.
-{@a tagged-template-expressions-not-supported}
+
+
## Tagged template expressions are not supported
-_Tagged template expressions are not supported in metadata._
+*Tagged template expressions are not supported in metadata.*
-The compiler encountered a JavaScript ES2015 [tagged template expression](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals#Tagged_template_literals) such as the following.
+The compiler encountered a JavaScript ES2015 [tagged template expression](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Template_literals#Tagged_template_literals) such as the following.
+
+
-```ts
// ERROR
const expression = 'funky';
-const raw = String.raw`A tagged template ${expression} string`;
- ...
- template: '' + raw + '
'
- ...
-```
-[`String.raw()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/raw)
-is a _tag function_ native to JavaScript ES2015.
+const raw = String.raw`A tagged template ${expression} string`;
+ …
+ template: '<div>' + raw + '</div>'
+ …
+
+
+
+[`String.raw()`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String/raw) is a *tag function* native to JavaScript ES2015.
The AOT compiler does not support tagged template expressions; avoid them in metadata expressions.
-{@a symbol-reference-expected}
+
+
## Symbol reference expected
@@ -512,8 +571,12 @@ The AOT compiler does not support tagged template expressions; avoid them in met
This error can occur if you use an expression in the `extends` clause of a class.
-
+
+
+
+
-Chuck: After reviewing your PR comment I'm still at a loss. See [comment there](https://github.com/angular/angular/pull/17712#discussion_r132025495).
+
--->
+@reviewed 2022-02-28
diff --git a/aio/content/guide/app-shell.md b/aio/content/guide/app-shell.md
index 58ad12c87680f..6ab9a93de921e 100644
--- a/aio/content/guide/app-shell.md
+++ b/aio/content/guide/app-shell.md
@@ -1,7 +1,7 @@
# App shell
Application shell is a way to render a portion of your application using a route at build time.
-It can improve the user experience by quickly launching a static rendered page (a skeleton common to all pages) while the browser downloads the full client version and switches to it automatically after the code loads.
+It can improve the user experience by quickly launching a static rendered page \(a skeleton common to all pages\) while the browser downloads the full client version and switches to it automatically after the code loads.
This gives users a meaningful first paint of your application that appears quickly because the browser can render the HTML and CSS without the need to initialize any JavaScript.
@@ -10,8 +10,11 @@ Learn more in [The App Shell Model](https://developers.google.com/web/fundamenta
## Step 1: Prepare the application
Do this with the following CLI command:
-
+
+
+
ng new my-app --routing
+
For an existing application, you have to manually add the `RouterModule` and defining a `` within your application.
@@ -20,17 +23,20 @@ For an existing application, you have to manually add the `RouterModule` and def
Use the CLI to automatically create the application shell.
-
+
+
ng generate app-shell
+
-For more information about this command see [App shell command](cli/generate#app-shell-command).
+For more information about this command, see [App shell command](cli/generate#app-shell-command).
After running this command you can see that the `angular.json` configuration file has been updated to add two new targets, with a few other changes.
+
"server": {
- "builder": "@angular-devkit/build-angular:server",
+ "builder": "@angular-devkit/build-angular:server",
"defaultConfiguration": "production",
"options": {
"outputPath": "dist/my-app/server",
@@ -55,7 +61,7 @@ After running this command you can see that the `angular.json` configuration fil
}
},
"app-shell": {
- "builder": "@angular-devkit/build-angular:app-shell",
+ "builder": "@angular-devkit/build-angular:app-shell",
"defaultConfiguration": "production",
"options": {
"route": "shell"
@@ -71,20 +77,34 @@ After running this command you can see that the `angular.json` configuration fil
}
}
}
+
## Step 3: Verify the app is built with the shell content
Use the CLI to build the `app-shell` target.
-
+
+
ng run my-app:app-shell:development
+
Or to use the production configuration.
-
+
+
ng run my-app:app-shell:production
+
-To verify the build output, open dist/my-app/browser/index.html
. Look for default text `app-shell works!` to show that the application shell route was rendered as part of the output.
+To verify the build output, open dist/my-app/browser/index.html
.
+Look for default text `app-shell works!` to show that the application shell route was rendered as part of the output.
+
+
+
+
+
+
+
+@reviewed 2022-02-28
diff --git a/aio/content/guide/architecture-components.md b/aio/content/guide/architecture-components.md
index 490a6fdd3455a..204c20f7b3e0a 100644
--- a/aio/content/guide/architecture-components.md
+++ b/aio/content/guide/architecture-components.md
@@ -3,11 +3,11 @@
A *component* controls a patch of screen called a [*view*](guide/glossary#view "Definition of view").
For example, individual components define and control each of the following views from the [Tour of Heroes tutorial](tutorial):
-* The application root with the navigation links.
-* The list of heroes.
-* The hero editor.
+* The application root with the navigation links
+* The list of heroes
+* The hero editor
-You define a component's application logic—what it does to support the view—inside a class.
+You define a component's application logic —what it does to support the view— inside a class.
The class interacts with the view through an API of properties and methods.
For example, `HeroListComponent` has a `heroes` property that holds an array of heroes.
@@ -15,176 +15,223 @@ Its `selectHero()` method sets a `selectedHero` property when the user clicks to
The component acquires the heroes from a service, which is a TypeScript [parameter property](https://www.typescriptlang.org/docs/handbook/classes.html#parameter-properties) on the constructor.
The service is provided to the component through the dependency injection system.
-
+
-Angular creates, updates, and destroys components as the user moves through the application. Your application can take action at each moment in this lifecycle through optional [lifecycle hooks](guide/lifecycle-hooks), like `ngOnInit()`.
+Angular creates, updates, and destroys components as the user moves through the application.
+Your application can take action at each moment in this lifecycle through optional [lifecycle hooks](guide/lifecycle-hooks), like `ngOnInit()`.
## Component metadata
-
+
+
+
+
+
-The `@Component` decorator identifies the class immediately below it as a component class, and specifies its metadata. In the example code below, you can see that `HeroListComponent` is just a class, with no special Angular notation or syntax at all. It's not a component until you mark it as one with the `@Component` decorator.
+The `@Component` decorator identifies the class immediately below it as a component class, and specifies its metadata.
+In the example code below, you can see that `HeroListComponent` is just a class, with no special Angular notation or syntax at all.
+It's not a component until you mark it as one with the `@Component` decorator.
-The metadata for a component tells Angular where to get the major building blocks that it needs to create and present the component and its view. In particular, it associates a *template* with the component, either directly with inline code, or by reference. Together, the component and its template describe a *view*.
+The metadata for a component tells Angular where to get the major building blocks that it needs to create and present the component and its view.
+In particular, it associates a *template* with the component, either directly with inline code, or by reference.
+Together, the component and its template describe a *view*.
In addition to containing or pointing to the template, the `@Component` metadata configures, for example, how the component can be referenced in HTML and what services it requires.
Here's an example of basic metadata for `HeroListComponent`.
-
+
This example shows some of the most useful `@Component` configuration options:
-* `selector`: A CSS selector that tells Angular to create and insert an instance of this component wherever it finds the corresponding tag in template HTML. For example, if an application's HTML contains ` `, then
-Angular inserts an instance of the `HeroListComponent` view between those tags.
+| Configuration options | Details |
+|:--- |:--- |
+| `selector` | A CSS selector that tells Angular to create and insert an instance of this component wherever it finds the corresponding tag in template HTML. For example, if an application's HTML contains ` `, then Angular inserts an instance of the `HeroListComponent` view between those tags. |
+| `templateUrl` | The module-relative address of this component's HTML template. Alternatively, you can provide the HTML template inline, as the value of the `template` property. This template defines the component's *host view*. |
+| `providers` | An array of [providers](guide/glossary#provider) for services that the component requires. In the example, this tells Angular how to provide the `HeroService` instance that the component's constructor uses to get the list of heroes to display. |
-* `templateUrl`: The module-relative address of this component's HTML template. Alternatively, you can provide the HTML template inline, as the value of the `template` property. This template defines the component's *host view*.
-
-* `providers`: An array of [providers](guide/glossary#provider) for services that the component requires. In the example, this tells Angular how to provide the `HeroService` instance that the component's constructor uses to get the list of heroes to display.
+## Templates and views
+
-## Templates and views
+
-
+
-You define a component's view with its companion template. A template is a form of HTML that tells Angular how to render the component.
+You define a component's view with its companion template.
+A template is a form of HTML that tells Angular how to render the component.
-Views are typically arranged hierarchically, allowing you to modify or show and hide entire UI sections or pages as a unit. The template immediately associated with a component defines that component's *host view*. The component can also define a *view hierarchy*, which contains *embedded views*, hosted by other components.
+Views are typically arranged hierarchically, allowing you to modify or show and hide entire UI sections or pages as a unit.
+The template immediately associated with a component defines that component's *host view*.
+The component can also define a *view hierarchy*, which contains *embedded views*, hosted by other components.
-
+
+
+
-A view hierarchy can include views from components in the same NgModule, but it also can (and often does) include views from components that are defined in different NgModules.
+A view hierarchy can include views from components in the same NgModule, but it also can \(and often does\) include views from components that are defined in different NgModules.
## Template syntax
-A template looks like regular HTML, except that it also contains Angular [template syntax](guide/template-syntax), which alters the HTML based on your application's logic and the state of application and DOM data. Your template can use *data binding* to coordinate the application and DOM data, *pipes* to transform data before it is displayed, and *directives* to apply application logic to what gets displayed.
+A template looks like regular HTML, except that it also contains Angular [template syntax](guide/template-syntax), which alters the HTML based on your application's logic and the state of application and DOM data.
+Your template can use *data binding* to coordinate the application and DOM data, *pipes* to transform data before it is displayed, and *directives* to apply application logic to what gets displayed.
For example, here is a template for the Tutorial's `HeroListComponent`.
-
+
+
+This template uses typical HTML elements like `` and ` `, and also includes Angular template-syntax elements, `*ngFor`, `{{hero.name}}`, `(click)`, `[hero]`, and ``.
+The template-syntax elements tell Angular how to render the HTML to the screen, using program logic and data.
-This template uses typical HTML elements like `` and ` `, and also includes Angular template-syntax elements, `*ngFor`, `{{hero.name}}`, `(click)`, `[hero]`, and ``. The template-syntax elements tell Angular how to render the HTML to the screen, using program logic and data.
+* The `*ngFor` directive tells Angular to iterate over a list
+* `{{hero.name}}`, `(click)`, and `[hero]` bind program data to and from the DOM, responding to user input.
+ See more about [data binding](#data-binding) below.
-* The `*ngFor` directive tells Angular to iterate over a list.
-* `{{hero.name}}`, `(click)`, and `[hero]` bind program data to and from the DOM, responding to user input. See more about [data binding](#data-binding) below.
-* The `` tag in the example is an element that represents a new component, `HeroDetailComponent`.
-`HeroDetailComponent` (code not shown) defines the hero-detail child view of `HeroListComponent`.
-Notice how custom components like this mix seamlessly with native HTML in the same layouts.
+* The `` tag in the example is an element that represents a new component, `HeroDetailComponent`.
+ `HeroDetailComponent` \(code not shown\) defines the hero-detail child view of `HeroListComponent`.
+ Notice how custom components like this mix seamlessly with native HTML in the same layouts.
### Data binding
-Without a framework, you would be responsible for pushing data values into the HTML controls and turning user responses into actions and value updates. Writing such push and pull logic by hand is tedious, error-prone, and a nightmare to read, as any experienced front-end JavaScript programmer can attest.
+Without a framework, you would be responsible for pushing data values into the HTML controls and turning user responses into actions and value updates.
+Writing such push and pull logic by hand is tedious, error-prone, and a nightmare to read, as any experienced front-end JavaScript programmer can attest.
-Angular supports *two-way data binding*, a mechanism for coordinating the parts of a template with the parts of a component. Add binding markup to the template HTML to tell Angular how to connect both sides.
+Angular supports *two-way data binding*, a mechanism for coordinating the parts of a template with the parts of a component.
+Add binding markup to the template HTML to tell Angular how to connect both sides.
-The following diagram shows the four forms of data binding markup. Each form has a direction: to the DOM, from the DOM, or both.
+The following diagram shows the four forms of data binding markup.
+Each form has a direction: to the DOM, from the DOM, or both.
-
-
-This example from the `HeroListComponent` template uses three of these forms.
+
-
+
-* The `[hero]` [*property binding*](guide/property-binding) passes the value of
-`selectedHero` from the parent `HeroListComponent` to the `hero` property of the child `HeroDetailComponent`.
+This example from the `HeroListComponent` template uses three of these forms.
-* 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.
+
-* The `{{hero.name}}` [*interpolation*](guide/interpolation)
-displays the component's `hero.name` property value within the `
` element.
+| Data bindings | Details |
+|:--- |:--- |
+| `[hero]` [property binding](guide/property-binding) | Passes the value of `selectedHero` from the parent `HeroListComponent` to the `hero` property of the child `HeroDetailComponent`. |
+| `(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. |
+| `{{hero.name}}` [interpolation](guide/interpolation) | Displays the component's `hero.name` property value within the `` element. |
-Two-way data binding (used mainly in [template-driven forms](guide/forms))
-combines property and event binding in a single notation.
+Two-way data binding \(used mainly in [template-driven forms](guide/forms)\) combines property and event binding in a single notation.
Here's an example from the `HeroDetailComponent` template that uses two-way data binding with the `ngModel` directive.
-
+
In two-way binding, a data property value flows to the input box from the component as with property binding.
-The user's changes also flow back to the component, resetting the property to the latest value,
-as with event binding.
+The user's changes also flow back to the component, resetting the property to the latest value, as with event binding.
-Angular processes *all* data bindings once for each JavaScript event cycle,
-from the root of the application component tree through all child components.
+Angular processes *all* data bindings once for each JavaScript event cycle, from the root of the application component tree through all child components.
-
+
+
+
Data binding plays an important role in communication between a template and its component, and is also important for communication between parent and child components.
-
+
+
+
### Pipes
-Angular pipes let you declare display-value transformations in your template HTML. A class with the `@Pipe` decorator defines a function that transforms input values to output values for display in a view.
+Angular pipes let you declare display-value transformations in your template HTML.
+A class with the `@Pipe` decorator defines a function that transforms input values to output values for display in a view.
+
+Angular defines various pipes, such as the [date](api/common/DatePipe) pipe and [currency](api/common/CurrencyPipe) pipe; for a complete list, see the [Pipes API list](api?type=pipe).
+You can also define new pipes.
+
+To specify a value transformation in an HTML template, use the [pipe operator (`|`)](guide/pipes).
+
+
+
+{{interpolated_value | pipe_name}}
-Angular defines various pipes, such as the [date](api/common/DatePipe) pipe and [currency](api/common/CurrencyPipe) pipe; for a complete list, see the [Pipes API list](api?type=pipe). You can also define new pipes.
+
-To specify a value transformation in an HTML template, use the [pipe operator (|)](guide/pipes).
+You can chain pipes, sending the output of one pipe function to be transformed by another pipe function.
+A pipe can also take arguments that control how it performs its transformation.
+For example, you can pass the desired format to the `date` pipe.
-`{{interpolated_value | pipe_name}}`
+
-You can chain pipes, sending the output of one pipe function to be transformed by another pipe function. A pipe can also take arguments that control how it performs its transformation. For example, you can pass the desired format to the `date` pipe.
+<!-- Default format: output 'Jun 15, 2015'-->
+<p>Today is {{today | date}}</p>
-```
-
- Today is {{today | date}}
+<!-- fullDate format: output 'Monday, June 15, 2015'-->
+<p>The date is {{today | date:'fullDate'}}</p>
-
- The date is {{today | date:'fullDate'}}
+<!-- shortTime format: output '9:43 AM'-->
+<p>The time is {{today | date:'shortTime'}}</p>
-
- The time is {{today | date:'shortTime'}}
-```
+
### Directives
-
+
+
+
+
+
-Angular templates are *dynamic*. When Angular renders them, it transforms the DOM according to the instructions given by *directives*. A directive is a class with a `@Directive()` decorator.
+Angular templates are *dynamic*.
+When Angular renders them, it transforms the DOM according to the instructions given by *directives*.
+A directive is a class with a `@Directive()` decorator.
A component is technically a directive.
-However, components are so distinctive and central to Angular applications that Angular
-defines the `@Component()` decorator, which extends the `@Directive()` decorator with
-template-oriented features.
+However, components are so distinctive and central to Angular applications that Angular defines the `@Component()` decorator, which extends the `@Directive()` decorator with template-oriented features.
-In addition to components, there are two other kinds of directives: *structural* and *attribute*.
+In addition to components, there are two other kinds of directives: *structural* and *attribute*.
Angular defines a number of directives of both kinds, and you can define your own using the `@Directive()` decorator.
-Just as for components, the metadata for a directive associates the decorated class with a `selector` element that you use to insert it into HTML. In templates, directives typically appear within an element tag as attributes, either by name or as the target of an assignment or a binding.
+Just as for components, the metadata for a directive associates the decorated class with a `selector` element that you use to insert it into HTML.
+In templates, directives typically appear within an element tag as attributes, either by name or as the target of an assignment or a binding.
#### Structural directives
*Structural directives* alter layout by adding, removing, and replacing elements in the DOM.
The example template uses two built-in structural directives to add application logic to how the view is rendered.
-
+
-* [`*ngFor`](guide/built-in-directives#ngFor) is an iterative; it tells Angular to stamp out one `` per hero in the `heroes` list.
-* [`*ngIf`](guide/built-in-directives#ngIf) is a conditional; it includes the `HeroDetail` component only if a selected hero exists.
+| Directives | Details |
+|:--- |:--- |
+| [`*ngFor`](guide/built-in-directives#ngFor) | An iterative; it tells Angular to stamp out one ` ` per hero in the `heroes` list. |
+| [`*ngIf`](guide/built-in-directives#ngIf) | A conditional; it includes the `HeroDetail` component only if a selected hero exists. |
#### Attribute directives
*Attribute directives* alter the appearance or behavior of an existing element.
In templates they look like regular HTML attributes, hence the name.
-The `ngModel` directive, which implements two-way data binding, is an example of an attribute directive. `ngModel` modifies the behavior of an existing element (typically ` `) by setting its display value property and responding to change events.
+The `ngModel` directive, which implements two-way data binding, is an example of an attribute directive.
+`ngModel` modifies the behavior of an existing element \(typically ` `\) by setting its display value property and responding to change events.
-
+
-Angular has more pre-defined directives that either alter the layout structure
-(for example, [ngSwitch](guide/built-in-directives#ngSwitch))
-or modify aspects of DOM elements and components
-(for example, [ngStyle](guide/built-in-directives#ngstyle) and [ngClass](guide/built-in-directives#ngClass)).
+Angular has more pre-defined directives that either alter the layout structure \(for example, [ngSwitch](guide/built-in-directives#ngSwitch)\) or modify aspects of DOM elements and components \(for example, [ngStyle](guide/built-in-directives#ngstyle) and [ngClass](guide/built-in-directives#ngClass)\).
Learn more in the [Attribute Directives](guide/attribute-directives) and [Structural Directives](guide/structural-directives) guides.
+
+
+
+
+
+
+
+@reviewed 2022-02-28
diff --git a/aio/content/guide/architecture-modules.md b/aio/content/guide/architecture-modules.md
index 1e2fba792de89..81d54cd2ae992 100644
--- a/aio/content/guide/architecture-modules.md
+++ b/aio/content/guide/architecture-modules.md
@@ -1,65 +1,84 @@
# Introduction to modules
Angular applications are modular and Angular has its own modularity system called *NgModules*.
-NgModules are containers for a cohesive block of code dedicated to an application domain, a workflow, or a closely related set of capabilities. They can contain components, service providers, and other code files whose scope is defined by the containing NgModule. They can import functionality that is exported from other NgModules, and export selected functionality for use by other NgModules.
+NgModules are containers for a cohesive block of code dedicated to an application domain, a workflow, or a closely related set of capabilities
+They can contain components, service providers, and other code files whose scope is defined by the containing NgModule.
+They can import functionality that is exported from other NgModules, and export selected functionality for use by other NgModules.
-Every Angular application has at least one NgModule class, [the *root module*](guide/bootstrapping), which is conventionally named `AppModule` and resides in a file named `app.module.ts`. You launch your application by *bootstrapping* the root NgModule.
+Every Angular application has at least one NgModule class, [the *root module*](guide/bootstrapping), which is conventionally named `AppModule` and resides in a file named `app.module.ts`.
+You launch your application by *bootstrapping* the root NgModule.
-While a small application might have only one NgModule, most applications have many more *feature modules*. The *root* NgModule for an application is so named because it can include child NgModules in a hierarchy of any depth.
+While a small application might have only one NgModule, most applications have many more *feature modules*.
+The *root* NgModule for an application is so named because it can include child NgModules in a hierarchy of any depth.
## NgModule metadata
-An NgModule is defined by a class decorated with `@NgModule()`. The `@NgModule()` decorator is a function that takes a single metadata object, whose properties describe the module. The most important properties are as follows.
+An NgModule is defined by a class decorated with `@NgModule()`.
+The `@NgModule()` decorator is a function that takes a single metadata object, whose properties describe the module.
+The most important properties are as follows.
-* `declarations`: The [components](guide/architecture-components), *directives*, and *pipes* that belong to this NgModule.
-
-* `exports`: The subset of declarations that should be visible and usable in the *component templates* of other NgModules.
-
-* `imports`: Other modules whose exported classes are needed by component templates declared in *this* NgModule.
-
-* `providers`: Creators of [services](guide/architecture-services) that this NgModule contributes to the global collection of services; they become accessible in all parts of the application. (You can also specify providers at the component level.)
-
-* `bootstrap`: The main application view, called the *root component*, which hosts all other application views. Only the *root NgModule* should set the `bootstrap` property.
+| Properties | Details |
+|:--- |:--- |
+| `declarations` | The [components](guide/architecture-components), *directives*, and *pipes* that belong to this NgModule. |
+| `exports` | The subset of declarations that should be visible and usable in the *component templates* of other NgModules. |
+| `imports` | Other modules whose exported classes are needed by component templates declared in *this* NgModule. |
+| `providers` | Creators of [services](guide/architecture-services) that this NgModule contributes to the global collection of services; they become accessible in all parts of the application. \(You can also specify providers at the component level.\) |
+| `bootstrap` | The main application view, called the *root component*, which hosts all other application views. Only the *root NgModule* should set the `bootstrap` property. |
Here's a simple root NgModule definition.
-
+
- `AppComponent` is included in the `exports` list here for illustration; it isn't actually necessary in this example. A root NgModule has no reason to *export* anything because other modules don't need to *import* the root NgModule.
+`AppComponent` is included in the `exports` list here for illustration; it isn't actually necessary in this example.
+A root NgModule has no reason to *export* anything because other modules don't need to *import* the root NgModule.
## NgModules and components
-NgModules provide a *compilation context* for their components. A root NgModule always has a root component that is created during bootstrap, but any NgModule can include any number of additional components, which can be loaded through the router or created through the template. The components that belong to an NgModule share a compilation context.
+NgModules provide a *compilation context* for their components.
+A root NgModule always has a root component that is created during bootstrap but any NgModule can include any number of additional components, which can be loaded through the router or created through the template.
+The components that belong to an NgModule share a compilation context.
-
+
+
+
-A component and its template together define a *view*. A component can contain a *view hierarchy*, which allows you to define arbitrarily complex areas of the screen that can be created, modified, and destroyed as a unit. A view hierarchy can mix views defined in components that belong to different NgModules. This is often the case, especially for UI libraries.
+A component and its template together define a *view*.
+A component can contain a *view hierarchy*, which allows you to define arbitrarily complex areas of the screen that can be created, modified, and destroyed as a unit.
+A view hierarchy can mix views defined in components that belong to different NgModules.
+This is often the case, especially for UI libraries.
-
+
+
+
-When you create a component, it's associated directly with a single view, called the *host view*. The host view can be the root of a view hierarchy, which can contain *embedded views*, which are in turn the host views of other components. Those components can be in the same NgModule, or can be imported from other NgModules. Views in the tree can be nested to any depth.
+When you create a component, it's associated directly with a single view, called the *host view*.
+The host view can be the root of a view hierarchy, which can contain *embedded views*, which are in turn the host views of other components.
+Those components can be in the same NgModule, or can be imported from other NgModules.
+Views in the tree can be nested to any depth.
-**Note:** The hierarchical structure of views is a key factor in the way Angular detects and responds to changes in the DOM and application data.
+**NOTE**:
+The hierarchical structure of views is a key factor in the way Angular detects and responds to changes in the DOM and application data.
## NgModules and JavaScript modules
-The NgModule system is different from and unrelated to the JavaScript (ES2015) module system for managing collections of JavaScript objects. These are *complementary* module systems that you can use together to write your applications.
+The NgModule system is different from, and unrelated to, the JavaScript \(ES2015\) module system for managing collections of JavaScript objects.
+These are *complementary* module systems that you can use together to write your applications.
In JavaScript each *file* is a module and all objects defined in the file belong to that module.
The module declares some objects to be public by marking them with the `export` key word.
@@ -70,14 +89,23 @@ Other JavaScript modules use *import statements* to access public objects from o
## Angular libraries
-
+
+
+
+
+
-Angular loads as a collection of JavaScript modules. You can think of them as library modules. Each Angular library name begins with the `@angular` prefix. Install them with the node package manager `npm` and import parts of them with JavaScript `import` statements.
+Angular loads as a collection of JavaScript modules.
+You can think of them as library modules.
+Each Angular library name begins with the `@angular` prefix.
+Install them with the node package manager `npm` and import parts of them with JavaScript `import` statements.
@@ -91,14 +119,24 @@ For example, the following code imports the `BrowserModule` NgModule from the `p
In the example of the simple root module above, the application module needs material from within
-`BrowserModule`. To access that material, add it to the `@NgModule` metadata `imports` like this.
+`BrowserModule`.
+To access that material, add it to the `@NgModule` metadata `imports` like this.
-In this way you're using the Angular and JavaScript module systems *together*. Although it's easy to confuse the two systems, which share the common vocabulary of "imports" and "exports", you will become familiar with the different contexts in which they are used.
+In this way, you're using the Angular and JavaScript module systems *together*.
+Although it's easy to confuse the two systems, which share the common vocabulary of "imports" and "exports", you will become familiar with the different contexts in which they are used.
- Learn more from the [NgModules](guide/ngmodules) guide.
+Learn more from the [NgModules](guide/ngmodules) guide.
+
+
+
+
+
+
+
+@reviewed 2022-02-28
diff --git a/aio/content/guide/architecture-next-steps.md b/aio/content/guide/architecture-next-steps.md
index b9c2806846f6e..8aeb42ff0f2bc 100644
--- a/aio/content/guide/architecture-next-steps.md
+++ b/aio/content/guide/architecture-next-steps.md
@@ -31,28 +31,30 @@ without deep knowledge of animation techniques or CSS.
Angular provides a framework for single-page applications, where most of the logic and data resides on the client.
Most applications still need to access a server using the `HttpClient` to access and save data.
-For some platforms and applications, you might also want to use the PWA (Progressive Web App) model to improve the user experience.
+For some platforms and applications, you might also want to use the PWA \(Progressive Web App\) model to improve the user experience.
* [HTTP](guide/http): Communicate with a server to get data, save data, and invoke server-side actions with an HTTP client.
-* [Server-side rendering](guide/universal): Angular Universal generates static application pages on the server through server-side rendering (SSR). This allows you to run your Angular application on the server in order to improve performance and show the first page quickly on mobile and low-powered devices, and also facilitate web crawlers.
+* [Server-side rendering](guide/universal): Angular Universal generates static application pages on the server through server-side rendering \(SSR\). This allows you to run your Angular application on the server in order to improve performance and show the first page quickly on mobile and low-powered devices, and also facilitate web crawlers.
* [Service workers and PWA](guide/service-worker-intro): Use a service worker to reduce dependency on the network and significantly improve the user experience.
* [Web workers](guide/web-worker): Learn how to run CPU-intensive computations in a background thread.
## Support for the development cycle
* [CLI Command Reference](cli): The Angular CLI is a command-line tool that you use to create projects, generate application and library code, and perform a variety of ongoing development tasks such as testing, bundling, and deployment.
-* [Compilation](guide/aot-compiler): Angular provides just-in-time (JIT) compilation for the development environment, and ahead-of-time (AOT) compilation for the production environment.
+* [Compilation](guide/aot-compiler): Angular provides just-in-time \(JIT\) compilation for the development environment, and ahead-of-time \(AOT\) compilation for the production environment.
* [Testing platform](guide/testing): Run unit tests on your application parts as they interact with the Angular framework.
* [Deployment](guide/deployment): Learn techniques for deploying your Angular application to a remote server.
* [Security guidelines](guide/security): Learn about Angular's built-in protections against common web-application vulnerabilities and attacks such as cross-site scripting attacks.
-* [Internationalization][AioGuideI18nOverview]: Make your application available in multiple languages with Angular's internationalization (i18n) tools.
+* [Internationalization][AioGuideI18nOverview]: Make your application available in multiple languages with Angular's internationalization \(i18n\) tools.
* [Accessibility](guide/accessibility): Make your application accessible to all users.
## File structure, configuration, and dependencies
* [Workspace and file structure](guide/file-structure): Understand the structure of Angular workspace and project folders.
* [Building and serving](guide/build): Learn to define different build and proxy server configurations for your project, such as development, staging, and production.
-* [npm packages](guide/npm-packages): The Angular Framework, Angular CLI, and components used by Angular applications are packaged as [npm](https://docs.npmjs.com) packages and distributed using the npm registry. The Angular CLI creates a default `package.json` file, which specifies a starter set of packages that work well together and jointly support many common application scenarios.
+* [npm packages](guide/npm-packages): The Angular Framework, Angular CLI, and components used by Angular applications are packaged as [npm](https://docs.npmjs.com) packages and distributed using the npm registry.
+ The Angular CLI creates a default `package.json` file, which specifies a starter set of packages that work well together and jointly support many common application scenarios.
+
* [TypeScript configuration](guide/typescript-configuration): TypeScript is the primary language for Angular application development.
* [Browser support](guide/browser-support): Make your applications compatible across a wide range of browsers.
@@ -66,6 +68,8 @@ For some platforms and applications, you might also want to use the PWA (Progres
[AioGuideI18nOverview]: guide/i18n-overview "Angular Internationalization | Angular"
+
+
-@reviewed 2021-09-15
+@reviewed 2022-02-28
diff --git a/aio/content/guide/architecture-services.md b/aio/content/guide/architecture-services.md
index 512bf5e54485e..851359eaee9c8 100644
--- a/aio/content/guide/architecture-services.md
+++ b/aio/content/guide/architecture-services.md
@@ -5,112 +5,126 @@ A service is typically a class with a narrow, well-defined purpose.
It should do something specific and do it well.
Angular distinguishes components from services to increase modularity and reusability.
-By separating a component's view-related functionality from other kinds of processing,
-you can make your component classes lean and efficient.
+By separating a component's view-related functionality from other kinds of processing, you can make your component classes lean and efficient.
Ideally, a component's job is to enable the user experience and nothing more.
-A component should present properties and methods for data binding,
-in order to mediate between the view (rendered by the template)
-and the application logic (which often includes some notion of a *model*).
+A component should present properties and methods for data binding, in order to mediate between the view \(rendered by the template\) and the application logic \(which often includes some notion of a *model*\).
-A component can delegate certain tasks to services, such as fetching data from the server,
-validating user input, or logging directly to the console.
-By defining such processing tasks in an *injectable service class*, you make those tasks
-available to any component.
-You can also make your application more adaptable by injecting different providers of the same kind of service,
-as appropriate in different circumstances.
+A component can delegate certain tasks to services, such as fetching data from the server, validating user input, or logging directly to the console.
+By defining such processing tasks in an *injectable service class*, you make those tasks available to any component.
+You can also make your application more adaptable by injecting different providers of the same kind of service, as appropriate in different circumstances.
-Angular doesn't *enforce* these principles. Angular does help you *follow* these principles
-by making it easy to factor your application logic into services and make those services
-available to components through *dependency injection*.
+Angular doesn't *enforce* these principles.
+Angular does help you *follow* these principles by making it easy to factor your application logic into services and make those services available to components through *dependency injection*.
## Service examples
Here's an example of a service class that logs to the browser console.
-
+
-Services can depend on other services. For example, here's a `HeroService` that depends on the `Logger` service, and also uses `BackendService` to get heroes. That service in turn might depend on the `HttpClient` service to fetch heroes asynchronously from a server.
+Services can depend on other services.
+For example, here's a `HeroService` that depends on the `Logger` service, and also uses `BackendService` to get heroes.
+That service in turn might depend on the `HttpClient` service to fetch heroes asynchronously from a server.
-
+
## Dependency injection (DI)
-
+
+
+
+
+
DI is wired into the Angular framework and used everywhere to provide new components with the services or other things they need.
Components consume services; that is, you can *inject* a service into a component, giving the component access to that service class.
To define a class as a service in Angular, use the `@Injectable()` decorator to provide the metadata that allows Angular to inject it into a component as a *dependency*.
-Similarly, use the `@Injectable()` decorator to indicate that a component or other class (such as another service, a pipe, or an NgModule) *has* a dependency.
+Similarly, use the `@Injectable()` decorator to indicate that a component or other class \(such as another service, a pipe, or an NgModule\) *has* a dependency.
-* The *injector* is the main mechanism. Angular creates an application-wide injector for you during the bootstrap process, and additional injectors as needed. You don't have to create injectors.
+* The *injector* is the main mechanism.
+ Angular creates an application-wide injector for you during the bootstrap process, and additional injectors as needed.
+ You don't have to create injectors.
-* An injector creates dependencies, and maintains a *container* of dependency instances that it reuses if possible.
+* An injector creates dependencies and maintains a *container* of dependency instances that it reuses, if possible.
+* A *provider* is an object that tells an injector how to obtain or create a dependency
-* A *provider* is an object that tells an injector how to obtain or create a dependency.
-
-For any dependency that you need in your app, you must register a provider with the application's injector,
-so that the injector can use the provider to create new instances.
+For any dependency that you need in your app, you must register a provider with the application's injector, so that the injector can use the provider to create new instances.
For a service, the provider is typically the service class itself.
-A dependency doesn't have to be a service—it could be a function, for example, or a value.
+A dependency doesn't have to be a service —it could be a function, for example, or a value.
-When Angular creates a new instance of a component class, it determines which services or other dependencies that component needs by looking at the constructor parameter types. For example, the constructor of `HeroListComponent` needs `HeroService`.
+When Angular creates a new instance of a component class, it determines which services or other dependencies that component needs by looking at the constructor parameter types.
+For example, the constructor of `HeroListComponent` needs `HeroService`.
-
+
-When Angular discovers that a component depends on a service, it first checks if the injector has any existing instances of that service. If a requested service instance doesn't yet exist, the injector makes one using the registered provider, and adds it to the injector before returning the service to Angular.
+When Angular discovers that a component depends on a service, it first checks if the injector has any existing instances of that service.
+If a requested service instance doesn't yet exist, the injector makes one using the registered provider and adds it to the injector before returning the service to Angular.
When all requested services have been resolved and returned, Angular can call the component's constructor with those services as arguments.
The process of `HeroService` injection looks something like this.
-
+
+
+
### Providing services
You must register at least one *provider* of any service you are going to use.
-The provider can be part of the service's own metadata, making that service available everywhere,
-or you can register providers with specific modules or components.
-You register providers in the metadata of the service (in the `@Injectable()` decorator),
-or in the `@NgModule()` or `@Component()` metadata
+The provider can be part of the service's own metadata, making that service available everywhere, or you can register providers with specific modules or components.
+You register providers in the metadata of the service \(in the `@Injectable()` decorator\), or in the `@NgModule()` or `@Component()` metadata
+
+* By default, the Angular CLI command [`ng generate service`](cli/generate) registers a provider with the root injector for your service by including provider metadata in the `@Injectable()` decorator.
+ The tutorial uses this method to register the provider of HeroService class definition.
-* By default, the Angular CLI command [`ng generate service`](cli/generate) registers a provider with the root injector for your service by including provider metadata in the `@Injectable()` decorator. The tutorial uses this method to register the provider of HeroService class definition.
+
- ```
- @Injectable({
+ @Injectable({
providedIn: 'root',
})
- ```
+
+
When you provide the service at the root level, Angular creates a single, shared instance of `HeroService`
and injects it into any class that asks for it.
Registering the provider in the `@Injectable()` metadata also allows Angular to optimize an app
by removing the service from the compiled application if it isn't used, a process known as *tree-shaking*.
-* When you register a provider with a [specific NgModule](guide/architecture-modules), the same instance of a service is available to all components in that NgModule. To register at this level, use the `providers` property of the `@NgModule()` decorator.
+* When you register a provider with a [specific NgModule](guide/architecture-modules), the same instance of a service is available to all components in that NgModule.
+ To register at this level, use the `providers` property of the `@NgModule()` decorator.
- ```
- @NgModule({
- providers: [
- BackendService,
- Logger
- ],
- ...
- })
- ```
+
+
+ @NgModule({
+ providers: [
+ BackendService,
+ Logger
+ ],
+ …
+ })
+
+
-* When you register a provider at the component level, you get a new instance of the
-service with each new instance of that component.
-At the component level, register a service provider in the `providers` property of the `@Component()` metadata.
+* When you register a provider at the component level, you get a new instance of the service with each new instance of that component.
+ At the component level, register a service provider in the `providers` property of the `@Component()` metadata.
-
+
For more detailed information, see the [Dependency Injection](guide/dependency-injection) section.
+
+
+
+
+
+
+
+@reviewed 2022-02-28
diff --git a/aio/content/guide/architecture.md b/aio/content/guide/architecture.md
index a64a055a07091..24107a2e51bcd 100644
--- a/aio/content/guide/architecture.md
+++ b/aio/content/guide/architecture.md
@@ -5,58 +5,72 @@ Angular is written in TypeScript.
It implements core and optional functionality as a set of TypeScript libraries that you import into your applications.
The architecture of an Angular application relies on certain fundamental concepts.
-The basic building blocks of the Angular framework are Angular components that are organized into *NgModules*. NgModules collect related code into functional sets; an Angular application is defined by a set of NgModules. An application always has at least a *root module* that enables bootstrapping, and typically has many more *feature modules*.
+The basic building blocks of the Angular framework are Angular components that are organized into *NgModules*.
+NgModules collect related code into functional sets; an Angular application is defined by a set of NgModules.
+An application always has at least a *root module* that enables bootstrapping, and typically has many more *feature modules*.
-* Components define *views*, which are sets of screen elements that Angular can choose among and modify according to your program logic and data.
+* Components define *views*, which are sets of screen elements that Angular can choose among and modify according to your program logic and data
+* Components use *services*, which provide specific functionality not directly related to views.
+ Service providers can be *injected* into components as *dependencies*, making your code modular, reusable, and efficient.
-* Components use *services*, which provide specific functionality not directly related to views. Service providers can be *injected* into components as *dependencies*, making your code modular, reusable, and efficient.
+Modules, components and services are classes that use *decorators*.
+These decorators mark their type and provide metadata that tells Angular how to use them.
-Modules, components and services are classes that use *decorators*. These decorators mark their type and provide metadata that tells Angular how to use them.
+* The metadata for a component class associates it with a *template* that defines a view.
+ A template combines ordinary HTML with Angular *directives* and *binding markup* that allow Angular to modify the HTML before rendering it for display.
-* The metadata for a component class associates it with a *template* that defines a view. A template combines ordinary HTML with Angular *directives* and *binding markup* that allow Angular to modify the HTML before rendering it for display.
+* The metadata for a service class provides the information Angular needs to make it available to components through *dependency injection \(DI\)*
-* The metadata for a service class provides the information Angular needs to make it available to components through *dependency injection (DI)*.
-
-An application's components typically define many views, arranged hierarchically. Angular provides the `Router` service to help you define navigation paths among views. The router provides sophisticated in-browser navigational capabilities.
+An application's components typically define many views, arranged hierarchically.
+Angular provides the `Router` service to help you define navigation paths among views.
+The router provides sophisticated in-browser navigational capabilities.
- See the [Angular Glossary](guide/glossary) for basic definitions of important Angular terms and usage.
+See the [Angular Glossary](guide/glossary) for basic definitions of important Angular terms and usage.
- For the sample application that this page describes, see the .
+For the sample application that this page describes, see the .
+
## Modules
-Angular *NgModules* differ from and complement JavaScript (ES2015) modules. An NgModule declares a compilation context for a set of components that is dedicated to an application domain, a workflow, or a closely related set of capabilities. An NgModule can associate its components with related code, such as services, to form functional units.
+Angular *NgModules* differ from and complement JavaScript \(ES2015\) modules.
+An NgModule declares a compilation context for a set of components that is dedicated to an application domain, a workflow, or a closely related set of capabilities.
+An NgModule can associate its components with related code, such as services, to form functional units.
-Every Angular application has a *root module*, conventionally named `AppModule`, which provides the bootstrap mechanism that launches the application. An application typically contains many functional modules.
+Every Angular application has a *root module*, conventionally named `AppModule`, which provides the bootstrap mechanism that launches the application.
+An application typically contains many functional modules.
-Like JavaScript modules, NgModules can import functionality from other NgModules, and allow their own functionality to be exported and used by other NgModules. For example, to use the router service in your app, you import the `Router` NgModule.
+Like JavaScript modules, NgModules can import functionality from other NgModules, and allow their own functionality to be exported and used by other NgModules.
+For example, to use the router service in your app, you import the `Router` NgModule.
-Organizing your code into distinct functional modules helps in managing development of complex applications, and in designing for reusability. In addition, this technique lets you take advantage of *lazy-loading*—that is, loading modules on demand—to minimize the amount of code that needs to be loaded at startup.
+Organizing your code into distinct functional modules helps in managing development of complex applications, and in designing for reusability.
+In addition, this technique lets you take advantage of *lazy-loading* —that is, loading modules on demand— to minimize the amount of code that needs to be loaded at startup.
- For a more detailed discussion, see [Introduction to modules](guide/architecture-modules).
+For a more detailed discussion, see [Introduction to modules](guide/architecture-modules).
## Components
-Every Angular application has at least one component, the *root component* that connects a component hierarchy with the page document object model (DOM). Each component defines a class that contains application data and logic, and is associated with an HTML *template* that defines a view to be displayed in a target environment.
+Every Angular application has at least one component, the *root component* that connects a component hierarchy with the page document object model \(DOM\).
+Each component defines a class that contains application data and logic, and is associated with an HTML *template* that defines a view to be displayed in a target environment.
The `@Component()` decorator identifies the class immediately below it as a component, and provides the template and related component-specific metadata.
- Decorators are functions that modify JavaScript classes. Angular defines a number of decorators that attach specific kinds of metadata to classes, so that the system knows what those classes mean and how they should work.
+Decorators are functions that modify JavaScript classes.
+Angular defines a number of decorators that attach specific kinds of metadata to classes, so that the system knows what those classes mean and how they should work.
-
Learn more about decorators on the web.
+
Learn more about decorators on the web.
@@ -66,10 +80,13 @@ A template combines HTML with Angular markup that can modify HTML elements befor
Template *directives* provide program logic, and *binding markup* connects your application data and the DOM.
There are two types of data binding:
-* *Event binding* lets your application respond to user input in the target environment by updating your application data.
-* *Property binding* lets you interpolate values that are computed from your application data into the HTML.
+| Data bindings | Details |
+|:--- |:--- |
+| Event binding | Lets your application respond to user input in the target environment by updating your application data. |
+| Property binding | Lets you interpolate values that are computed from your application data into the HTML. |
-Before a view is displayed, Angular evaluates the directives and resolves the binding syntax in the template to modify the HTML elements and the DOM, according to your program data and logic. Angular supports *two-way data binding*, meaning that changes in the DOM, such as user choices, are also reflected in your program data.
+Before a view is displayed, Angular evaluates the directives and resolves the binding syntax in the template to modify the HTML elements and the DOM, according to your program data and logic.
+Angular supports *two-way data binding*, meaning that changes in the DOM, such as user choices, are also reflected in your program data.
Your templates can use *pipes* to improve the user experience by transforming values for display.
For example, use pipes to display dates and currency values that are appropriate for a user's locale.
@@ -77,80 +94,91 @@ Angular provides predefined pipes for common transformations, and you can also d
- For a more detailed discussion of these concepts, see [Introduction to components](guide/architecture-components).
+For a more detailed discussion of these concepts, see [Introduction to components](guide/architecture-components).
-{@a dependency-injection}
-
+
## Services and dependency injection
-For data or logic that isn't associated with a specific view, and that you want to share across components, you create a *service* class. A service class definition is immediately preceded by the `@Injectable()` decorator. The decorator provides the metadata that allows other providers to be **injected** as dependencies into your class.
+For data or logic that isn't associated with a specific view, and that you want to share across components, you create a *service* class.
+A service class definition is immediately preceded by the `@Injectable()` decorator.
+The decorator provides the metadata that allows other providers to be **injected** as dependencies into your class.
- *Dependency injection* (DI) lets you keep your component classes lean and efficient. They don't fetch data from the server, validate user input, or log directly to the console; they delegate such tasks to services.
+*Dependency injection* \(DI\) lets you keep your component classes lean and efficient.
+They don't fetch data from the server, validate user input, or log directly to the console; they delegate such tasks to services.
- For a more detailed discussion, see [Introduction to services and DI](guide/architecture-services).
+For a more detailed discussion, see [Introduction to services and DI](guide/architecture-services).
### Routing
-The Angular `Router` NgModule provides a service that lets you define a navigation path among the different application states and view hierarchies in your application. It is modeled on the familiar browser navigation conventions:
+The Angular `Router` NgModule provides a service that lets you define a navigation path among the different application states and view hierarchies in your application.
+It is modeled on the familiar browser navigation conventions:
-* Enter a URL in the address bar and the browser navigates to a corresponding page.
+* Enter a URL in the address bar and the browser navigates to a corresponding page
+* Click links on the page and the browser navigates to a new page
+* Click the browser's back and forward buttons and the browser navigates backward and forward through the history of pages you've seen
-* Click links on the page and the browser navigates to a new page.
-
-* Click the browser's back and forward buttons and the browser navigates backward and forward through the history of pages you've seen.
-
-The router maps URL-like paths to views instead of pages. When a user performs an action, such as clicking a link, that would load a new page in the browser, the router intercepts the browser's behavior, and shows or hides view hierarchies.
+The router maps URL-like paths to views instead of pages.
+When a user performs an action, such as clicking a link, that would load a new page in the browser, the router intercepts the browser's behavior, and shows or hides view hierarchies.
If the router determines that the current application state requires particular functionality, and the module that defines it hasn't been loaded, the router can *lazy-load* the module on demand.
-The router interprets a link URL according to your application's view navigation rules and data state. You can navigate to new views when the user clicks a button or selects from a drop box, or in response to some other stimulus from any source. The router logs activity in the browser's history, so the back and forward buttons work as well.
+The router interprets a link URL according to your application's view navigation rules and data state.
+You can navigate to new views when the user clicks a button or selects from a drop box, or in response to some other stimulus from any source.
+The router logs activity in the browser's history, so the back and forward buttons work as well.
-To define navigation rules, you associate *navigation paths* with your components. A path uses a URL-like syntax that integrates your program data, in much the same way that template syntax integrates your views with your program data. You can then apply program logic to choose which views to show or to hide, in response to user input and your own access rules.
+To define navigation rules, you associate *navigation paths* with your components.
+A path uses a URL-like syntax that integrates your program data, in much the same way that template syntax integrates your views with your program data.
+You can then apply program logic to choose which views to show or to hide, in response to user input and your own access rules.
- For a more detailed discussion, see [Routing and navigation](guide/router).
+For a more detailed discussion, see [Routing and navigation](guide/router).
-
## What's next
-You've learned the basics about the main building blocks of an Angular application. The following diagram shows how these basic pieces are related.
+You've learned the basics about the main building blocks of an Angular application.
+The following diagram shows how these basic pieces are related.
-
-
-* Together, a component and template define an Angular view.
- * A decorator on a component class adds the metadata, including a pointer to the associated template.
- * Directives and binding markup in a component's template modify views based on program data and logic.
-* The dependency injector provides services to a component, such as the router service that lets you define navigation among views.
+
-Each of these subjects is introduced in more detail in the following pages.
+
-* [Introduction to Modules](guide/architecture-modules)
+* Together, a component and template define an Angular view
+ * A decorator on a component class adds the metadata, including a pointer to the associated template
+ * Directives and binding markup in a component's template modify views based on program data and logic
+* The dependency injector provides services to a component, such as the router service that lets you define navigation among views
-* [Introduction to Components](guide/architecture-components)
+Each of these subjects is introduced in more detail in the following pages.
- * [Templates and views](guide/architecture-components#templates-and-views)
+* [Introduction to Modules](guide/architecture-modules)
+* [Introduction to Components](guide/architecture-components)
+ * [Templates and views](guide/architecture-components#templates-and-views)
+ * [Component metadata](guide/architecture-components#component-metadata)
+ * [Data binding](guide/architecture-components#data-binding)
+ * [Directives](guide/architecture-components#directives)
+ * [Pipes](guide/architecture-components#pipes)
+* [Introduction to services and dependency injection](guide/architecture-services)
- * [Component metadata](guide/architecture-components#component-metadata)
+When you're familiar with these fundamental building blocks, you can explore them in more detail in the documentation.
+To learn about more tools and techniques that are available to help you build and deploy Angular applications, see [Next steps: tools and techniques](guide/architecture-next-steps).
- * [Data binding](guide/architecture-components#data-binding)
+
- * [Directives](guide/architecture-components#directives)
+
- * [Pipes](guide/architecture-components#pipes)
+
-* [Introduction to services and dependency injection](guide/architecture-services)
+
-When you're familiar with these fundamental building blocks, you can explore them in more detail in the documentation. To learn about more tools and techniques that are available to help you build and deploy Angular applications, see [Next steps: tools and techniques](guide/architecture-next-steps).
-
+@reviewed 2022-02-28
diff --git a/aio/content/guide/attribute-binding.md b/aio/content/guide/attribute-binding.md
index 1fe1ddb2c0ce0..1f7bdb8ad5b59 100644
--- a/aio/content/guide/attribute-binding.md
+++ b/aio/content/guide/attribute-binding.md
@@ -15,20 +15,18 @@ It is recommended that you set an element property with a [property binding](gui
However, sometimes you don't have an element property to bind.
In those situations, use attribute binding.
-For example, [ARIA](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA) and
-[SVG](https://developer.mozilla.org/en-US/docs/Web/SVG) are purely attributes.
+For example, [ARIA](https://developer.mozilla.org/docs/Web/Accessibility/ARIA) and [SVG](https://developer.mozilla.org/docs/Web/SVG) are purely attributes.
Neither ARIA nor SVG correspond to element properties and don't set element properties.
In these cases, you must use attribute binding because there are no corresponding property targets.
-
## Syntax
-Attribute binding syntax resembles [property binding](guide/property-binding), but instead of an element property between brackets, you precede the name of the attribute with the prefix `attr`, followed by a dot.
+Attribute binding syntax resembles [property binding](guide/property-binding), but instead of an element property between brackets, you precede the name of the attribute with the prefix `attr`, followed by a period \(full-stop\) character.
Then, you set the attribute value with an expression that resolves to a string.
-
+
- <p [attr.attribute-you-are-targeting]="expression"></p>
+<p [attr.attribute-you-are-targeting]="expression"></p>
@@ -40,12 +38,11 @@ When the expression resolves to `null` or `undefined`, Angular removes the attri
## Binding ARIA attributes
-One of the primary use cases for attribute binding
-is to set ARIA attributes, as in this example:
+One of the primary use cases for attribute binding is to set ARIA attributes, as in this example:
-
+
-{@a colspan}
+
## Binding to `colspan`
@@ -55,12 +52,19 @@ Depending on the amount of data that your application populates a table with, th
To use attribute binding with the `` attribute `colspan`:
-1. Specify the `colspan` attribute by using the following syntax: `[attr.colspan]`.
-1. Set `[attr.colspan]` equal to an expression.
+1. Specify the `colspan` attribute by using the following syntax:
+
+
+
+ [attr.colspan]
+
+
+
+1. Set `[attr.colspan]` equal to an expression.
In the following example, you bind the `colspan` attribute to the expression `1 + 1`.
-
+
This binding causes the ` ` to span two columns.
@@ -74,32 +78,48 @@ For more information on how to bind to the `colSpan` property, see the [`colspan
+
-{@a class-binding}
## Binding to the `class` attribute
Use class binding to add and remove CSS class names from an element's `class` attribute.
### Binding to a single CSS `class`
-To create a single class binding, use the prefix `class` followed by a dot and the name of the CSS class—for example, `[class.sale]="onSale"`.
-Angular adds the class when the bound expression, `onSale` is truthy, and it removes the class when the expression is falsy—with the exception of `undefined`.
+To create a single class binding, use the prefix `class` followed by a dot and the name of the CSS class.
+For example,
+
+
+
+[class.sale]="onSale"
+
+
+
+Angular adds the class when the bound expression, `onSale` is truthy, and it removes the class when the expression is falsy —with the exception of `undefined`.
See [styling delegation](guide/style-precedence#styling-delegation) for more information.
### Binding to multiple CSS classes
-To bind to multiple classes, use `[class]` set to an expression—for example, `[class]="classExpression"`.
+To bind to multiple classes, use `[class]` set to an expression.
+For example,
+
+
+
+[class]="classExpression"
+
+
+
The expression can be one of:
-* A space-delimited string of class names.
-* An object with class names as the keys and truthy or falsy expressions as the values.
-* An array of class names.
+* A space-delimited string of class names
+* An object with class names as the keys and truthy or falsy expressions as the values
+* An array of class names
With the object format, Angular adds a class only if its associated value is truthy.
-With any object-like expression—such as `object`, `Array`, `Map`, or `Set`—the identity of the object must change for Angular to update the class list.
+With any object-like expression —such as `object`, `Array`, `Map`, or `Set`— the identity of the object must change for Angular to update the class list.
Updating the property without changing object identity has no effect.
@@ -108,89 +128,82 @@ If there are multiple bindings to the same class name, Angular uses [styling pre
The following table summarizes class binding syntax.
-
-
-
-
-
-
-
-
-
-
-
-
-
- Binding Type
-
-
- Syntax
-
-
- Input Type
-
-
- Example Input Values
-
-
-
- Single class binding
- [class.sale]="onSale"
- boolean | undefined | null
- true
, false
-
-
- Multi-class binding
- [class]="classExpression"
- string
- "my-class-1 my-class-2 my-class-3"
-
-
- Record<string, boolean | undefined | null>
- {foo: true, bar: false}
-
-
- Array
<string
>
- ['foo', 'bar']
-
-
-
-
-{@a style-binding}
+| Binding Type | Syntax | Input Type | Example Input Values |
+|:--- |:--- |:--- |:--- |
+| Single class binding | `[class.sale]="onSale"` | boolean | undefined | null
| `true`, `false` |
+| Multi-class binding | `[class]="classExpression"` | `string` | `"my-class-1 my-class-2 my-class-3"` |
+| Multi-class binding | `[class]="classExpression"` | Record<string, boolean | undefined | null>
| `{foo: true, bar: false}` |
+| Multi-class binding | `[class]="classExpression"` | Array<string>
| `['foo', 'bar']` |
+
+
+
## Binding to the style attribute
Use style binding to set styles dynamically.
### Binding to a single style
-To create a single style binding, use the prefix `style` followed by a dot and the name of the CSS style property—for example, `[style.width]="width"`.
+To create a single style binding, use the prefix `style` followed by a dot and the name of the CSS style property.
+For example,
+
+
+
+[style.width]="width"
+
+
+
Angular sets the property to the value of the bound expression, which is usually a string.
Optionally, you can add a unit extension like `em` or `%`, which requires a number type.
-You can write a style property name in either [dash-case](guide/glossary#dash-case), or
-[camelCase](guide/glossary#camelcase).
+You can write a style property name in either [dash-case](guide/glossary#dash-case), or [camelCase](guide/glossary#camelcase).
+
+
-
- <nav [style.background-color]="expression"></nav>
+<nav [style.background-color]="expression"></nav>
+
+<nav [style.backgroundColor]="expression"></nav>
- <nav [style.backgroundColor]="expression"></nav>
### Binding to multiple styles
-To toggle multiple styles, bind to the `[style]` attribute—for example, `[style]="styleExpression"`.
+To toggle multiple styles, bind to the `[style]` attribute.
+For example,
+
+
+
+[style]="styleExpression"
+
+
+
The `styleExpression` can be one of:
-* A string list of styles such as `"width: 100px; height: 100px; background-color: cornflowerblue;"`.
-* An object with style names as the keys and style values as the values, such as `{width: '100px', height: '100px', backgroundColor: 'cornflowerblue'}`.
+* A string list of styles, such as
+
+
+
+ "width: 100px; height: 100px; background-color: cornflowerblue;"
+
+
+
+* An object with style names as the keys and style values as the values, such as
+
+
+
+ {width: '100px', height: '100px', backgroundColor: 'cornflowerblue'}
-Note that binding an array to `[style]` is not supported.
+
+
+
+
+**NOTE**:
+Binding an array to `[style]` is not supported.
+
+
@@ -201,64 +214,18 @@ Updating the property without changing object identity has no effect.
#### Single and multiple-style binding example
-
-
+
If there are multiple bindings to the same style attribute, Angular uses [styling precedence](guide/style-precedence) to determine which binding to use.
The following table summarizes style binding syntax.
-
-
-
-
-
-
-
-
-
-
-
-
-
- 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 | null
- 100
-
-
- Multi-style binding
- [style]="styleExpression"
- string
- "width: 100px; height: 100px"
-
-
- Record<string, string | undefined | null>
- {width: '100px', height: '100px'}
-
-
+| 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 | null
| `100` |
+| Multi-style binding | `[style]="styleExpression"` | `string` | `"width: 100px; height: 100px"` |
+| Multi-style binding | `[style]="styleExpression"` |
Record<string, string | undefined | null>
| `{width: '100px', height: '100px'}` |
@@ -267,36 +234,91 @@ However, using the preceding style binding syntax without `NgStyle` is preferred
-{@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).
+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'}`)
+
+Styling precedence (highest to lowest)
+
+1. Template bindings
+ 1. Property binding
+
+
+ <div [class.foo]="hasFoo">
+ <div [style.color]="color">
+
+
+ 1. Map binding
+
+
+ <div [class]="classExpr">
+ <div [style]="styleExpr">
+
+
+ 1. Static value
+
+
+ <div class="foo">
+ <div style="color: blue">
+
+
+1. Directive host bindings
+ 1. Property binding
+
+
+ host: {'[class.foo]': 'hasFoo'}
+ host: {'[style.color]': 'color'}
+
+
+ 1. Map binding
+
+
+ host: {'[class]': 'classExpr'}
+ host: {'[style]': 'styleExpr'}
+
+
+ 1. Static value
+
+
+ host: host: {'class': 'foo'}
+ host: {'style': 'color: blue'}
+
+
+1. Component host bindings
+ 1. Property binding
+
+
+ host: {'[class.foo]': 'hasFoo'}
+ host: {'[style.color]': 'color'}
+
+
+ 1. Map binding
+
+
+ host: {'[class]': 'classExpr'}
+ host: {'[style]': 'styleExpr'}
+
+
+ 1. Static value
+
+
+ host: {'class': 'foo'}
+ 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]`) takes precedence over a generic `[class]` binding, and a binding to a specific style (for example, `[style.bar]`) takes precedence over a generic `[style]` binding.
+A binding to a specific class \(for example, `[class.foo]`\) takes precedence over a generic `[class]` binding, and a binding to a specific style \(for example, `[style.bar]`\) takes 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.
@@ -307,15 +329,16 @@ Directive host bindings are considered less specific because directives can be u
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 takes 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.
@@ -323,36 +346,29 @@ Whereas setting a style property to `null` ensures the style is removed, setting
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 falls 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.
-
## Injecting attribute values
-There are cases where you need to differentiate the behavior of a [Component](api/core/Component) or [Directive](api/core/Directive) based on a static value set on the host element as an HTML attribute. For example, you might have a directive that needs to know the `type` of a `
` or ` ` element.
+There are cases where you need to differentiate the behavior of a [Component](api/core/Component) or [Directive](api/core/Directive) based on a static value set on the host element as an HTML attribute.
+For example, you might have a directive that needs to know the `type` of a `` or ` ` element.
The [Attribute](api/core/Attribute) parameter decorator is great for passing the value of an HTML attribute to a component/directive constructor using [dependency injection](guide/dependency-injection).
- The injected value captures the value of the specified HTML attribute at that moment.
- Future updates to the attribute value are not reflected in the injected value.
+The injected value captures the value of the specified HTML attribute at that moment.
+Future updates to the attribute value are not reflected in the injected value.
-
-
+
-
-
+
In the preceding example, the result of `app.component.html` is **The type of the input is: number**.
@@ -360,8 +376,17 @@ Another example is the [RouterOutlet](api/router/RouterOutlet) directive, which
-
+@Attribute()
vs @Input()
- Remember, use [@Input()](api/core/Input) when you want to keep track of the attribute value and update the associated property. Use [@Attribute()](api/core/Attribute) when you want to inject the value of an HTML attribute to a component or directive constructor.
+Remember, use [@Input()](api/core/Input) when you want to keep track of the attribute value and update the associated property.
+Use [@Attribute()](api/core/Attribute) when you want to inject the value of an HTML attribute to a component or directive constructor.
+
+
+
+
+
+
+
+@reviewed 2022-02-28
diff --git a/aio/content/guide/attribute-directives.md b/aio/content/guide/attribute-directives.md
index e3b94ad2e8a04..00d9f9e6a329d 100644
--- a/aio/content/guide/attribute-directives.md
+++ b/aio/content/guide/attribute-directives.md
@@ -12,153 +12,167 @@ See the for a working example containing the code
This section walks you through creating a highlight directive that sets the background color of the host element to yellow.
-1. To create a directive, use the CLI command [`ng generate directive`](cli/generate).
+1. To create a directive, use the CLI command [`ng generate directive`](cli/generate).
-
-ng generate directive highlight
-
+
- The CLI creates `src/app/highlight.directive.ts`, a corresponding test file `src/app/highlight.directive.spec.ts`, and declares the directive class in the `AppModule`.
+ ng generate directive highlight
- The CLI generates the default `src/app/highlight.directive.ts` as follows:
+
-
+ The CLI creates `src/app/highlight.directive.ts`, a corresponding test file `src/app/highlight.directive.spec.ts`, and declares the directive class in the `AppModule`.
- The `@Directive()` decorator's configuration property specifies the directive's CSS attribute selector, `[appHighlight]`.
+ The CLI generates the default `src/app/highlight.directive.ts` as follows:
-1. Import `ElementRef` from `@angular/core`.
- `ElementRef` grants direct access to the host DOM element through its `nativeElement` property.
+
-1. Add `ElementRef` in the directive's `constructor()` to [inject](guide/dependency-injection) a reference to the host DOM element, the element to which you apply `appHighlight`.
+ The `@Directive()` decorator's configuration property specifies the directive's CSS attribute selector, `[appHighlight]`.
-1. Add logic to the `HighlightDirective` class that sets the background to yellow.
+1. Import `ElementRef` from `@angular/core`.
+ `ElementRef` grants direct access to the host DOM element through its `nativeElement` property.
-
+1. Add `ElementRef` in the directive's `constructor()` to [inject](guide/dependency-injection) a reference to the host DOM element, the element to which you apply `appHighlight`.
+
+1. Add logic to the `HighlightDirective` class that sets the background to yellow.
+
+
- Directives _do not_ support namespaces.
+Directives *do not* support namespaces.
-
+
-{@a apply-directive}
+
+
## Applying an attribute directive
-1. To use the `HighlightDirective`, add a `` element to the HTML template with the directive as an attribute.
+1. To use the `HighlightDirective`, add a `
` element to the HTML template with the directive as an attribute.
-
+
Angular creates an instance of the `HighlightDirective` class and injects a reference to the `
` element into the directive's constructor, which sets the `
` element's background style to yellow.
-{@a respond-to-user}
+
## Handling user events
This section shows you how to detect when a user mouses into or out of the element and to respond by setting or clearing the highlight color.
-1. Import `HostListener` from '@angular/core'.
+1. Import `HostListener` from '@angular/core'.
-
+
-1. Add two event handlers that respond when the mouse enters or leaves, each with the `@HostListener()` decorator.
+1. Add two event handlers that respond when the mouse enters or leaves, each with the `@HostListener()` decorator.
-
+
Subscribe to events of the DOM element that hosts an attribute directive, the `
` in this case, with the `@HostListener()` decorator.
- The handlers delegate to a helper method, `highlight()`, that sets the color on the host DOM element, `el`.
+
+
+The handlers delegate to a helper method, `highlight()`, that sets the color on the host DOM element, `el`.
+
+
The complete directive is as follows:
-
+
The background color appears when the pointer hovers over the paragraph element and disappears as the pointer moves out.
-
+
+
+
-{@a bindings}
+
+
## Passing values into an attribute directive
This section walks you through setting the highlight color while applying the `HighlightDirective`.
-1. In `highlight.directive.ts`, import `Input` from `@angular/core`.
+1. In `highlight.directive.ts`, import `Input` from `@angular/core`.
-
+
-1. Add an `appHighlight` `@Input()` property.
+1. Add an `appHighlight` `@Input()` property.
-
+
- The `@Input()` decorator adds metadata to the class that makes the directive's `appHighlight` property available for binding.
+ The `@Input()` decorator adds metadata to the class that makes the directive's `appHighlight` property available for binding.
-1. In `app.component.ts`, add a `color` property to the `AppComponent`.
+1. In `app.component.ts`, add a `color` property to the `AppComponent`.
-
+
-1. To simultaneously apply the directive and the color, use property binding with the `appHighlight` directive selector, setting it equal to `color`.
+1. To simultaneously apply the directive and the color, use property binding with the `appHighlight` directive selector, setting it equal to `color`.
-
+
- The `[appHighlight]` attribute binding performs two tasks:
+ The `[appHighlight]` attribute binding performs two tasks:
- * applies the highlighting directive to the `` element
- * sets the directive's highlight color with a property binding
+ * Applies the highlighting directive to the `
` element
+ * Sets the directive's highlight color with a property binding
### Setting the value with user input
This section guides you through adding radio buttons to bind your color choice to the `appHighlight` directive.
-1. Add markup to `app.component.html` for choosing a color as follows:
+1. Add markup to `app.component.html` for choosing a color as follows:
-
+
-1. Revise the `AppComponent.color` so that it has no initial value.
+1. Revise the `AppComponent.color` so that it has no initial value.
-
+
-1. In `highlight.directive.ts`, revise `onMouseEnter` method so that it first tries to highlight with `appHighlight` and falls back to `red` if `appHighlight` is `undefined`.
+1. In `highlight.directive.ts`, revise `onMouseEnter` method so that it first tries to highlight with `appHighlight` and falls back to `red` if `appHighlight` is `undefined`.
-
+
-1. Serve your application to verify that the user can choose the color with the radio buttons.
+1. Serve your application to verify that the user can choose the color with the radio buttons.
-
-
-
+
-{@a second-property}
+
+
+
+
+
## Binding to a second property
This section guides you through configuring your application so the developer can set the default color.
-1. Add a second `Input()` property to `HighlightDirective` called `defaultColor`.
+1. Add a second `Input()` property to `HighlightDirective` called `defaultColor`.
-
+
-1. Revise the directive's `onMouseEnter` so that it first tries to highlight with the `appHighlight`, then with the `defaultColor`, and falls back to `red` if both properties are `undefined`.
+1. Revise the directive's `onMouseEnter` so that it first tries to highlight with the `appHighlight`, then with the `defaultColor`, and falls back to `red` if both properties are `undefined`.
-
+
-1. To bind to the `AppComponent.color` and fall back to "violet" as the default color, add the following HTML.
- In this case, the `defaultColor` binding doesn't use square brackets, `[]`, because it is static.
+1. To bind to the `AppComponent.color` and fall back to "violet" as the default color, add the following HTML.
+ In this case, the `defaultColor` binding doesn't use square brackets, `[]`, because it is static.
-
+
- As with components, you can add multiple directive property bindings to a host element.
+ As with components, you can add multiple directive property bindings to a host element.
The default color is red if there is no default color binding.
When the user chooses a color the selected color becomes the active highlight color.
-
-
-
+
+
+
+
+
-{@a ngNonBindable}
+
## Deactivating Angular processing with `NgNonBindable`
@@ -167,12 +181,20 @@ To prevent expression evaluation in the browser, add `ngNonBindable` to the host
In the following example, the expression `{{ 1 + 1 }}` renders just as it does in your code editor, and does not display `2`.
-
+
Applying `ngNonBindable` to an element stops binding for that element's child elements.
However, `ngNonBindable` still lets directives work on the element where you apply `ngNonBindable`.
In the following example, the `appHighlight` directive is still active but Angular does not evaluate the expression `{{ 1 + 1 }}`.
-
+
If you apply `ngNonBindable` to a parent element, Angular disables interpolation and binding of any sort, such as property binding or event binding, for the element's children.
+
+
+
+
+
+
+
+@reviewed 2022-02-28
diff --git a/aio/content/guide/binding-syntax.md b/aio/content/guide/binding-syntax.md
index e7bb2e627db4c..149358e57d9e4 100644
--- a/aio/content/guide/binding-syntax.md
+++ b/aio/content/guide/binding-syntax.md
@@ -10,26 +10,27 @@ See the for a working example containing the code
-
## Data binding and HTML
Developers can customize HTML by specifying attributes with string values.
In the following example, `class`, `src`, and `disabled` modify the `
`, `
`, and `
` elements respectively.
-```html
-Plain old HTML
-
-Save
-```
+
+
+<div class="special">Plain old HTML</div>
+<img src="images/item.png">
+<button disabled>Save</button>
+
+
Use data binding to 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.
Data binding works with properties of DOM elements, components, and directives, not HTML attributes.
-{@a html-attribute-vs-dom-property}
+
### HTML attributes and DOM properties
@@ -38,11 +39,29 @@ Angular binding distinguishes between HTML attributes and DOM properties.
Attributes initialize DOM properties and you can configure them to modify an element's behavior.
Properties are features of DOM nodes.
-* A few HTML attributes have 1:1 mapping to properties; for example, `id`.
+* 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,
+
+
-* Some HTML attributes don't have corresponding properties; for example, `aria-*`.
+ textContent
-* Some DOM properties don't have corresponding attributes; for example, `textContent`.
+
@@ -56,15 +75,16 @@ When you write a data binding, you're dealing exclusively with the DOM propertie
#### Example 1: an `
`
-When the browser renders `
`, it creates a
-corresponding DOM node with a `value` property and initializes that `value` to "Sarah".
+When the browser renders `
`, it creates a corresponding DOM node with a `value` property and initializes that `value` to "Sarah".
-```html
-
-```
+
+
+<input type="text" value="Sarah">
+
+
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".
+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.
@@ -76,9 +96,11 @@ A button's `disabled` property is `false` by default so the button is enabled.
When you add the `disabled` attribute, you are initializing the button's `disabled` property to `true` which disables the button.
-```html
-
Test Button
-```
+
+
+<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 `
Still Disabled `.
@@ -90,10 +112,12 @@ To control the state of the button, set the `disabled` property instead.
Though you could technically set the `[attr.disabled]` attribute binding, the values are different in that the property binding must be 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">
+
+
The first line, which uses the `disabled` property, uses a boolean value.
The second line, which uses the disabled attribute checks for `null`.
@@ -103,100 +127,30 @@ Generally, use property binding over attribute binding as a boolean value is eas
To see the `disabled` button example in a functioning application, see the
.
This example shows you how to toggle the disabled property from the component.
-
## Types of data binding
Angular provides three categories of data binding according to the direction of data flow:
-* From the source to view
-* From view to source
-* In a two way sequence of view to source to view
-
-
-
-
-
-
-
-
-
-
-
-
- Type
-
-
- Syntax
-
-
- Category
-
-
-
-
-
- Interpolation
- Property
- Attribute
- Class
- Style
-
-
-
-
- {{expression}}
- [target]="expression"
-
-
-
-
-
- One-way from data source to view target
-
-
-
- Event
-
-
-
- (target)="statement"
-
-
-
-
- One-way from view target to data source
-
-
-
-
- Two-way
-
-
-
- [(target)]="expression"
-
-
-
- Two-way
-
-
-
-
+* From source to view
+* From view to source
+* In a two-way sequence of view to source to view
+| Type | Syntax | Category |
+|:--- |:--- |:--- |
+| Interpolation
Property
Attribute
Class
Style |
{{expression}} 
[target]="expression" | One-way from data source to view target |
+| Event |
(target)="statement" | One-way from view target to data source |
+| Two-way |
[(target)]="expression" | Two-way |
Binding types other than interpolation have a target name to the left of the equal sign.
-The target of a binding is a property or event, which you surround with square brackets, `[]`, parentheses, `()`, or both, `[()]`.
+The target of a binding is a property or event, which you surround with square bracket \(`[ ]`\) characters, parenthesis \(`( )`\) characters, or both \(`[( )]`\) characters.
The binding punctuation of `[]`, `()`, `[()]`, and the prefix specify the direction of data flow.
-* Use `[]` to bind from source to view.
-* Use `()` to bind from view to source.
-* Use `[()]` to bind in a two way sequence of view to source to view.
-
+* Use `[]` to bind from source to view
+* Use `()` to bind from view to source
+* Use `[()]` to bind in a two way sequence of view to source to view
-Place the expression or statement to the right of the equal sign within double quotes, `""`.
+Place the expression or statement to the right of the equal sign within double quote \(`""`\) characters.
For more information see [Interpolation](guide/interpolation) and [Template statements](guide/template-statements).
## Binding types and targets
@@ -205,100 +159,19 @@ The target of a data binding can be a property, an event, or an attribute name.
Every public member of a source directive is automatically available for binding in a template expression or statement.
The following table summarizes the targets for the different binding types.
-
-
-
-
-
-
-
-
-
-
-
- Type
-
-
- Target
-
-
- Examples
-
-
-
-
- Property
-
-
- Element property
- Component property
- Directive property
-
-
- alt
, 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
-
-
-
-
-
-
+| Type | Target | Examples |
+|:--- |:--- |:--- |
+| Property | Element property
Component property
Directive property | `alt`, `src`, `hero`, and `ngClass` in the following:
|
+| Event | Elementevent
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 |
|
+
+
+
+
+
+
+
+@reviewed 2022-02-28
diff --git a/aio/content/guide/bootstrapping.md b/aio/content/guide/bootstrapping.md
index 3b3974fc41397..2d2c14a622aa0 100644
--- a/aio/content/guide/bootstrapping.md
+++ b/aio/content/guide/bootstrapping.md
@@ -1,28 +1,27 @@
# Launching your app with a root module
-#### Prerequisites
+## Prerequisites
A basic understanding of the following:
-* [JavaScript Modules vs. NgModules](guide/ngmodule-vs-jsmodule).
-
+* [JavaScript Modules vs. NgModules](guide/ngmodule-vs-jsmodule)
An NgModule describes how the application parts fit together.
-Every application has at least one Angular module, the _root_ module,
-which must be present for bootstrapping the application on launch.
+Every application has at least one Angular module, the *root* module, which must be present for bootstrapping the application on launch.
By convention and by default, this NgModule is named `AppModule`.
When you use the [Angular CLI](cli) command `ng new` to generate an app, the default `AppModule` looks like the following:
-```typescript
+
+
/* JavaScript imports */
-import { BrowserModule } from '@angular/platform-browser';
-import { NgModule } from '@angular/core';
+import { BrowserModule } from '@angular/platform-browser';
+import { NgModule } from '@angular/core';
import { AppComponent } from './app.component';
-/* the AppModule class with the @NgModule decorator */
-@NgModule({
+/* the AppModule class with the @NgModule decorator */
+@NgModule({
declarations: [
AppComponent
],
@@ -34,24 +33,23 @@ import { AppComponent } from './app.component';
})
export class AppModule { }
-```
+
-After the import statements is a class with the
-**`@NgModule`** [decorator](guide/glossary#decorator '"Decorator" explained').
+After the import statements is a class with the **`@NgModule`** [decorator](guide/glossary#decorator '"Decorator" explained').
The `@NgModule` decorator identifies `AppModule` as an `NgModule` class.
`@NgModule` takes a metadata object that tells Angular how to compile and launch the application.
-* **_declarations_**—this application's lone component.
-* **_imports_**—import `BrowserModule` to have browser specific services such as DOM rendering, sanitization, and location.
-* **_providers_**—the service providers.
-* **_bootstrap_**—the _root_ component that Angular creates and inserts
-into the `index.html` host web page.
+| metadata object | Details |
+|:--- |:--- |
+| declarations | This application's lone component. |
+| imports | Import `BrowserModule` to have browser-specific services such as DOM rendering, sanitization, and location. |
+| providers | The service providers. |
+| bootstrap | The *root* component that Angular creates and inserts into the `index.html` host web page. |
-The default application created by the Angular CLI only has one component, `AppComponent`, so it
-is in both the `declarations` and the `bootstrap` arrays.
+The default application created by the Angular CLI only has one component, `AppComponent`, so it is in both the `declarations` and the `bootstrap` arrays.
-{@a declarations}
+
## The `declarations` array
@@ -59,118 +57,106 @@ The module's `declarations` array tells Angular which components belong to that
As you create more components, add them to `declarations`.
You must declare every component in exactly one `NgModule` class.
-If you use a component without declaring it, Angular returns an
-error message.
+If you use a component without declaring it, Angular returns an error message.
-The `declarations` array only takes declarables. Declarables
-are components, [directives](guide/attribute-directives) and [pipes](guide/pipes).
+The `declarations` array only takes declarables. Declarables are components, [directives](guide/attribute-directives) and [pipes](guide/pipes).
All of a module's declarables must be in the `declarations` array.
-Declarables must belong to exactly one module. The compiler emits
-an error if you try to declare the same class in more than one module.
+Declarables must belong to exactly one module. The compiler emits an error if you try to declare the same class in more than one module.
-These declared classes are visible within the module but invisible
-to components in a different module unless they are exported from
-this module and the other module imports this one.
+These declared classes are visible within the module but invisible to components in a different module, unless they are exported from this module and the other module imports this one.
An example of what goes into a declarations array follows:
-```typescript
- declarations: [
- YourComponent,
- YourPipe,
- YourDirective
- ],
-```
+
-A declarable can only belong to one module, so only declare it in
-one `@NgModule`. When you need it elsewhere,
-import the module that has the declarable you need in it.
+declarations: [
+ YourComponent,
+ YourPipe,
+ YourDirective
+],
+
+
+A declarable can only belong to one module, so only declare it in one `@NgModule`.
+When you need it elsewhere, import the module that contains the declarable you need.
### Using directives with `@NgModule`
Use the `declarations` array for directives.
To use a directive, component, or pipe in a module, you must do a few things:
-1. Export it from the file where you wrote it.
-2. Import it into the appropriate module.
-3. Declare it in the `@NgModule` `declarations` array.
-
+1. Export it from the file where you wrote it.
+1. Import it into the appropriate module.
+1. Declare it in the `@NgModule` `declarations` array.
Those three steps look like the following. In the file where you create your directive, export it.
The following example, named `ItemDirective` is the default directive structure that the CLI generates in its own file, `item.directive.ts`:
-
+
-The key point here is that you have to export it so you can import it elsewhere. Next, import it
-into the `NgModule`, in this example `app.module.ts`, with a JavaScript import statement:
+The key point here is that you have to export it, so that you can import it elsewhere.
+Next, import it into the `NgModule`, in this example `app.module.ts`, with a JavaScript import statement:
-
+
And in the same file, add it to the `@NgModule` `declarations` array:
-
-
+
-Now you could use your `ItemDirective` in a component. This example uses `AppModule`, but you'd do it the same way for a feature module. For more about directives, see [Attribute Directives](guide/attribute-directives) and [Structural Directives](guide/structural-directives). You'd also use the same technique for [pipes](guide/pipes) and components.
+Now you could use your `ItemDirective` in a component.
+This example uses `AppModule`, but you'd do it the same way for a feature module.
+For more about directives, see [Attribute Directives](guide/attribute-directives) and [Structural Directives](guide/structural-directives).
+You'd also use the same technique for [pipes](guide/pipes) and components.
-Remember, components, directives, and pipes belong to one module only. You only need to declare them once in your application because you share them by importing the necessary modules. This saves you time and helps keep your application lean.
+Remember, components, directives, and pipes belong to one module only.
+You only need to declare them once in your application because you share them by importing the necessary modules.
+This saves you time and helps keep your application lean.
-{@a imports}
+
## The `imports` array
The module's `imports` array appears exclusively in the `@NgModule` metadata object.
It tells Angular about other NgModules that this particular module needs to function properly.
-
-
-
-This list of modules are those that export components, directives, or pipes
-that component templates in this module reference. In this case, the component is
-`AppComponent`, which references components, directives, or pipes in `BrowserModule`,
-`FormsModule`, or `HttpClientModule`.
-A component template can reference another component, directive,
-or pipe when the referenced class is declared in this module or
-the class was imported from another module.
+
+This list of modules are those that export components, directives, or pipes that component templates in this module reference.
+In this case, the component is `AppComponent`, which references components, directives, or pipes in `BrowserModule`, `FormsModule`, or `HttpClientModule`.
+A component template can reference another component, directive, or pipe when the referenced class is declared in this module, or the class was imported from another module.
-
-{@a bootstrap-array}
+
## The `providers` array
-The providers array is where you list the services the application needs. When
-you list services here, they are available app-wide. You can scope
-them when using feature modules and lazy loading. For more information, see
-[Providers](guide/providers).
+The providers array is where you list the services the application needs.
+When you list services here, they are available app-wide.
+You can scope them when using feature modules and lazy loading.
+For more information, see [Providers](guide/providers).
## The `bootstrap` array
-The application launches by bootstrapping the root `AppModule`, which is
-also referred to as an `entryComponent`.
-Among other things, the bootstrapping process creates the component(s) listed in the `bootstrap` array
-and inserts each one into the browser DOM.
+The application launches by bootstrapping the root `AppModule`, which is also referred to as an `entryComponent`.
+Among other things, the bootstrapping process creates the component\(s\) listed in the `bootstrap` array and inserts each one into the browser DOM.
Each bootstrapped component is the base of its own tree of components.
-Inserting a bootstrapped component usually triggers a cascade of
-component creations that fill out that tree.
+Inserting a bootstrapped component usually triggers a cascade of component creations that fill out that tree.
-While you can put more than one component tree on a host web page,
-most applications have only one component tree and bootstrap a single root component.
+While you can put more than one component tree on a host web page, most applications have only one component tree and bootstrap a single root component.
-This one root component is usually called `AppComponent` and is in the
-root module's `bootstrap` array.
+This one root component is usually called `AppComponent` and is in the root module's `bootstrap` array.
In a situation where you want to bootstrap a component based on an API response,
-or you want to mount the `AppComponent` in a different DOM node that doesn't match
-the component selector, please refer to `ApplicationRef.bootstrap()`
-documentation.
+or you want to mount the `AppComponent` in a different DOM node that doesn't match the component selector, please refer to `ApplicationRef.bootstrap()` documentation.
## More about Angular Modules
-For more on NgModules you're likely to see frequently in applications,
-see [Frequently Used Modules](guide/frequent-ngmodules).
+For more on NgModules you're likely to see frequently in applications, see [Frequently Used Modules](guide/frequent-ngmodules).
+
+
+
+
+
+
+
+@reviewed 2022-02-28
diff --git a/aio/content/guide/browser-support.md b/aio/content/guide/browser-support.md
index 0b67fb02c76e5..6150f272add8d 100644
--- a/aio/content/guide/browser-support.md
+++ b/aio/content/guide/browser-support.md
@@ -1,43 +1,20 @@
# Browser support
-Angular supports most recent browsers. This includes the following specific versions:
-
-
-
- Browser
- Supported versions
-
-
- Chrome
- latest
-
-
- Firefox
- latest and extended support release (ESR)
-
-
- Edge
- 2 most recent major versions
-
-
- Safari
- 2 most recent major versions
-
-
- iOS
- 2 most recent major versions
-
-
- Android
- 2 most recent major versions
-
-
-
+Angular supports most recent browsers.
+This includes the following specific versions:
+
+| Browser | Supported versions |
+|:--- |:--- |
+| Chrome | latest |
+| Firefox | latest and extended support release \(ESR\) |
+| Edge | 2 most recent major versions |
+| Safari | 2 most recent major versions |
+| iOS | 2 most recent major versions |
+| Android | 2 most recent major versions |
-Angular's continuous integration process runs unit tests of the framework on all of these browsers for every pull request,
-using [Sauce Labs](https://saucelabs.com/).
+Angular's continuous integration process runs unit tests of the framework on all of these browsers for every pull request, using [Sauce Labs](https://saucelabs.com).
@@ -45,14 +22,20 @@ using [Sauce Labs](https://saucelabs.com/).
Angular is built on the latest standards of the web platform.
Targeting such a wide range of browsers is challenging because they do not support all features of modern browsers.
-You compensate by loading polyfill scripts ("polyfills") for the browsers that you must support.
+You compensate by loading polyfill scripts \("polyfills"\) for the browsers that you must support.
See instructions on how to include polyfills into your project below.
The suggested polyfills are the ones that run full Angular applications.
You might need additional polyfills to support features not covered by this list.
-Note that polyfills cannot magically transform an old, slow browser into a modern, fast one.
+
+
+
+**NOTE**:
+Polyfills cannot magically transform an old, slow browser into a modern, fast one.
+
+
@@ -64,38 +47,46 @@ If you are not using the CLI to create your projects, see [Polyfill instructions
When you create a project with the `ng new` command, a `src/polyfills.ts` configuration file is created as part of your project folder.
This file incorporates the mandatory and many of the optional polyfills as JavaScript `import` statements.
-* The npm packages for the mandatory polyfills (such as `zone.js`) are installed automatically for you when you create your project with `ng new`, and their corresponding `import` statements are already enabled in the `src/polyfills.ts` configuration file.
-
-* If you need an _optional_ polyfill, you must install its npm package, then uncomment or create the corresponding import statement in the `src/polyfills.ts` configuration file.
+* The npm packages for the mandatory polyfills \(such as `zone.js`\) are installed automatically for you when you create your project with `ng new`, and their corresponding `import` statements are already enabled in the `src/polyfills.ts` configuration file
+* If you need an *optional* polyfill, you must install its npm package, then uncomment or create the corresponding import statement in the `src/polyfills.ts` configuration file
-
-{@a non-cli}
+
## Polyfills for non-CLI users
-If you are not using the CLI, add your polyfill scripts directly to the host web page (`index.html`).
+If you are not using the CLI, add your polyfill scripts directly to the host web page \(`index.html`\).
For example:
- <!-- pre-zone polyfills -->
- <script src="node_modules/core-js/client/shim.min.js"></script>
- <script>
- /**
- * you can configure some zone flags which can disable zone interception for some
- * asynchronous activities to improve startup performance - use these options only
- * if you know what you are doing as it could result in hard to trace down bugs..
- */
- // __Zone_disable_requestAnimationFrame = true; // disable patch requestAnimationFrame
- // __Zone_disable_on_property = true; // disable patch onProperty such as onclick
- // __zone_symbol__UNPATCHED_EVENTS = ['scroll', 'mousemove']; // disable patch specified eventNames
- /*
- * in Edge developer tools, the addEventListener will also be wrapped by zone.js
- * with the following flag, it will bypass `zone.js` patch for Edge
- */
- // __Zone_enable_cross_context_check = true;
- </script>
- <!-- zone.js required by Angular -->
- <script src="node_modules/zone.js/bundles/zone.umd.js"></script>
- <!-- application polyfills -->
+
+<!-- pre-zone polyfills -->
+<script src="node_modules/core-js/client/shim.min.js"></script>
+<script>
+ /**
+ * you can configure some zone flags which can disable zone interception for some
+ * asynchronous activities to improve startup performance - use these options only
+ * if you know what you are doing as it could result in hard to trace down bugs.
+ */
+ // __Zone_disable_requestAnimationFrame = true; // disable patch requestAnimationFrame
+ // __Zone_disable_on_property = true; // disable patch onProperty such as onclick
+ // __zone_symbol__UNPATCHED_EVENTS = ['scroll', 'mousemove']; // disable patch specified eventNames
+ /*
+ * in Edge developer tools, the addEventListener will also be wrapped by zone.js
+ * with the following flag, it will bypass `zone.js` patch for Edge.
+ */
+ // __Zone_enable_cross_context_check = true;
+</script>
+<!-- zone.js required by Angular -->
+<script src="node_modules/zone.js/bundles/zone.umd.js"></script>
+<!-- application polyfills -->
+
+
+
+
+
+
+
+
+@reviewed 2022-02-28
diff --git a/aio/content/guide/build.md b/aio/content/guide/build.md
index f3da17581834a..3a9c79e47610c 100644
--- a/aio/content/guide/build.md
+++ b/aio/content/guide/build.md
@@ -2,13 +2,14 @@
This page discusses build-specific configuration options for Angular projects.
-{@a app-environments}
+
## Configuring application environments
You can define different named build configurations for your project, such as *stage* and *production*, with different defaults.
-Each named configuration can have defaults for any of the options that apply to the various [builder targets](guide/glossary#target), such as `build`, `serve`, and `test`. The [Angular CLI](cli) `build`, `serve`, and `test` commands can then replace files with appropriate versions for your intended target environment.
+Each named configuration can have defaults for any of the options that apply to the various [builder targets](guide/glossary#target), such as `build`, `serve`, and `test`.
+The [Angular CLI](cli) `build`, `serve`, and `test` commands can then replace files with appropriate versions for your intended target environment.
### Configure environment-specific defaults
@@ -17,72 +18,114 @@ You can add override defaults for additional environments, such as production an
For example:
-```
-└──myProject/src/environments/
- └──environment.ts
- └──environment.prod.ts
- └──environment.stage.ts
-```
+
+
+ myProject/src/environments
+
+
+
+ environment.ts
+
+
+ environment.prod.ts
+
+
+ environment.stage.ts
+
+
+
+
+The base file `environment.ts`, contains the default environment settings.
+For example:
-The base file `environment.ts`, contains the default environment settings. For example:
+
-```
export const environment = {
production: false
};
-```
+
+
The `build` command uses this as the build target when no environment is specified.
You can add further variables, either as additional properties on the environment object, or as separate objects.
For example, the following adds a default for a variable to the default environment:
-```
+
+
export const environment = {
production: false,
apiUrl: 'http://my-api-url'
};
-```
+
+
You can add target-specific configuration files, such as `environment.prod.ts`.
The following sets content sets default values for the production build target:
-```
+
+
export const environment = {
production: true,
apiUrl: 'http://my-prod-url'
};
-```
+
+
### Using environment-specific variables in your app
The following application structure configures build targets for production and staging environments:
-```
-└── src
- └── app
- ├── app.component.html
- └── app.component.ts
- └── environments
- ├── environment.prod.ts
- ├── environment.staging.ts
- └── environment.ts
-```
+
+
+ src
+
+
+
+ app
+
+
+
+ app.component.html
+
+
+ app.component.ts
+
+
+
+ environments
+
+
+
+ environment.ts
+
+
+ environment.prod.ts
+
+
+ environment.prod.ts
+
+
+
+
To use the environment configurations you have defined, your components must import the original environments file:
-```
+
+
import { environment } from './../environments/environment';
-```
+
+
This ensures that the build and serve commands can find the configurations for specific build targets.
-The following code in the component file (`app.component.ts`) uses an environment variable defined in the configuration files.
+The following code in the component file \(`app.component.ts`\) uses an environment variable defined in the configuration files.
+
+
-```
-import { Component } from '@angular/core';
+import { Component } from '@angular/core';
import { environment } from './../environments/environment';
-@Component({
+@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
@@ -93,9 +136,10 @@ export class AppComponent {
}
title = 'app works!';
}
-```
-{@a file-replacement}
+
+
+
## Configure target-specific file replacements
@@ -106,7 +150,8 @@ By default no files are replaced.
You can add file replacements for specific build targets.
For example:
-```
+
+
"configurations": {
"production": {
"fileReplacements": [
@@ -115,16 +160,19 @@ For example:
"with": "src/environments/environment.prod.ts"
}
],
- ...
-```
+ …
+
+
This means that when you build your production configuration with `ng build --configuration production`, the `src/environments/environment.ts` file is replaced with the target-specific version of the file, `src/environments/environment.prod.ts`.
-You can add additional configurations as required. To add a staging environment, create a copy of `src/environments/environment.ts` called `src/environments/environment.staging.ts`, then add a `staging` configuration to `angular.json`:
+You can add additional configurations as required.
+To add a staging environment, create a copy of `src/environments/environment.ts` called `src/environments/environment.staging.ts`, then add a `staging` configuration to `angular.json`:
+
+
-```
"configurations": {
- "production": { ... },
+ "production": { … },
"staging": {
"fileReplacements": [
{
@@ -134,22 +182,26 @@ You can add additional configurations as required. To add a staging environment,
]
}
}
-```
+
+
You can add more configuration options to this target environment as well.
Any option that your build supports can be overridden in a build target configuration.
To build using the staging configuration, run the following command:
-
- ng build --configuration=staging
+
+
+ng build --configuration=staging
+
You can also configure the `serve` command to use the targeted build configuration if you add it to the "serve:configurations" section of `angular.json`:
-```
+
+
"serve": {
- "builder": "@angular-devkit/build-angular:dev-server",
+ "builder": "@angular-devkit/build-angular:dev-server",
"options": {
"browserTarget": "your-project-name:build"
},
@@ -162,10 +214,11 @@ You can also configure the `serve` command to use the targeted build configurati
}
}
},
-```
-{@a size-budgets}
-{@a configure-size-budgets}
+
+
+
+
## Configuring size budgets
@@ -174,124 +227,79 @@ The CLI lets you set size thresholds in your configuration to ensure that parts
Define your size boundaries in the CLI configuration file, `angular.json`, in a `budgets` section for each [configured environment](#app-environments).
-```
+
+
{
- ...
+ …
"configurations": {
"production": {
- ...
+ …
budgets: []
}
}
}
-```
+
+
You can specify size budgets for the entire app, and for particular parts.
Each budget entry configures a budget of a given type.
Specify size values in the following formats:
-* 123 or 123b: Size in bytes
-
-* 123kb: Size in kilobytes
-
-* 123mb: Size in megabytes
-
-* 12%: Percentage of size relative to baseline. (Not valid for baseline values.)
+| Size value | Details |
+|:--- |:--- |
+| `123` or `123b` | Size in bytes. |
+| `123kb` | Size in kilobytes. |
+| `123mb` | Size in megabytes. |
+| `12%` | Percentage of size relative to baseline. \(Not valid for baseline values.\) |
When you configure a budget, the build system warns or reports an error when a given part of the application reaches or exceeds a boundary size that you set.
Each budget entry is a JSON object with the following properties:
-
-
- Property
- Value
-
-
-
- type
-
-
- The type of budget. One of:
-
-* `bundle` - The size of a specific bundle.
-* `initial` - The size of JavaScript needed for bootstrapping the application. Defaults to warning @ 500kb and erroring at 1mb.
-* `allScript` - The size of all scripts.
-* `all` - The size of the entire application.
-* `anyComponentStyle` - This size of any one component stylesheet. Defaults to warning at 2kb and erroring at 4kb.
-* `anyScript` - The size of any one script.
-* `any` - The size of any file.
-
-
-
-
- name
-
-
- The name of the bundle (for `type=bundle`).
-
-
-
-
- baseline
- The baseline size for comparison.
-
-
- maximumWarning
- The maximum threshold for warning relative to the baseline.
-
-
- maximumError
- The maximum threshold for error relative to the baseline.
-
-
- minimumWarning
- The minimum threshold for warning relative to the baseline.
-
-
- minimumError
- The minimum threshold for error relative to the baseline.
-
-
- warning
- The threshold for warning relative to the baseline (min & max).
-
-
- error
- The threshold for error relative to the baseline (min & max).
-
-
-
-
-{@a commonjs }
+| Property | Value |
+|:--- |:--- |
+| type | The type of budget. One of: Value Details bundle
The size of a specific bundle. initial
The size of JavaScript needed for bootstrapping the application. Defaults to warning at 500kb and erroring at 1mb. allScript
The size of all scripts. all
The size of the entire application. anyComponentStyle
This size of any one component stylesheet. Defaults to warning at 2kb and erroring at 4kb. anyScript
The size of any one script. any
The size of any file.
|
+| name | The name of the bundle \(for `type=bundle`\). |
+| baseline | The baseline size for comparison. |
+| maximumWarning | The maximum threshold for warning relative to the baseline. |
+| maximumError | The maximum threshold for error relative to the baseline. |
+| minimumWarning | The minimum threshold for warning relative to the baseline. |
+| minimumError | The minimum threshold for error relative to the baseline. |
+| warning | The threshold for warning relative to the baseline \(min & max\). |
+| error | The threshold for error relative to the baseline \(min & max\). |
+
+
+
## Configuring CommonJS dependencies
It is recommended that you avoid depending on CommonJS modules in your Angular applications.
Depending on CommonJS modules can prevent bundlers and minifiers from optimizing your application, which results in larger bundle sizes.
-Instead, it is recommended that you use [ECMAScript modules](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import) in your entire application.
-For more information, see [How CommonJS is making your bundles larger](https://web.dev/commonjs-larger-bundles/).
+Instead, it is recommended that you use [ECMAScript modules](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Statements/import) in your entire application.
+For more information, see [How CommonJS is making your bundles larger](https://web.dev/commonjs-larger-bundles).
The Angular CLI outputs warnings if it detects that your browser application depends on CommonJS modules.
To disable these warnings, add the CommonJS module name to `allowedCommonJsDependencies` option in the `build` options located in `angular.json` file.
-
+
+
"build": {
- "builder": "@angular-devkit/build-angular:browser",
+ "builder": "@angular-devkit/build-angular:browser",
"options": {
"allowedCommonJsDependencies": [
"lodash"
]
- ...
+ …
}
- ...
+ …
},
+
-{@a browser-compat}
+
## Configuring browser compatibility
@@ -302,68 +310,85 @@ Internally, Autoprefixer relies on a library called [Browserslist](https://githu
Browserlist looks for configuration options in a `browserslist` property of the package configuration file, or in a configuration file named `.browserslistrc`.
Autoprefixer looks for the `browserslist` configuration when it prefixes your CSS.
-* Tell Autoprefixer what browsers to target by adding a browserslist property to the package configuration file, `package.json`:
-```
- "browserslist": [
- "> 1%",
- "last 2 versions"
- ]
-```
-
-* Alternatively, you can add a new file, `.browserslistrc`, to the project directory, that specifies browsers you want to support:
-```
- ### Supported Browsers
- > 1%
- last 2 versions
-```
+* Tell Autoprefixer what browsers to target by adding a browserslist property to the package configuration file, `package.json`:
+
+
+
+ "browserslist": [
+ "> 1%",
+ "last 2 versions"
+ ]
+
+
+
+* Alternatively, you can add a new file, `.browserslistrc`, to the project directory, that specifies browsers you want to support:
+
+
+
+ ### Supported Browsers
+ > 1%
+ last 2 versions
+
+
See the [browserslist repo](https://github.com/browserslist/browserslist) for more examples of how to target specific browsers and versions.
-{@a proxy}
+
## Proxying to a backend server
Use the [proxying support](https://webpack.js.org/configuration/dev-server/#devserverproxy) in the `webpack` development server to divert certain URLs to a backend server, by passing a file to the `--proxy-config` build option.
For example, to divert all calls for `http://localhost:4200/api` to a server running on `http://localhost:3000/api`, take the following steps.
-1. Create a file `proxy.conf.json` in your project's `src/` folder.
+1. Create a file `proxy.conf.json` in your project's `src/` folder.
+1. Add the following content to the new proxy file:
+
+
-1. Add the following content to the new proxy file:
- ```
{
"/api": {
"target": "http://localhost:3000",
"secure": false
}
}
- ```
-1. In the CLI configuration file, `angular.json`, add the `proxyConfig` option to the `serve` target:
- ```
- ...
+
+
+1. In the CLI configuration file, `angular.json`, add the `proxyConfig` option to the `serve` target:
+
+
+
+ …
"architect": {
"serve": {
- "builder": "@angular-devkit/build-angular:dev-server",
+ "builder": "@angular-devkit/build-angular:dev-server",
"options": {
"browserTarget": "your-application-name:build",
"proxyConfig": "src/proxy.conf.json"
},
- ...
- ```
+ …
-1. To run the development server with this proxy configuration, call `ng serve`.
+
+
+1. To run the development server with this proxy configuration, call `ng serve`.
Edit the proxy configuration file to add configuration options; following are some examples.
For a description of all options, see [webpack DevServer documentation](https://webpack.js.org/configuration/dev-server/#devserverproxy).
-Note that if you edit the proxy configuration file, you must relaunch the `ng serve` process to make your changes effective.
+
+
+**NOTE**:
+If you edit the proxy configuration file, you must relaunch the `ng serve` process to make your changes effective.
+
+
### Rewrite the URL path
The `pathRewrite` proxy configuration option lets you rewrite the URL path at run time.
For example, specify the following `pathRewrite` value to the proxy configuration to remove "api" from the end of a path.
-```
+
+
{
"/api": {
"target": "http://localhost:3000",
@@ -373,11 +398,14 @@ For example, specify the following `pathRewrite` value to the proxy configuratio
}
}
}
-```
-If you need to access a backend that is not on `localhost`, set the `changeOrigin` option as well. For example:
+
+
+If you need to access a backend that is not on `localhost`, set the `changeOrigin` option as well.
+For example:
+
+
-```
{
"/api": {
"target": "http://npmjs.org",
@@ -388,11 +416,14 @@ If you need to access a backend that is not on `localhost`, set the `changeOrigi
"changeOrigin": true
}
}
-```
-To help determine whether your proxy is working as intended, set the `logLevel` option. For example:
+
+
+To help determine whether your proxy is working as intended, set the `logLevel` option.
+For example:
+
+
-```
{
"/api": {
"target": "http://localhost:3000",
@@ -403,17 +434,19 @@ To help determine whether your proxy is working as intended, set the `logLevel`
"logLevel": "debug"
}
}
-```
-Proxy log levels are `info` (the default), `debug`, `warn`, `error`, and `silent`.
+
+
+Proxy log levels are `info` \(the default\), `debug`, `warn`, `error`, and `silent`.
### Proxy multiple entries
You can proxy multiple entries to the same target by defining the configuration in JavaScript.
-Set the proxy configuration file to `proxy.conf.js` (instead of `proxy.conf.json`), and specify configuration files as in the following example.
+Set the proxy configuration file to `proxy.conf.js` \(instead of `proxy.conf.json`\), and specify configuration files as in the following example.
+
+
-```
const PROXY_CONFIG = [
{
context: [
@@ -431,27 +464,31 @@ const PROXY_CONFIG = [
]
module.exports = PROXY_CONFIG;
-```
+
+
In the CLI configuration file, `angular.json`, point to the JavaScript proxy configuration file:
-```
-...
+
+
+…
"architect": {
"serve": {
- "builder": "@angular-devkit/build-angular:dev-server",
+ "builder": "@angular-devkit/build-angular:dev-server",
"options": {
"browserTarget": "your-application-name:build",
"proxyConfig": "src/proxy.conf.js"
},
-...
-```
+…
+
+
### Bypass the proxy
If you need to optionally bypass the proxy, or dynamically change the request before it's sent, add the bypass option, as shown in this JavaScript example.
-```
+
+
const PROXY_CONFIG = {
"/api/proxy": {
"target": "http://localhost:3000",
@@ -467,22 +504,26 @@ const PROXY_CONFIG = {
}
module.exports = PROXY_CONFIG;
-```
+
+
### Using corporate proxy
If you work behind a corporate proxy, the backend cannot directly proxy calls to any URL outside your local network.
In this case, you can configure the backend proxy to redirect calls through your corporate proxy using an agent:
-
+
+
npm install --save-dev https-proxy-agent
+
When you define an environment variable `http_proxy` or `HTTP_PROXY`, an agent is automatically added to pass calls through your corporate proxy when running `npm start`.
Use the following content in the JavaScript configuration file.
-```
+
+
var HttpsProxyAgent = require('https-proxy-agent');
var proxyConfig = [{
context: '/api',
@@ -491,7 +532,7 @@ var proxyConfig = [{
}];
function setupForCorporateProxy(proxyConfig) {
- var proxyServer = process.env.http_proxy || process.env.HTTP_PROXY;
+ var proxyServer = process.env.http_proxy || process.env.HTTP_PROXY;
if (proxyServer) {
var agent = new HttpsProxyAgent(proxyServer);
console.log('Using corporate proxy server: ' + proxyServer);
@@ -503,10 +544,19 @@ function setupForCorporateProxy(proxyConfig) {
}
module.exports = setupForCorporateProxy(proxyConfig);
-```
-{@a browser-compat}
+
+
+
## Configuring browser compatibility
See [browser support guide](guide/browser-support).
+
+
+
+
+
+
+
+@reviewed 2022-02-28
diff --git a/aio/content/guide/built-in-directives.md b/aio/content/guide/built-in-directives.md
index cec28fb80d91a..29d646fe46066 100644
--- a/aio/content/guide/built-in-directives.md
+++ b/aio/content/guide/built-in-directives.md
@@ -12,14 +12,16 @@ See the for a working example containing the code
The different types of Angular directives are as follows:
-1. [Components](guide/component-overview)—directives with a template.
- This type of directive is the most common directive type.
-1. [Attribute directives](guide/built-in-directives#built-in-attribute-directives)—directives that change the appearance or behavior of an element, component, or another directive.
-1. [Structural directives](guide/built-in-directives#built-in-structural-directives)—directives that change the DOM layout by adding and removing DOM elements.
+| Directive Types | Details |
+|:--- |:--- |
+| [Components](guide/component-overview) | Used with a template. This type of directive is the most common directive type. |
+| [Attribute directives](guide/built-in-directives#built-in-attribute-directives) | Change the appearance or behavior of an element, component, or another directive. |
+| [Structural directives](guide/built-in-directives#built-in-structural-directives) | Change the DOM layout by adding and removing DOM elements. |
This guide covers built-in [attribute directives](guide/built-in-directives#built-in-attribute-directives) and [structural directives](guide/built-in-directives#built-in-structural-directives).
-{@a attribute-directives}
+
+
## Built-in attribute directives
Attribute directives listen to and modify the behavior of other HTML elements, attributes, properties, and components.
@@ -27,9 +29,11 @@ Attribute directives listen to and modify the behavior of other HTML elements, a
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.
+| Common directives | Details |
+|:--- |:--- |
+| [`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. |
@@ -38,7 +42,8 @@ They do not have special access to any private APIs that other directives can't
-{@a ngClass}
+
+
## Adding and removing classes with `NgClass`
Add or remove multiple CSS classes simultaneously with `ngClass`.
@@ -55,75 +60,78 @@ On the element you'd like to style, add `[ngClass]` and set it equal to an expre
In this case, `isSpecial` is a boolean set to `true` in `app.component.ts`.
Because `isSpecial` is true, `ngClass` applies the class of `special` to the ``.
-
+
### Using `NgClass` with a method
-1. To use `NgClass` with a method, add the method to the component class.
- In the following example, `setCurrentClasses()` sets the property `currentClasses` with an object that adds or removes three classes based on the `true` or `false` state of three other component properties.
+1. To use `NgClass` with a method, add the method to the component class.
+ In the following example, `setCurrentClasses()` sets the property `currentClasses` with an object that adds or removes three classes based on the `true` or `false` state of three other component properties.
- Each key of the object is a CSS class name.
- If a key is `true`, `ngClass` adds the class.
- If a key is `false`, `ngClass` removes the class.
+ Each key of the object is a CSS class name.
+ If a key is `true`, `ngClass` adds the class.
+ If a key is `false`, `ngClass` removes the class.
-
+
-1. In the template, add the `ngClass` property binding to `currentClasses` to set the element's classes:
+1. In the template, add the `ngClass` property binding to `currentClasses` to set the element's classes:
-
+
For this use case, Angular applies the classes on initialization and in case of changes.
The full example calls `setCurrentClasses()` initially with `ngOnInit()` and when the dependent properties change through a button click.
These steps are not necessary to implement `ngClass`.
For more information, see the
`app.component.ts` and `app.component.html`.
-{@a ngstyle}
+
+
## Setting inline styles with `NgStyle`
Use `NgStyle` to set multiple inline styles simultaneously, based on the state of the component.
-1. To use `NgStyle`, add a method to the component class.
+1. To use `NgStyle`, add a method to the component class.
- In the following example, `setCurrentStyles()` sets the property `currentStyles` with an object that defines three styles, based on the state of three other component properties.
+ In the following example, `setCurrentStyles()` sets the property `currentStyles` with an object that defines three styles, based on the state of three other component properties.
-
+
-1. To set the element's styles, add an `ngStyle` property binding to `currentStyles`.
+1. To set the element's styles, add an `ngStyle` property binding to `currentStyles`.
-
+
For this use case, Angular applies the styles upon initialization and in case of changes.
To do this, the full example calls `setCurrentStyles()` initially with `ngOnInit()` and when the dependent properties change through a button click.
However, these steps are not necessary to implement `ngStyle` on its own.
See the
`app.component.ts` and `app.component.html` for this optional implementation.
-{@a ngModel}
+
+
## Displaying and updating properties with `ngModel`
Use the `NgModel` directive to display a data property and update that property when the user makes changes.
-1. Import `FormsModule` and add it to the NgModule's `imports` list.
+1. Import `FormsModule` and add it to the NgModule's `imports` list.
-
+
-1. Add an `[(ngModel)]` binding on an HTML `
### `NgModel` and value accessors
@@ -140,7 +148,7 @@ When you write an Angular component, you don't need a value accessor or `NgModel
-{@a structural-directives}
+
## Built-in structural directives
@@ -149,14 +157,16 @@ They shape or reshape the DOM's structure, typically by adding, removing, and ma
This section introduces the most common built-in structural directives:
-* [`NgIf`](guide/built-in-directives#ngIf)—conditionally creates or disposes of subviews from the template.
-* [`NgFor`](guide/built-in-directives#ngFor)—repeat a node for each item in a list.
-* [`NgSwitch`](guide/built-in-directives#ngSwitch)—a set of directives that switch among alternative views.
+| Common built-in structural directives | Details |
+|:--- |:--- |
+| [`NgIf`](guide/built-in-directives#ngIf) | Conditionally creates or disposes of subviews from the template. |
+| [`NgFor`](guide/built-in-directives#ngFor) | Repeat a node for each item in a list. |
+| [`NgSwitch`](guide/built-in-directives#ngSwitch) | A set of directives that switch among alternative views. |
For more information, see [Structural Directives](guide/structural-directives).
+
-{@a ngIf}
## Adding or removing an element with `NgIf`
Add or remove an element by applying an `NgIf` directive to a host element.
@@ -166,7 +176,7 @@ Angular then disposes of their components, which frees up memory and resources.
To add or remove an element, bind `*ngIf` to a condition expression such as `isActive` in the following example.
-
+
When the `isActive` expression returns a truthy value, `NgIf` adds the `ItemDetailComponent` to the DOM.
When the expression is falsy, `NgIf` removes the `ItemDetailComponent` from the DOM and disposes of the component and all of its sub-components.
@@ -180,47 +190,48 @@ By default, `NgIf` prevents display of an element bound to a null value.
To use `NgIf` to guard a ``, add `*ngIf="yourProperty"` to the `
`.
In the following example, the `currentCustomer` name appears because there is a `currentCustomer`.
-
+
However, if the property is `null`, Angular does not display the `
`.
In this example, Angular does not display the `nullCustomer` because it is `null`.
-
+
+
+
-{@a ngFor}
## Listing items with `NgFor`
Use the `NgFor` directive to present a list of items.
-1. Define a block of HTML that determines how Angular renders a single item.
-
-1. To list your items, assign the short hand `let item of items` to `*ngFor`.
+1. Define a block of HTML that determines how Angular renders a single item.
+1. To list your items, assign the short hand `let item of items` to `*ngFor`.
-
+
The string `"let item of items"` instructs Angular to do the following:
- * Store each item in the `items` array in the local `item` looping variable
- * Make each item available to the templated HTML for each iteration
- * Translate `"let item of items"` into an `
` around the host element
- * Repeat the `` for each `item` in the list
+* Store each item in the `items` array in the local `item` looping variable
+* Make each item available to the templated HTML for each iteration
+* Translate `"let item of items"` into an `` around the host element
+* Repeat the `` for each `item` in the list
For more information see the [Structural directive shorthand](guide/structural-directives#shorthand) section of [Structural directives](guide/structural-directives).
+
### Repeating a component view
To repeat a component element, apply `*ngFor` to the selector.
In the following example, the selector is ``.
-
+
Reference a template input variable, such as `item`, in the following locations:
- * within the `ngFor` host element
- * within the host element descendants to access the item's properties
+* Within the `ngFor` host element
+* Within the host element 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 directive shorthand](guide/structural-directives#shorthand).
@@ -231,7 +242,7 @@ Get the `index` of `*ngFor` in a template input variable and use it in the templ
In the `*ngFor`, add a semicolon and `let i=index` to the short hand.
The following example gets the `index` in a variable named `i` and displays it with the item name.
-
+
The index property of the `NgFor` directive context returns the zero-based index of the item in each iteration.
@@ -240,7 +251,8 @@ then uses this template repeatedly to create a new set of elements and bindings
in the list.
For more information about shorthand, see the [Structural Directives](guide/structural-directives#shorthand) guide.
-{@a one-per-element}
+
+
## Repeating elements when a condition is true
To repeat a block of HTML when a particular condition is true, put the `*ngIf` on a container element that wraps an `*ngFor` element.
@@ -250,33 +262,36 @@ Because structural directives add and remove nodes from the DOM, apply only one
For more information about `NgFor` see the [NgForOf API reference](api/common/NgForOf).
-{@a ngfor-with-trackby}
+
+
### Tracking items with `*ngFor` `trackBy`
Reduce the number of calls your application makes to the server by tracking changes to an item list.
With the `*ngFor` `trackBy` property, Angular can change and re-render only those items that have changed, rather than reloading the entire list of items.
-1. Add a method to the component that returns the value `NgFor` should track.
- In this example, the value to track is the item's `id`.
- If the browser has already rendered `id`, Angular keeps track of it and doesn't re-query the server for the same `id`.
+1. Add a method to the component that returns the value `NgFor` should track.
+ In this example, the value to track is the item's `id`.
+ If the browser has already rendered `id`, Angular keeps track of it and doesn't re-query the server for the same `id`.
-
+
-1. In the short hand expression, set `trackBy` to the `trackByItems()` method.
+1. In the short hand expression, set `trackBy` to the `trackByItems()` method.
-
+
**Change ids** creates new items with new `item.id`s.
In the following illustration of the `trackBy` effect, **Reset items** creates new items with the same `item.id`s.
-* With no `trackBy`, both buttons trigger complete DOM element replacement.
-* With `trackBy`, only changing the `id` triggers element replacement.
+* With no `trackBy`, both buttons trigger complete DOM element replacement.
+* With `trackBy`, only changing the `id` triggers element replacement.
-
+
+
+
-{@a ngcontainer}
+
## Hosting a directive without a DOM element
@@ -286,63 +301,81 @@ Use `` when there's no single element to host the directive.
Here's a conditional paragraph using ``.
-
-
+
-
+
+
+
-1. Import the `ngModel` directive from `FormsModule`.
+1. Import the `ngModel` directive from `FormsModule`.
+
+1. Add `FormsModule` to the imports section of the relevant Angular module.
-1. Add `FormsModule` to the imports section of the relevant Angular module.
+1. To conditionally exclude an ``, wrap the ` ` in an ``.
-1. To conditionally exclude an ``, wrap the ` ` in an ``.
+
-
+
-
-
-
+
+
+
+
+
-{@a ngSwitch}
## Switching cases with `NgSwitch`
Like the JavaScript `switch` statement, `NgSwitch` displays one element from among several possible elements, based on a switch condition.
Angular puts only the selected element into the DOM.
-
+
+
+
`NgSwitch` is a set of three directives:
- * `NgSwitch`—an attribute directive that changes the behavior of its companion directives.
- * `NgSwitchCase`—structural directive that 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`—structural directive that adds its element to the DOM when there is no selected `NgSwitchCase`.
+| `NgSwitch` directives | Details |
+|:--- |:--- |
+| `NgSwitch` | An attribute directive that changes the behavior of its companion directives. |
+| `NgSwitchCase` | Structural directive that 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` | Structural directive that adds its element to the DOM when there is no selected `NgSwitchCase`. |
+
+1. On an element, such as a ``, add `[ngSwitch]` bound to an expression that returns the switch value, such as `feature`.
+ Though the `feature` value in this example is a string, the switch value can be of any type.
-1. On an element, such as a `
`, add `[ngSwitch]` bound to an expression that returns the switch value, such as `feature`.
- Though the `feature` value in this example is a string, the switch value can be of any type.
+1. Bind to `*ngSwitchCase` and `*ngSwitchDefault` on the elements for the cases.
-1. Bind to `*ngSwitchCase` and `*ngSwitchDefault` on the elements for the cases.
+
-
+1. In the parent component, define `currentItem`, to use it in the `[ngSwitch]` expression.
-1. In the parent component, define `currentItem`, to use it in the `[ngSwitch]` expression.
+
-
+1. In each child component, add an `item` [input property](guide/inputs-outputs#input "Input property") which is bound to the `currentItem` of the parent component.
+ The following two snippets show the parent component and one of the child components.
+ The other child components are identical to `StoutItemComponent`.
-1. In each child component, add an `item` [input property](guide/inputs-outputs#input "Input property") which is bound to the `currentItem` of the parent component.
- The following two snippets show the parent component and one of the child components.
- The other child components are identical to `StoutItemComponent`.
+
-
+
-
-
-
+
+
+
Switch directives also work with built-in HTML elements and web components.
For example, you could replace the `
` switch case with a `` as follows.
-
+
## What's next
For information on how to build your own custom directives, see [Attribute Directives](guide/attribute-directives) and [Structural Directives](guide/structural-directives).
+
+
+
+
+
+
+
+@reviewed 2022-02-28
diff --git a/aio/content/guide/cheatsheet.md b/aio/content/guide/cheatsheet.md
index d721ad0209790..90217a849fa3a 100644
--- a/aio/content/guide/cheatsheet.md
+++ b/aio/content/guide/cheatsheet.md
@@ -2,479 +2,122 @@
Cheat Sheet
-
-
-Bootstrapping
-import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
-
-
-
-
-platformBrowserDynamic().bootstrapModule (AppModule);
-Bootstraps the application, using the root component from the specified NgModule
.
-
-
-
+| Bootstrapping | Details |
+|:--- |:--- |
+|
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; | Import `platformBrowserDynamic` from `@angular/platform-browser-dynamic`. |
+|
platformBrowserDynamic().bootstrapModule(AppModule); | Bootstraps the application, using the root component from the specified `NgModule`. |
+
+| NgModules | Details |
+|:--- |:--- |
+|
import { NgModule } from '@angular/core'; | Import `NgModule` from `@angular/core`. |
+|
@NgModule({ 
 declarations: …, 
 imports: …, 
 exports: …, 
 providers: …, 
 bootstrap: … 
}) 
class MyModule {} | Defines a module that contains components, directives, pipes, and providers. |
+|
declarations: [ 
 MyRedComponent, 
 MyBlueComponent, 
 MyDatePipe 
] | List of components, directives, and pipes that belong to this module. |
+|
imports: [ 
 BrowserModule, 
 SomeOtherModule 
] | List of modules to import into this module. Everything from the imported modules is available to `declarations` of this module. |
+|
exports: [ 
 MyRedComponent, 
 MyDatePipe 
] | List of components, directives, and pipes visible to modules that import this module. |
+|
providers: [ 
 MyService, 
 { provide: … } 
] | List of dependency injection providers visible both to the contents of this module and to importers of this module. |
+|
bootstrap: [MyAppComponent] | List of components to bootstrap when this module is bootstrapped. |
+
+| Template syntax | Details |
+|:--- |:--- |
+|
<input [value]="firstName"> | Binds property `value` to the result of expression `firstName`. |
+|
<div [attr.role]="myAriaRole"> | Binds attribute `role` to the result of expression `myAriaRole`. |
+|
<div [class.extra-sparkle]="isDelightful"> | Binds the presence of the CSS class `extra-sparkle` on the element to the truthiness of the expression `isDelightful`. |
+|
<div [style.width.px]="mySize"> | Binds style property `width` to the result of expression `mySize` in pixels. Units are optional. |
+|
<button (click)="readRainbow($event)"> | Calls method `readRainbow` when a click event is triggered on this button element \(or its children\) and passes in the event object. |
+|
<div title="Hello {{ponyName}}"> | Binds a property to an interpolated string, for example, "Hello Seabiscuit". Equivalent to:
<div [title]="'Hello ' + ponyName"> |
+|
<p> 
 Hello {{ponyName}} 
</p> | Binds text content to an interpolated string, for example, "Hello Seabiscuit". |
+|
<my-cmp [(title)]="name"> | Sets up two-way data binding. Equivalent to:
<my-cmp [title]="name" (titleChange)="name=$event"> |
+|
<video ‐movieplayer …></video> 
<button (click)="movieplayer.play()"> 
 Play 
</button> | Creates a local variable `movieplayer` that provides access to the `video` element instance in data-binding and event-binding expressions in the current template. |
+|
<p *myUnless="myExpression"> 
 … 
</p> | The asterisk \(`*`\) character turns the current element into an embedded template. Equivalent to:
<ng-template [myUnless]="myExpression"> 
 <p> 
 … 
 </p> 
</ng-template> |
+|
<p> 
 Card No.: {{cardNumber | myCardNumberFormatter}} 
</p> | Transforms the current value of expression `cardNumber` using the pipe called `myCardNumberFormatter`. |
+|
<p> 
 Employer: {{employer?.companyName}} 
</p> | The safe navigation operator \(`?`\) means that the `employer` field is optional and if `undefined`, the rest of the expression should be ignored. |
+|
<svg:rect x="0" 
 y="0" 
 width="100" 
 height="100"/> | An SVG snippet template needs an `svg:` prefix on its root element to disambiguate the SVG element from an HTML component. |
+|
<svg> 
 <rect x="0" 
 y="0" 
 width="100" 
 height="100"/> 
</svg> | An `
` root element is detected as an SVG element automatically, without the prefix. |
+
+| Built-in directives | Details |
+|:--- |:--- |
+| import { CommonModule } from '@angular/common'; | Import `CommonModule` from `@angular/common`. |
+| <section *ngIf="showSection"> | Removes or recreates a portion of the DOM tree based on the `showSection` expression. |
+| <li *ngFor="let item of list"> | Turns the `li` element and its contents into a template, and uses that to instantiate a view for each item in list. |
+| <div [ngSwitch]="conditionExpression">
 <ng-template [ngSwitchCase]="case1Exp"> 
 … 
 </ng-template>
 <ng-template ngSwitchCase="case2LiteralString"> 
 … 
 </ng-template>
 <ng-template ngSwitchDefault> 
 … 
 </ng-template> 
</div> | Conditionally swaps the contents of the `div` by selecting one of the embedded templates based on the current value of `conditionExpression`. |
+| <div [ngClass]="{'active': isActive, 
 'disabled': isDisabled}"> | Binds the presence of CSS classes on the element to the truthiness of the associated map values. The right-hand expression should return `{class-name: true/false}` map. |
+| <div [ngStyle]="{'property': 'value'}"> 
<div [ngStyle]="dynamicStyles()"> | Allows you to assign styles to an HTML element using CSS. You can use CSS directly, as in the first example, or you can call a method from the component. |
+
+| Forms | Details |
+|:--- |:--- |
+| import { FormsModule } from '@angular/forms'; | Import `FormsModule` from `@angular/forms`. |
+| <input [(ngModel)]="userName"> | Provides two-way data-binding, parsing, and validation for form controls. |
+
+| Class decorators | Details |
+|:--- |:--- |
+| import { Directive, … } from '@angular/core'; | Import `Directive, …` from `@angular/core';`. |
+| @Component({…}) 
class MyComponent() {} | Declares that a class is a component and provides metadata about the component. |
+| @Directive({…}) 
class MyDirective() {} | Declares that a class is a directive and provides metadata about the directive. |
+| @Pipe({…}) 
class MyPipe() {} | Declares that a class is a pipe and provides metadata about the pipe. |
+| @Injectable() 
class MyService() {} | Declares that a class can be provided and injected by other classes. Without this decorator, the compiler won't generate enough metadata to allow the class to be created properly when it's injected somewhere. |
+
+| Directive configuration | Details |
+|:--- |:--- |
+| @Directive({ 
 property1: value1, 
 … 
}) | Add `property1` property with `value1` value to Directive. |
+| selector: '.cool-button:not(a)' | Specifies a CSS selector that identifies this directive within a template. Supported selectors include `element`, `[attribute]`, `.class`, and `:not()`. Does not support parent-child relationship selectors. |
+| providers: [ 
 MyService, 
 { provide: … } 
] | List of dependency injection providers for this directive and its children. |
+
+| Component configuration `@Component` extends `@Directive`, so the `@Directive` configuration applies to components as well | Details |
+|:--- |:--- |
+| moduleId: module.id | If set, the `templateUrl` and `styleUrl` are resolved relative to the component. |
+| viewProviders: [MyService, { provide: … }] | List of dependency injection providers scoped to this component's view. |
+| template: 'Hello {{name}}' 
templateUrl: 'my-component.html' | Inline template or external template URL of the component's view. |
+| styles: ['.primary {color: red}'] 
styleUrls: ['my-component.css'] | List of inline CSS styles or external stylesheet URLs for styling the component's view. |
+
+| Class field decorators for directives and components | Details |
+|:--- |:--- |
+| import { Input, … } from '@angular/core'; | Import `Input, …` from `@angular/core`. |
+| @Input() myProperty; | Declares an input property that you can update using property binding \(example: ``\). |
+| @Output() myEvent = new EventEmitter(); | Declares an output property that fires events that you can subscribe to with an event binding \(example: ``\). |
+| @HostBinding('class.valid') isValid; | Binds a host element property \(here, the CSS class `valid`\) to a directive/component property \(`isValid`\). |
+| @HostListener('click', ['$event']) onClick(e) {…} | Subscribes to a host element event \(`click`\) with a directive/component method \(`onClick`\), optionally passing an argument \(`$event`\). |
+| @ContentChild(myPredicate) myChildComponent; | Binds the first result of the component content query \(`myPredicate`\) to a property \(`myChildComponent`\) of the class. |
+| @ContentChildren(myPredicate) myChildComponents; | Binds the results of the component content query \(`myPredicate`\) to a property \(`myChildComponents`\) of the class. |
+| @ViewChild(myPredicate) myChildComponent; | Binds the first result of the component view query \(`myPredicate`\) to a property \(`myChildComponent`\) of the class. Not available for directives. |
+| @ViewChildren(myPredicate) myChildComponents; | Binds the results of the component view query \(`myPredicate`\) to a property \(`myChildComponents`\) of the class. Not available for directives. |
+
+| Directive and component change detection and lifecycle hooks \(implemented as class methods\) | Details |
+|:--- |:--- |
+| constructor(myService: MyService, …) { … } | Called before any other lifecycle hook. Use it to inject dependencies, but avoid any serious work here. |
+| ngOnChanges(changeRecord) { … } | Called after every change to input properties and before processing content or child views. |
+| ngOnInit() { … } | Called after the constructor, initializing input properties, and the first call to `ngOnChanges`. |
+| ngDoCheck() { … } | Called every time that the input properties of a component or a directive are checked. Use it to extend change detection by performing a custom check. |
+| ngAfterContentInit() { … } | Called after `ngOnInit` when the component's or directive's content has been initialized. |
+| ngAfterContentChecked() { … } | Called after every check of the component's or directive's content. |
+| ngAfterViewInit() { … } | Called after `ngAfterContentInit` when the component's views and child views / the view that a directive is in has been initialized. |
+| ngAfterViewChecked() { … } | Called after every check of the component's views and child views / the view that a directive is in. |
+| ngOnDestroy() { … } | Called once, before the instance is destroyed. |
+
+| Dependency injection configuration | Details |
+|:--- |:--- |
+| { provide: MyService, useClass: MyMockService } | Sets or overrides the provider for `MyService` to the `MyMockService` class. |
+| { provide: MyService, useFactory: myFactory } | Sets or overrides the provider for `MyService` to the `myFactory` factory function. |
+| { provide: MyValue, useValue: 41 } | Sets or overrides the provider for `MyValue` to the value `41`. |
+
+| Routing and navigation | Details |
+|:--- |:--- |
+| import { Routes, RouterModule, … } from '@angular/router'; | Import `Routes, RouterModule, …` from `@angular/router`. |
+| const routes: Routes = [ 
 { path: '', component: HomeComponent }, 
 { path: 'path/:routeParam', component: MyComponent }, 
 { path: 'staticPath', component: … }, 
 { path: '**', component: … }, 
 { path: 'oldPath', redirectTo: '/staticPath' }, 
 { path: …, component: …, data: { message: 'Custom' } } 
]); 
 
const routing = RouterModule.forRoot(routes); | Configures routes for the application. Supports static, parameterized, redirect, and wildcard routes. Also supports custom route data and resolve. |
+| <router-outlet></router-outlet> 
<router-outlet name="aux"></router-outlet> | Marks the location to load the component of the active route. |
+| <a routerLink="/path"> 
<a [routerLink]="[ '/path', routeParam ]"> 
<a [routerLink]="[ '/path', { matrixParam: 'value' } ]"> 
<a [routerLink]="[ '/path' ]" [queryParams]="{ page: 1 }"> 
<a [routerLink]="[ '/path' ]" fragment="anchor"> | Creates a link to a different view based on a route instruction consisting of a route path, required and optional parameters, query parameters, and a fragment. To navigate to a root route, use the `/` prefix; for a child route, use the `./`prefix; for a sibling or parent, use the `../` prefix. |
+| <a [routerLink]="[ '/path' ]" routerLinkActive="active"> | The provided classes are added to the element when the `routerLink` becomes the current active route. |
+| class CanActivateGuard implements CanActivate { 
 canActivate( 
 route: ActivatedRouteSnapshot, 
 state: RouterStateSnapshot 
 ): Observable<boolean|UrlTree>|Promise<boolean|UrlTree>|boolean|UrlTree { … } 
} 
 
{ path: …, canActivate: [CanActivateGuard] } | An interface for defining a class that the router should call first to determine if it should activate this component. Should return a boolean|UrlTree
or an Observable/Promise that resolves to a boolean|UrlTree
. |
+| class CanDeactivateGuard implements CanDeactivate<T> { 
 canDeactivate( 
 component: T, 
 route: ActivatedRouteSnapshot, 
 state: RouterStateSnapshot 
 ): Observable<boolean|UrlTree>|Promise<boolean|UrlTree>|boolean|UrlTree { … } 
} 
 
{ path: …, canDeactivate: [CanDeactivateGuard] } | An interface for defining a class that the router should call first to determine if it should deactivate this component after a navigation. Should return a boolean|UrlTree
or an Observable/Promise that resolves to a boolean|UrlTree
. |
+| class CanActivateChildGuard implements CanActivateChild { 
 canActivateChild( 
 route: ActivatedRouteSnapshot, 
 state: RouterStateSnapshot 
 ): Observable<boolean|UrlTree>|Promise<boolean|UrlTree>|boolean|UrlTree { … } 
} 
 
{ path: …, canActivateChild: [CanActivateGuard], children: … } | An interface for defining a class that the router should call first to determine if it should activate the child route. Should return a boolean|UrlTree
or an Observable/Promise that resolves to a boolean|UrlTree
. |
+| class ResolveGuard implements Resolve<T> { 
 resolve( 
 route: ActivatedRouteSnapshot, 
 state: RouterStateSnapshot 
 ): Observable<any>|Promise<any>|any { … } 
} 
 
{ path: …, resolve: [ResolveGuard] } | An interface for defining a class that the router should call first to resolve route data before rendering the route. Should return a value or an Observable/Promise that resolves to a value. |
+| class CanLoadGuard implements CanLoad { 
 canLoad( 
 route: Route 
 ): Observable<boolean|UrlTree>|Promise<boolean|UrlTree>|boolean|UrlTree { … } 
} 
 
{ path: …, canLoad: [CanLoadGuard], loadChildren: … } | An interface for defining a class that the router should call first to check if the lazy loaded module should be loaded. Should return a boolean|UrlTree
or an Observable/Promise that resolves to a boolean|UrlTree
. |
-
-
-NgModules
-import { NgModule } from '@angular/core';
-
-
-
-
-@NgModule ({
- declarations: ..., imports: ..., exports: ...,
- providers: ..., bootstrap: ...
-})
-class MyModule {}
-
-Defines a module that contains components, directives, pipes, and providers.
-
-
-declarations: [MyRedComponent, MyBlueComponent, MyDatePipe]
-List of components, directives, and pipes that belong to this module.
-
-
-imports: [BrowserModule, SomeOtherModule]
-List of modules to import into this module. Everything from the imported modules
-is available to declarations
of this module.
-
-
-exports: [MyRedComponent, MyDatePipe]
-List of components, directives, and pipes visible to modules that import this module.
-
-
-providers: [MyService, { provide: ... }]
-List of dependency injection providers visible both to the contents of this module and to importers of this module.
-
-
-bootstrap: [MyAppComponent]
-List of components to bootstrap when this module is bootstrapped.
-
-
-
-
-
-
-Template syntax
-
-
-
-<input [value] ="firstName">
-Binds property value
to the result of expression firstName
.
-
-
-<div [attr.role] ="myAriaRole">
-Binds attribute role
to the result of expression myAriaRole
.
-
-
-<div [class.extra-sparkle] ="isDelightful">
-Binds the presence of the CSS class extra-sparkle
on the element to the truthiness of the expression isDelightful
.
-
-
-<div [style.width.px] ="mySize">
-Binds style property width
to the result of expression mySize
in pixels. Units are optional.
-
-
-<button (click) ="readRainbow($event)">
-Calls method readRainbow
when a click event is triggered on this button element (or its children) and passes in the event object.
-
-
-<div title="Hello {{ponyName}} ">
-Binds a property to an interpolated string, for example, "Hello Seabiscuit". Equivalent to:
-<div [title]="'Hello ' + ponyName">
-
-
-<p>Hello {{ponyName}} </p>
-Binds text content to an interpolated string, for example, "Hello Seabiscuit".
-
-
-<my-cmp [(title)] ="name">
-Sets up two-way data binding. Equivalent to: <my-cmp [title]="name" (titleChange)="name=$event">
-
-
-<video #movieplayer ...></video>
-<button (click) ="movieplayer.play()">Play</button>
-
-Creates a local variable movieplayer
that provides access to the video
element instance in data-binding and event-binding expressions in the current template.
-
-
-<p *myUnless ="myExpression">...</p>
-The *
symbol turns the current element into an embedded template. Equivalent to:
-<ng-template [myUnless]="myExpression"><p>...</p></ng-template>
-
-
-<p>Card No.: {{cardNumber | myCardNumberFormatter}} </p>
-Transforms the current value of expression cardNumber
using the pipe called myCardNumberFormatter
.
-
-
-<p>Employer: {{employer?.companyName}} </p>
-The safe navigation operator (?
) means that the employer
field is optional and if undefined
, the rest of the expression should be ignored.
-
-
-<svg: rect x="0" y="0" width="100" height="100"/>
-An SVG snippet template needs an svg:
prefix on its root element to disambiguate the SVG element from an HTML component.
-
-
-<svg >
- <rect x="0" y="0" width="100" height="100"/>
-</svg >
-
-An <svg>
root element is detected as an SVG element automatically, without the prefix.
-
-
-
-
-
-
-Built-in directives
-import { CommonModule } from '@angular/common';
-
-
-
-
-<section *ngIf ="showSection">
-Removes or recreates a portion of the DOM tree based on the showSection
expression.
-
-
-<li *ngFor ="let item of list">
-Turns the li element and its contents into a template, and uses that to instantiate a view for each item in list.
-
-
-<div [ngSwitch] ="conditionExpression">
- <ng-template [ngSwitchCase ] ="case1Exp">...</ng-template>
- <ng-template ngSwitchCase ="case2LiteralString">...</ng-template>
- <ng-template ngSwitchDefault >...</ng-template>
-</div>
-
-Conditionally swaps the contents of the div by selecting one of the embedded templates based on the current value of conditionExpression
.
-
-
-<div [ngClass] ="{'active': isActive, 'disabled': isDisabled}">
-Binds the presence of CSS classes on the element to the truthiness of the associated map values. The right-hand expression should return {class-name: true/false} map.
-
-
-
-<div [ngStyle] ="{'property': 'value'}">
-<div [ngStyle] ="dynamicStyles()">
-
-Allows you to assign styles to an HTML element using CSS. You can use CSS directly, as in the first example, or you can call a method from the component.
-
-
-
-
-
-
-Forms
-import { FormsModule } from '@angular/forms';
-
-
-
-
-<input [(ngModel)] ="userName">
-Provides two-way data-binding, parsing, and validation for form controls.
-
-
-
-
-
-
-Class decorators
-import { Directive, ... } from '@angular/core';
-
-
-
-
-@Component({...})
-class MyComponent() {}
-
-Declares that a class is a component and provides metadata about the component.
-
-
-@Directive({...})
-class MyDirective() {}
-
-Declares that a class is a directive and provides metadata about the directive.
-
-
-@Pipe({...})
-class MyPipe() {}
-
-Declares that a class is a pipe and provides metadata about the pipe.
-
-
-@Injectable()
-class MyService() {}
-
-Declares that a class can be provided and injected by other classes. Without this decorator, the compiler won't generate enough metadata to allow the class to be created properly when it's injected somewhere.
-
-
-
-
-
-
-Directive configuration
-@Directive({ property1: value1, ... })
-
-
-
-
-selector: '.cool-button:not(a)'
-Specifies a CSS selector that identifies this directive within a template. Supported selectors include element
,
-[attribute]
, .class
, and :not()
.
-Does not support parent-child relationship selectors.
-
-
-providers: [MyService, { provide: ... }]
-List of dependency injection providers for this directive and its children.
-
-
-
-
-
-
-Component configuration
-
-@Component
extends @Directive
,
-so the @Directive
configuration applies to components as well
-
-
-
-moduleId: module.id
-If set, the templateUrl
and styleUrl
are resolved relative to the component.
-
-
-viewProviders: [MyService, { provide: ... }]
-List of dependency injection providers scoped to this component's view.
-
-
-template: 'Hello {{name}}'
-templateUrl: 'my-component.html'
-
-Inline template or external template URL of the component's view.
-
-
-styles: ['.primary {color: red}']
-styleUrls: ['my-component.css']
-
-List of inline CSS styles or external stylesheet URLs for styling the component’s view.
-
-
-
-
-
-
-Class field decorators for directives and components
-import { Input, ... } from '@angular/core';
-
-
-
-
-@Input() myProperty;
-Declares an input property that you can update using property binding (example:
-<my-cmp [myProperty]="someExpression">
).
-
-
-@Output() myEvent = new EventEmitter();
-Declares an output property that fires events that you can subscribe to with an event binding (example: <my-cmp (myEvent)="doSomething()">
).
-
-
-@HostBinding('class.valid') isValid;
-Binds a host element property (here, the CSS class valid
) to a directive/component property (isValid
).
-
-
-@HostListener('click', ['$event']) onClick(e) {...}
-Subscribes to a host element event (click
) with a directive/component method (onClick
), optionally passing an argument ($event
).
-
-
-@ContentChild(myPredicate) myChildComponent;
-Binds the first result of the component content query (myPredicate
) to a property (myChildComponent
) of the class.
-
-
-@ContentChildren(myPredicate) myChildComponents;
-Binds the results of the component content query (myPredicate
) to a property (myChildComponents
) of the class.
-
-
-@ViewChild(myPredicate) myChildComponent;
-Binds the first result of the component view query (myPredicate
) to a property (myChildComponent
) of the class. Not available for directives.
-
-
-@ViewChildren(myPredicate) myChildComponents;
-Binds the results of the component view query (myPredicate
) to a property (myChildComponents
) of the class. Not available for directives.
-
-
-
-
-
-
-Directive and component change detection and lifecycle hooks
-(implemented as class methods)
-
-
-
-
-constructor(myService: MyService, ...) { ... }
-Called before any other lifecycle hook. Use it to inject dependencies, but avoid any serious work here.
-
-
-ngOnChanges(changeRecord) { ... }
-Called after every change to input properties and before processing content or child views.
-
-
-ngOnInit() { ... }
-Called after the constructor, initializing input properties, and the first call to ngOnChanges
.
-
-
-ngDoCheck() { ... }
-Called every time that the input properties of a component or a directive are checked. Use it to extend change detection by performing a custom check.
-
-
-ngAfterContentInit() { ... }
-Called after ngOnInit
when the component's or directive's content has been initialized.
-
-
-ngAfterContentChecked() { ... }
-Called after every check of the component's or directive's content.
-
-
-ngAfterViewInit() { ... }
-Called after ngAfterContentInit
when the component's views and child views / the view that a directive is in has been initialized.
-
-
-ngAfterViewChecked() { ... }
-Called after every check of the component's views and child views / the view that a directive is in.
-
-
-ngOnDestroy() { ... }
-Called once, before the instance is destroyed.
-
-
-
-
-
-
-Dependency injection configuration
-
-
-
-{ provide : MyService, useClass : MyMockService }
-Sets or overrides the provider for MyService
to the MyMockService
class.
-
-
-{ provide : MyService, useFactory : myFactory }
-Sets or overrides the provider for MyService
to the myFactory
factory function.
-
-
-{ provide : MyValue, useValue : 41 }
-Sets or overrides the provider for MyValue
to the value 41
.
-
-
-
-
-
-
-Routing and navigation
-import { Routes, RouterModule, ... } from '@angular/router';
-
-
-
-
-const routes: Routes = [
- { path: '', component: HomeComponent },
- { path: 'path/:routeParam', component: MyComponent },
- { path: 'staticPath', component: ... },
- { path: '**', component: ... },
- { path: 'oldPath', redirectTo: '/staticPath' },
- { path: ..., component: ..., data: { message: 'Custom' } }
-]);
-
-const routing = RouterModule.forRoot(routes);
-
-Configures routes for the application. Supports static, parameterized, redirect, and wildcard routes. Also supports custom route data and resolve.
-
-
-<router-outlet ></router-outlet >
-<router-outlet name="aux"></router-outlet >
-
-Marks the location to load the component of the active route.
-
-
-<a routerLink ="/path">
-<a [routerLink] ="[ '/path', routeParam ]">
-<a [routerLink] ="[ '/path', { matrixParam: 'value' } ]">
-<a [routerLink] ="[ '/path' ]" [queryParams]="{ page: 1 }">
-<a [routerLink] ="[ '/path' ]" fragment="anchor">
-
-Creates a link to a different view based on a route instruction consisting of a route path, required and optional parameters, query parameters, and a fragment. To navigate to a root route, use the /
prefix; for a child route, use the ./
prefix; for a sibling or parent, use the ../
prefix.
-
-
-<a [routerLink]="[ '/path' ]" routerLinkActive ="active">
-The provided classes are added to the element when the routerLink
becomes the current active route.
-
-
-class CanActivate Guard implements CanActivate {
- canActivate(
- route: ActivatedRouteSnapshot,
- state: RouterStateSnapshot
- ): Observable<boolean|UrlTree>|Promise<boolean|UrlTree>|boolean|UrlTree { ... }
-}
-
-{ path: ..., canActivate: [CanActivate Guard] }
-
-An interface for defining a class that the router should call first to determine if it should activate this component. Should return a boolean|UrlTree or an Observable/Promise that resolves to a boolean|UrlTree.
-
-
-class CanDeactivate Guard implements CanDeactivate <T> {
- canDeactivate(
- component: T,
- route: ActivatedRouteSnapshot,
- state: RouterStateSnapshot
- ): Observable<boolean|UrlTree>|Promise<boolean|UrlTree>|boolean|UrlTree { ... }
-}
-
-{ path: ..., canDeactivate: [CanDeactivate Guard] }
-
-An interface for defining a class that the router should call first to determine if it should deactivate this component after a navigation. Should return a boolean|UrlTree or an Observable/Promise that resolves to a boolean|UrlTree.
-
-
-class CanActivateChild Guard implements CanActivateChild {
- canActivateChild(
- route: ActivatedRouteSnapshot,
- state: RouterStateSnapshot
- ): Observable<boolean|UrlTree>|Promise<boolean|UrlTree>|boolean|UrlTree { ... }
-}
+
-{ path: ..., canActivateChild: [CanActivateGuard],
- children: ... }
-
-An interface for defining a class that the router should call first to determine if it should activate the child route. Should return a boolean|UrlTree or an Observable/Promise that resolves to a boolean|UrlTree.
-
-
-class Resolve Guard implements Resolve <T> {
- resolve(
- route: ActivatedRouteSnapshot,
- state: RouterStateSnapshot
- ): Observable<any>|Promise<any>|any { ... }
-}
+
-{ path: ..., resolve: [Resolve Guard] }
-
-An interface for defining a class that the router should call first to resolve route data before rendering the route. Should return a value or an Observable/Promise that resolves to a value.
-
-
-class CanLoad Guard implements CanLoad {
- canLoad(
- route: Route
- ): Observable<boolean|UrlTree>|Promise<boolean|UrlTree>|boolean|UrlTree { ... }
-}
+
-{ path: ..., canLoad: [CanLoad Guard], loadChildren: ... }
-
-An interface for defining a class that the router should call first to check if the lazy loaded module should be loaded. Should return a boolean|UrlTree or an Observable/Promise that resolves to a boolean|UrlTree.
-
-
-
+
-
+@reviewed 2022-02-28
diff --git a/aio/content/guide/cli-builder.md b/aio/content/guide/cli-builder.md
index aeeb8c8eb8dd1..3477e56baa101 100644
--- a/aio/content/guide/cli-builder.md
+++ b/aio/content/guide/cli-builder.md
@@ -3,33 +3,34 @@
A number of Angular CLI commands run a complex process on your code, such as linting, building, or testing.
The commands use an internal tool called Architect to run *CLI builders*, which apply another tool to accomplish the wanted task.
-With Angular version 8, the CLI Builder API is stable and available to developers who want to customize the Angular CLI by adding or modifying commands. For example, you could supply a builder to perform an entirely new task, or to change which third-party tool is used by an existing command.
+With Angular version 8, the CLI Builder API is stable and available to developers who want to customize the Angular CLI by adding or modifying commands.
+For example, you could supply a builder to perform an entirely new task, or to change which third-party tool is used by an existing command.
This document explains how CLI builders integrate with the workspace configuration file, and shows how you can create your own builder.
- Find the code from the examples used here in [this GitHub repository](https://github.com/mgechev/cli-builders-demo).
+Find the code from the examples used here in this [GitHub repository](https://github.com/mgechev/cli-builders-demo).
## CLI builders
The internal Architect tool delegates work to handler functions called [*builders*](guide/glossary#builder).
-A builder handler function receives two arguments; a set of input `options` (a JSON object), and a `context` (a `BuilderContext` object).
+A builder handler function receives two arguments; a set of input `options` \(a JSON object\), and a `context` \(a `BuilderContext` object\).
-The separation of concerns here is the same as with [schematics](guide/glossary#schematic), which are used for other CLI commands that touch your code (such as `ng generate`).
+The separation of concerns here is the same as with [schematics](guide/glossary#schematic), which are used for other CLI commands that touch your code \(such as `ng generate`\).
-* The `options` object is provided by the CLI user, while the `context` object is provided by the CLI Builder API.
+* The `options` object is provided by the CLI user, while the `context` object is provided by the CLI Builder API
+* In addition to the contextual information, the `context` object, which is an instance of the `BuilderContext`, also provides access to a scheduling method, `context.scheduleTarget()`.
+ The scheduler executes the builder handler function with a given [target configuration](guide/glossary#target).
-* In addition to the contextual information, the `context` object, which is an instance of the `BuilderContext`, also provides access to a scheduling method, `context.scheduleTarget()`. The scheduler executes the builder handler function with a given [target configuration](guide/glossary#target).
-
-The builder handler function can be synchronous (return a value) or asynchronous (return a Promise), or it can watch and return multiple values (return an Observable).
+The builder handler function can be synchronous \(return a value\) or asynchronous \(return a Promise\), or it can watch and return multiple values \(return an Observable\).
The return value or values must always be of type `BuilderOutput`.
This object contains a Boolean `success` field and an optional `error` field that can contain an error message.
Angular provides some builders that are used by the CLI for commands such as `ng build` and `ng test`.
-Default target configurations for these and other built-in CLI builders can be found (and customized) in the "architect" section of the [workspace configuration file](guide/workspace-config), `angular.json`.
+Default target configurations for these and other built-in CLI builders can be found \(and customized\) in the "architect" section of the [workspace configuration file](guide/workspace-config), `angular.json`.
Also, extend and customize Angular by creating your own builders, which you can run using the [`ng run` CLI command](cli/run).
### Builder project structure
@@ -37,20 +38,21 @@ Also, extend and customize Angular by creating your own builders, which you can
A builder resides in a "project" folder that is similar in structure to an Angular workspace, with global configuration files at the top level, and more specific configuration in a source folder with the code files that define the behavior.
For example, your `myBuilder` folder could contain the following files.
-| FILES | PURPOSE |
-| :----------------------- | :------------------------------------------|
-| `src/my-builder.ts` | Main source file for the builder definition. |
-| `src/my-builder.spec.ts` | Source file for tests. |
-| `src/schema.json` | Definition of builder input options. |
-| `builders.json` | Builders definition. |
-| `package.json` | Dependencies. See https://docs.npmjs.com/files/package.json. |
-| `tsconfig.json` | [TypeScript configuration](https://www.typescriptlang.org/docs/handbook/tsconfig-json.html). |
+| Files | Purpose |
+|:--- | :--- |
+| `src/my-builder.ts` | Main source file for the builder definition. |
+| `src/my-builder.spec.ts` | Source file for tests. |
+| `src/schema.json` | Definition of builder input options. |
+| `builders.json` | Builders definition. |
+| `package.json` | Dependencies. See [https://docs.npmjs.com/files/package.json](https://docs.npmjs.com/files/package.json). |
+| `tsconfig.json` | [TypeScript configuration](https://www.typescriptlang.org/docs/handbook/tsconfig-json.html). |
-Publish the builder to `npm` (see [Publishing your Library](guide/creating-libraries#publishing-your-library)). If you publish it as `@example/my-builder`, install it using the following command.
+Publish the builder to `npm` \(see [Publishing your Library](guide/creating-libraries#publishing-your-library)\).
+If you publish it as `@example/my-builder`, install it using the following command.
-
+
-npm install @example/my-builder
+npm install @example/my-builder
@@ -59,59 +61,48 @@ npm install @example/my-builder
As an example, create a builder that copies a file.
To create a builder, use the `createBuilder()` CLI Builder function, and return a `Promise` object.
-
-
+
-Now let’s add some logic to it. The following code retrieves the source and destination file paths
-from user options and copies the file from the source to the destination (using the
-[Promise version of the built-in NodeJS `copyFile()` function](https://nodejs.org/api/fs.html#fs_fspromises_copyfile_src_dest_mode)).
+Now let's add some logic to it.
+The following code retrieves the source and destination file paths from user options and copies the file from the source to the destination \(using the [Promise version of the built-in NodeJS `copyFile()` function](https://nodejs.org/api/fs.html#fs_fspromises_copyfile_src_dest_mode)\).
If the copy operation fails, it returns an error with a message about the underlying problem.
-
-
+
### Handling output
-By default, `copyFile()` does not print anything to the process standard output or error. If an
-error occurs, it might be difficult to understand exactly what the builder was trying to do when the
-problem occurred. Add some additional context by logging additional information using the
-`Logger` API. This also lets the builder itself be executed in a separate process, even if the
-standard output and error are deactivated (as in an [Electron app](https://electronjs.org/)).
+By default, `copyFile()` does not print anything to the process standard output or error.
+If an error occurs, it might be difficult to understand exactly what the builder was trying to do when the problem occurred.
+Add some additional context by logging additional information using the `Logger` API.
+This also lets the builder itself be executed in a separate process, even if the standard output and error are deactivated \(as in an [Electron app](https://electronjs.org)\).
You can retrieve a `Logger` instance from the context.
-
-
+
### Progress and status reporting
The CLI Builder API includes progress and status reporting tools, which can provide hints for certain functions and interfaces.
-To report progress, use the `context.reportProgress()` method, which takes a current value, (optional) total, and status string as arguments.
+To report progress, use the `context.reportProgress()` method, which takes a current value, \(optional\) total, and status string as arguments.
The total can be any number; for example, if you know how many files you have to process, the total could be the number of files, and current should be the number processed so far.
The status string is unmodified unless you pass in a new string value.
You can see an [example](https://github.com/angular/angular-cli/blob/ba21c855c0c8b778005df01d4851b5a2176edc6f/packages/angular_devkit/build_angular/src/tslint/index.ts#L107) of how the `tslint` builder reports progress.
-In our example, the copy operation either finishes or is still executing, so there’s no need for a progress report, but you can report status so that a parent builder that called our builder would know what’s going on.
+In our example, the copy operation either finishes or is still executing, so there's no need for a progress report, but you can report status so that a parent builder that called our builder would know what's going on.
Use the `context.reportStatus()` method to generate a status string of any length.
-(Note that there’s no guarantee that a long string will be shown entirely; it could be cut to fit the UI that displays it.)
+
+
+
+**NOTE**:
+There's no guarantee that a long string will be shown entirely; it could be cut to fit the UI that displays it.
+
+
+
Pass an empty string to remove the status.
-
-
+
## Builder input
@@ -122,16 +113,17 @@ In either case, you must provide required inputs, but can let other inputs defau
You define builder inputs in a JSON schema associated with that builder.
The Architect tool collects the resolved input values into an `options` object, and validates their types against the schema before passing them to the builder function.
-(The Schematics library does the same kind of validation of user input.)
+\(The Schematics library does the same kind of validation of user input.\)
-For our example builder, you expect the `options` value to be a `JsonObject` with two keys: a
-`source` and a `destination`, each of which are a string.
+For our example builder, you expect the `options` value to be a `JsonObject` with two keys:
+A `source` and a `destination`, each of which are a string.
You can provide the following schema for type validation of these values.
-
+
+
{
- "$schema": "http://json-schema.org/schema",
+ "$schema": "http://json-schema.org/schema",
"type": "object",
"properties": {
"source": {
@@ -148,7 +140,7 @@ You can provide the following schema for type validation of these values.
This is a very simple example, but the use of a schema for validation can be very powerful.
-For more information, see the [JSON schemas website](http://json-schema.org/).
+For more information, see the [JSON schemas website](http://json-schema.org).
@@ -156,7 +148,7 @@ To link our builder implementation with its schema and name, you need to create
Create a file named `builders.json` that looks like this:
-
+
{
"builders": {
@@ -172,31 +164,28 @@ Create a file named `builders.json` that looks like this:
In the `package.json` file, add a `builders` key that tells the Architect tool where to find our builder definition file.
-
+
{
- "name": "@example/copy-file",
+ "name": "@example/copy-file",
"version": "1.0.0",
"description": "Builder for copying files",
"builders": "builders.json",
"dependencies": {
- "@angular-devkit/architect": "~0.1200.0",
- "@angular-devkit/core": "^12.0.0"
+ "@angular-devkit/architect": "~0.1200.0",
+ "@angular-devkit/core": "^12.0.0"
}
}
The official name of our builder is now ` @example/copy-file:copy`.
-The first part of this is the package name (resolved using node resolution), and the second part is the builder name (resolved using the `builders.json` file).
+The first part of this is the package name \(resolved using node resolution\), and the second part is the builder name \(resolved using the `builders.json` file\).
-Using one of our `options` is very straightforward. You did this in the previous section when you accessed `options.source` and `options.destination`.
+Using one of our `options` is very straightforward.
+You did this in the previous section when you accessed `options.source` and `options.destination`.
-
-
+
### Target configuration
@@ -207,19 +196,19 @@ A target specifies the builder to use, its default options configuration, and na
The Architect tool uses the target definition to resolve input options for a given run.
The `angular.json` file has a section for each project, and the "architect" section of each project configures targets for builders used by CLI commands such as 'build', 'test', and 'lint'.
-By default, for example, the `build` command runs the builder @angular-devkit/build-angular:browser
to perform the build task, and passes in default option values as specified for the `build` target in `angular.json`.
+By default, for example, the `build` command runs the builder `@angular-devkit/build-angular:browser` to perform the build task, and passes in default option values as specified for the `build` target in `angular.json`.
-
+
{
"myApp": {
- ...
+ …
"architect": {
"build": {
- "builder": "@angular-devkit/build-angular:browser",
+ "builder": "@angular-devkit/build-angular:browser",
"options": {
"outputPath": "dist/myApp",
"index": "src/index.html",
- ...
+ …
},
"configurations": {
"production": {
@@ -231,11 +220,11 @@ By default, for example, the `build` command runs the builder
@@ -246,13 +235,19 @@ You might also add more alternative configurations to the `build` target, to def
#### Target strings
-The generic `ng run` CLI command takes as its first argument a target string of the form *project:target[:configuration]*.
+The generic `ng run` CLI command takes as its first argument a target string of the following form.
+
+
-* *project*: The name of the Angular CLI project that the target is associated with.
+project:target[:configuration]
-* *target*: A named builder configuration from the `architect` section of the `angular.json` file.
+
-* *configuration*: (optional) The name of a specific configuration override for the given target, as defined in the `angular.json` file.
+| | Details |
+|:--- |:--- |
+| project | The name of the Angular CLI project that the target is associated with. |
+| target | A named builder configuration from the `architect` section of the `angular.json` file. |
+| configuration | \(optional\) The name of a specific configuration override for the given target, as defined in the `angular.json` file. |
If your builder calls another builder, it might need to read a passed target string.
Parse this string into an object by using the `targetFromTargetString()` utility function from `@angular-devkit/architect`.
@@ -265,7 +260,7 @@ To invoke a builder, you schedule a task to be run when all configuration resolu
The builder function is not executed until the scheduler returns a `BuilderRun` control object.
The CLI typically schedules tasks by calling the `context.scheduleTarget()` function, and then resolves input options using the target definition in the `angular.json` file.
-Architect resolves input options for a given target by taking the default options object, then overwriting values from the configuration used (if any), then further overwriting values from the overrides object passed to `context.scheduleTarget()`.
+Architect resolves input options for a given target by taking the default options object, then overwriting values from the configuration used \(if any\), then further overwriting values from the overrides object passed to `context.scheduleTarget()`.
For the Angular CLI, the overrides object is built from command line arguments.
Architect validates the resulting options values against the schema of the builder.
@@ -275,41 +270,41 @@ For more information see [Workspace Configuration](guide/workspace-config).
- You can also invoke a builder directly from another builder or test by calling `context.scheduleBuilder()`.
- You pass an `options` object directly to the method, and those option values are validated against the schema of the builder without further adjustment.
+You can also invoke a builder directly from another builder or test by calling `context.scheduleBuilder()`.
+You pass an `options` object directly to the method, and those option values are validated against the schema of the builder without further adjustment.
- Only the `context.scheduleTarget()` method resolves the configuration and overrides through the `angular.json` file.
+Only the `context.scheduleTarget()` method resolves the configuration and overrides through the `angular.json` file.
### Default architect configuration
-Let’s create a simple `angular.json` file that puts target configurations into context.
+Let's create a simple `angular.json` file that puts target configurations into context.
-You can publish the builder to npm (see [Publishing your Library](guide/creating-libraries#publishing-your-library)), and install it using the following command:
+You can publish the builder to npm \(see [Publishing your Library](guide/creating-libraries#publishing-your-library)\), and install it using the following command:
-
+
-npm install @example/copy-file
+npm install @example/copy-file
If you create a new project with `ng new builder-test`, the generated `angular.json` file looks something like this, with only default builder configurations.
-
+
{
- // ...
+ // …
"projects": {
- // ...
+ // …
"builder-test": {
- // ...
+ // …
"architect": {
- // ...
+ // …
"build": {
- "builder": "@angular-devkit/build-angular:browser",
+ "builder": "@angular-devkit/build-angular:browser",
"options": {
- // ... more options...
+ // … more options…
"outputPath": "dist/builder-test",
"index": "src/index.html",
"main": "src/main.ts",
@@ -318,7 +313,7 @@ If you create a new project with `ng new builder-test`, the generated `angular.j
},
"configurations": {
"production": {
- // ... more options...
+ // … more options…
"optimization": true,
"aot": true,
"buildOptimizer": true
@@ -328,7 +323,7 @@ If you create a new project with `ng new builder-test`, the generated `angular.j
}
}
}
- // ...
+ // …
}
@@ -340,29 +335,28 @@ This target tells the builder to copy the `package.json` file.
You need to update the `angular.json` file to add a target for this builder to the "architect" section of our new project.
-* We'll add a new target section to the "architect" object for our project.
+* We'll add a new target section to the "architect" object for our project
+* The target named "copy-package" uses our builder, which you published to `@example/copy-file`.
+ \(See [Publishing your Library](guide/creating-libraries#publishing-your-library).\)
-* The target named "copy-package" uses our builder, which you published to `@example/copy-file`. (See [Publishing your Library](guide/creating-libraries#publishing-your-library))
+* The options object provides default values for the two inputs that you defined; `source`, which is the existing file you are copying, and `destination`, the path you want to copy to
+* The `configurations` key is optional, we'll leave it out for now
-* The options object provides default values for the two inputs that you defined; `source`, which is the existing file you are copying, and `destination`, the path you want to copy to.
-
-* The `configurations` key is optional, we'll leave it out for now.
-
-
+
{
"projects": {
"builder-test": {
"architect": {
"copy-package": {
- "builder": "@example/copy-file:copy",
+ "builder": "@example/copy-file:copy",
"options": {
"source": "package.json",
"destination": "package-copy.json"
}
},
"build": {
- "builder": "@angular-devkit/build-angular:browser",
+ "builder": "@angular-devkit/build-angular:browser",
"options": {
"outputPath": "dist/builder-test",
"index": "src/index.html",
@@ -395,7 +389,7 @@ You need to update the `angular.json` file to add a target for this builder to t
To run our builder with the new target's default configuration, use the following CLI command.
-
+
ng run builder-test:copy-package
@@ -406,69 +400,77 @@ This copies the `package.json` file to `package-copy.json`.
Use command-line arguments to override the configured defaults.
For example, to run with a different `destination` value, use the following CLI command.
-
+
ng run builder-test:copy-package --destination=package-other.json
This copies the file to `package-other.json` instead of `package-copy.json`.
-Because you did not override the *source* option, it will copy from the `package.json` file (the default value provided for the target).
+Because you did not override the *source* option, it will copy from the `package.json` file \(the default value provided for the target\).
## Testing a builder
Use integration testing for your builder, so that you can use the Architect scheduler to create a context, as in this [example](https://github.com/mgechev/cli-builders-demo).
-* In the builder source directory, you have created a new test file `my-builder.spec.ts`. The code creates new instances of `JsonSchemaRegistry` (for schema validation), `TestingArchitectHost` (an in-memory implementation of `ArchitectHost`), and `Architect`.
+* In the builder source directory, you have created a new test file `my-builder.spec.ts`.
+ The code creates new instances of `JsonSchemaRegistry` \(for schema validation\), `TestingArchitectHost` \(an in-memory implementation of `ArchitectHost`\), and `Architect`.
-* We've added a `builders.json` file next to the builder's `package.json` file, and modified the package file to point to it.
+* We've added a `builders.json` file next to the builder's `package.json` file, and modified the package file to point to it.
-Here’s an example of a test that runs the copy file builder.
+Here's an example of a test that runs the copy file builder.
The test uses the builder to copy the `package.json` file and validates that the copied file's contents are the same as the source.
-
-
+
- When running this test in your repo, you need the [`ts-node`](https://github.com/TypeStrong/ts-node) package. You can avoid this by renaming `my-builder.spec.ts` to `my-builder.spec.js`.
+When running this test in your repo, you need the [`ts-node`](https://github.com/TypeStrong/ts-node) package.
+You can avoid this by renaming `my-builder.spec.ts` to `my-builder.spec.js`.
### Watch mode
-Architect expects builders to run once (by default) and return.
-This behavior is not entirely compatible with a builder that watches for changes (like Webpack, for example).
+Architect expects builders to run once \(by default\) and return.
+This behavior is not entirely compatible with a builder that watches for changes \(like Webpack, for example\).
Architect can support watch mode, but there are some things to look out for.
-* To be used with watch mode, a builder handler function should return an Observable. Architect subscribes to the Observable until it completes and might reuse it if the builder is scheduled again with the same arguments.
+* To be used with watch mode, a builder handler function should return an Observable.
+ Architect subscribes to the Observable until it completes and might reuse it if the builder is scheduled again with the same arguments.
-* The builder should always emit a `BuilderOutput` object after each execution. Once it’s been executed, it can enter a watch mode, to be triggered by an external event. If an event triggers it to restart, the builder should execute the `context.reportRunning()` function to tell Architect that it is running again. This prevents Architect from stopping the builder if another run is scheduled.
+* The builder should always emit a `BuilderOutput` object after each execution.
+ Once it's been executed, it can enter a watch mode, to be triggered by an external event.
+ If an event triggers it to restart, the builder should execute the `context.reportRunning()` function to tell Architect that it is running again.
+ This prevents Architect from stopping the builder if another run is scheduled.
-When your builder calls `BuilderRun.stop()` to exit watch mode, Architect unsubscribes from the builder’s Observable and calls the builder’s teardown logic to clean up.
-(This behavior also allows for long running builds to be stopped and cleaned up.)
+When your builder calls `BuilderRun.stop()` to exit watch mode, Architect unsubscribes from the builder's Observable and calls the builder's teardown logic to clean up.
+\(This behavior also allows for long running builds to be stopped and cleaned up.\)
In general, if your builder is watching an external event, you should separate your run into three phases.
-1. **Running**
- For example, webpack compiles. This ends when webpack finishes and your builder emits a `BuilderOutput` object.
-
-1. **Watching**
- Between two runs, watch an external event stream. For example, webpack watches the file system for any changes. This ends when webpack restarts building, and `context.reportRunning()` is called. This goes back to step 1.
-
-1. **Completion**
- Either the task is fully completed (for example, webpack was supposed to run a number of times), or the builder run was stopped (using `BuilderRun.stop()`). Your teardown logic is executed, and Architect unsubscribes from your builder’s Observable.
+| Phases | Details |
+|:--- |:--- |
+| Running | For example, webpack compiles. This ends when webpack finishes and your builder emits a `BuilderOutput` object. |
+| Watching | Between two runs, watch an external event stream. For example, webpack watches the file system for any changes. This ends when webpack restarts building, and `context.reportRunning()` is called. This goes back to step 1. |
+| Completion | Either the task is fully completed \(for example, webpack was supposed to run a number of times\), or the builder run was stopped \(using `BuilderRun.stop()`\). Your teardown logic is executed, and Architect unsubscribes from your builder's Observable. |
## Summary
The CLI Builder API provides a new way of changing the behavior of the Angular CLI by using builders to execute custom logic.
-* Builders can be synchronous or asynchronous, execute once or watch for external events, and can schedule other builders or targets.
+* Builders can be synchronous or asynchronous, execute once or watch for external events, and can schedule other builders or targets
+* Builders have option defaults specified in the `angular.json` configuration file, which can be overwritten by an alternate configuration for the target, and further overwritten by command line flags
+
+* We recommend that you use integration tests to test Architect builders.
+ Use unit tests to validate the logic that the builder executes.
+
+* If your builder returns an Observable, it should clean up in the teardown logic of that Observable
+
+
-* Builders have option defaults specified in the `angular.json` configuration file, which can be overwritten by an alternate configuration for the target, and further overwritten by command line flags.
+
-* We recommend that you use integration tests to test Architect builders. Use unit tests to validate the logic that the builder executes.
+
-* If your builder returns an Observable, it should clean up in the teardown logic of that Observable.
+@reviewed 2022-02-28
diff --git a/aio/content/guide/comparing-observables.md b/aio/content/guide/comparing-observables.md
index 227d364bcddab..244f5806dac2d 100644
--- a/aio/content/guide/comparing-observables.md
+++ b/aio/content/guide/comparing-observables.md
@@ -1,318 +1,129 @@
# Observables compared to other techniques
-You can often use observables instead of promises to deliver values asynchronously. Similarly, observables can take the place of event handlers. Finally, because observables deliver multiple values, you can use them where you might otherwise build and operate on arrays.
+You can often use observables instead of promises to deliver values asynchronously.
+Similarly, observables can take the place of event handlers.
+Finally, because observables deliver multiple values, you can use them where you might otherwise build and operate on arrays.
-Observables behave somewhat differently from the alternative techniques in each of these situations, but offer some significant advantages. Here are detailed comparisons of the differences.
+Observables behave somewhat differently from the alternative techniques in each of these situations, but offer some significant advantages.
+Here are detailed comparisons of the differences.
## Observables compared to promises
-Observables are often compared to promises. Here are some key differences:
+Observables are often compared to promises.
+Here are some key differences:
-* Observables are declarative; computation does not start until subscription. Promises execute immediately on creation. This makes observables useful for defining recipes that can be run whenever you need the result.
+* Observables are declarative; computation does not start until subscription.
+ Promises execute immediately on creation.
+ This makes observables useful for defining recipes that can be run whenever you need the result.
-* Observables provide many values. Promises provide one. This makes observables useful for getting multiple values over time.
+* Observables provide many values.
+ Promises provide one.
+ This makes observables useful for getting multiple values over time.
-* Observables differentiate between chaining and subscription. Promises only have `.then()` clauses. This makes observables useful for creating complex transformation recipes to be used by other part of the system, without causing the work to be executed.
-
-* Observables `subscribe()` is responsible for handling errors. Promises push errors to the child promises. This makes observables useful for centralized and predictable error handling.
+* Observables differentiate between chaining and subscription.
+ Promises only have `.then()` clauses.
+ This makes observables useful for creating complex transformation recipes to be used by other part of the system, without causing the work to be executed.
+* Observables `subscribe()` is responsible for handling errors.
+ Promises push errors to the child promises.
+ This makes observables useful for centralized and predictable error handling.
### Creation and subscription
-* Observables are not executed until a consumer subscribes. The `subscribe()` executes the defined behavior once, and it can be called again. Each subscription has its own computation. Resubscription causes recomputation of values.
+* Observables are not executed until a consumer subscribes.
+ The `subscribe()` executes the defined behavior once, and it can be called again.
+ Each subscription has its own computation.
+ Resubscription causes recomputation of values.
-
-
+
-* Promises execute immediately, and just once. The computation of the result is initiated when the promise is created. There is no way to restart work. All `then` clauses (subscriptions) share the same computation.
+* Promises execute immediately, and just once.
+ The computation of the result is initiated when the promise is created.
+ There is no way to restart work.
+ All `then` clauses \(subscriptions\) share the same computation.
-
-
+
### Chaining
-* Observables differentiate between transformation function such as a map and subscription. Only subscription activates the subscriber function to start computing the values.
+* Observables differentiate between transformation function such as a map and subscription.
+ Only subscription activates the subscriber function to start computing the values.
-
-
+
-* Promises do not differentiate between the last `.then` clauses (equivalent to subscription) and intermediate `.then` clauses (equivalent to map).
+* Promises do not differentiate between the last `.then` clauses \(equivalent to subscription\) and intermediate `.then` clauses \(equivalent to map\).
-
-
+
### Cancellation
-* Observable subscriptions are cancellable. Unsubscribing removes the listener from receiving further values, and notifies the subscriber function to cancel work.
+* Observable subscriptions are cancellable.
+ Unsubscribing removes the listener from receiving further values, and notifies the subscriber function to cancel work.
-
-
+
-* Promises are not cancellable.
+* Promises are not cancellable.
### Error handling
-* Observable execution errors are delivered to the subscriber's error handler, and the subscriber automatically unsubscribes from the observable.
+* Observable execution errors are delivered to the subscriber's error handler, and the subscriber automatically unsubscribes from the observable.
-
-
+
-* Promises push errors to the child promises.
+* Promises push errors to the child promises.
-
-
+
### Cheat sheet
The following code snippets illustrate how the same kind of operation is defined using observables and promises.
-
-
-
- Operation
- Observable
- Promise
-
-
-
-
- Creation
-
-
-new Observable((observer) => {
- observer.next(123);
-});
-
-
-
-new Promise((resolve, reject) => {
- resolve(123);
-});
-
-
-
- Transform
- obs.pipe(map((value) => value * 2));
- promise.then((value) => value * 2);
-
-
- Subscribe
-
-
-sub = obs.subscribe((value) => {
- console.log(value)
-});
-
-
-
-promise.then((value) => {
- console.log(value);
-});
-
-
-
- Unsubscribe
- sub.unsubscribe();
- Implied by promise resolution.
-
-
-
+| Operation | Observable | Promise |
+|:--- |:--- |:--- |
+| Creation | new Observable((observer) => { 
 observer.next(123); 
}); | new Promise((resolve, reject) => { 
 resolve(123); 
}); |
+| Transform | obs.pipe(map((value) => value * 2)); | promise.then((value) => value * 2); |
+| Subscribe | sub = obs.subscribe((value) => { 
 console.log(value) 
}); | promise.then((value) => { 
 console.log(value); 
}); |
+| Unsubscribe | sub.unsubscribe(); | Implied by promise resolution. |
## Observables compared to events API
-Observables are very similar to event handlers that use the events API. Both techniques define notification handlers, and use them to process multiple values delivered over time. Subscribing to an observable is equivalent to adding an event listener. One significant difference is that you can configure an observable to transform an event before passing the event to the handler.
+Observables are very similar to event handlers that use the events API.
+Both techniques define notification handlers, and use them to process multiple values delivered over time.
+Subscribing to an observable is equivalent to adding an event listener.
+One significant difference is that you can configure an observable to transform an event before passing the event to the handler.
Using observables to handle events and asynchronous operations can have the advantage of greater consistency in contexts such as HTTP requests.
Here are some code samples that illustrate how the same kind of operation is defined using observables and the events API.
-
-
-
- Observable
- Events API
-
-
- Creation & cancellation
-
-// Setup
-const clicks$ = fromEvent(buttonEl, ‘click’);
-// Begin listening
-const subscription = clicks$
- .subscribe(e => console.log(‘Clicked’, e))
-// Stop listening
-subscription.unsubscribe();
-
-
-function handler(e) {
- console.log(‘Clicked’, e);
-}
-// Setup & begin listening
-button.addEventListener(‘click’, handler);
-// Stop listening
-button.removeEventListener(‘click’, handler);
-
-
-
-
- Subscription
-
-observable.subscribe(() => {
- // notification handlers here
-});
-
-
-element.addEventListener(eventName, (event) => {
- // notification handler here
-});
-
-
-
- Configuration
- Listen for keystrokes, but provide a stream representing the value in the input.
-fromEvent(inputEl, 'keydown').pipe(
- map(e => e.target.value)
-);
-
- Does not support configuration.
-element.addEventListener(eventName, (event) => {
- // Cannot change the passed Event into another
- // value before it gets to the handler
-});
-
-
-
-
+| | Observable | Events API |
+|:--- |:--- |:--- |
+| Creation & cancellation | // Setup 
const clicks$ = fromEvent(buttonEl, 'click'); 
// Begin listening 
const subscription = clicks$ 
 .subscribe(e => console.log('Clicked', e)) 
// Stop listening 
subscription.unsubscribe(); | function handler(e) { 
 console.log('Clicked', e); 
} 
// Setup & begin listening 
button.addEventListener('click', handler); 
// Stop listening 
button.removeEventListener('click', handler); |
+| Subscription | observable.subscribe(() => { 
 // notification handlers here 
}); | element.addEventListener(eventName, (event) => { 
 // notification handler here 
}); |
+| Configuration | Listen for keystrokes, but provide a stream representing the value in the input. fromEvent(inputEl, 'keydown').pipe( 
 map(e => e.target.value) 
); | Does not support configuration. element.addEventListener(eventName, (event) => { 
 // Cannot change the passed Event into another 
 // value before it gets to the handler 
}); |
## Observables compared to arrays
-An observable produces values over time. An array is created as a static set of values. In a sense, observables are asynchronous where arrays are synchronous. In the following examples, ➞ implies asynchronous value delivery.
-
-
-
-
- Observable
- Array
-
-
- Given
-
- obs: ➞1➞2➞3➞5➞7
- obsB: ➞'a'➞'b'➞'c'
-
-
- arr: [1, 2, 3, 5, 7]
- arrB: ['a', 'b', 'c']
-
-
-
- concat()
-
- concat(obs, obsB)
- ➞1➞2➞3➞5➞7➞'a'➞'b'➞'c'
-
-
- arr.concat(arrB)
- [1,2,3,5,7,'a','b','c']
-
-
-
- filter()
-
- obs.pipe(filter((v) => v>3))
- ➞5➞7
-
-
- arr.filter((v) => v>3)
- [5, 7]
-
-
-
- find()
-
- obs.pipe(find((v) => v>3))
- ➞5
-
-
- arr.find((v) => v>3)
- 5
-
-
-
- findIndex()
-
- obs.pipe(findIndex((v) => v>3))
- ➞3
-
-
- arr.findIndex((v) => v>3)
- 3
-
-
-
- forEach()
-
- obs.pipe(tap((v) => {
- console.log(v);
-}))
-1
-2
-3
-5
-7
-
-
- arr.forEach((v) => {
- console.log(v);
-})
-1
-2
-3
-5
-7
-
-
-
- map()
-
- obs.pipe(map((v) => -v))
- ➞-1➞-2➞-3➞-5➞-7
-
-
- arr.map((v) => -v)
- [-1, -2, -3, -5, -7]
-
-
-
- reduce()
-
- obs.pipe(reduce((s,v)=> s+v, 0))
- ➞18
-
-
- arr.reduce((s,v) => s+v, 0)
- 18
-
-
-
+An observable produces values over time.
+An array is created as a static set of values.
+In a sense, observables are asynchronous where arrays are synchronous.
+In the following examples, →
implies asynchronous value delivery.
+
+| Values | Observable | Array |
+|:--- |:--- |:--- |
+| Given | obs: →1→2→3→5→7 obsB: →'a'→'b'→'c' | arr: [1, 2, 3, 5, 7] arrB: ['a', 'b', 'c'] |
+| `concat()` | concat(obs, obsB) →1→2→3→5→7→'a'→'b'→'c' | arr.concat(arrB) [1,2,3,5,7,'a','b','c'] |
+| `filter()` | obs.pipe(filter((v) => v>3)) →5→7 | arr.filter((v) => v>3) [5, 7] |
+| `find()` | obs.pipe(find((v) => v>3)) →5 | arr.find((v) => v>3) 5 |
+| `findIndex()` | obs.pipe(findIndex((v) => v>3)) →3 | arr.findIndex((v) => v>3) 3 |
+| `forEach()` | obs.pipe(tap((v) => { 
 console.log(v); 
 })) 
 1 
 2 
 3 
 5 
 7 | arr.forEach((v) => { 
 console.log(v); 
 }) 
 1 
 2 
 3 
 5 
 7 |
+| `map()` | obs.pipe(map((v) => -v)) →-1→-2→-3→-5→-7 | arr.map((v) => -v) [-1, -2, -3, -5, -7] |
+| `reduce()` | obs.pipe(reduce((s,v)=> s+v, 0)) →18 | arr.reduce((s,v) => s+v, 0) 18 |
+
+
+
+
+
+
+
+@reviewed 2022-02-28
diff --git a/aio/content/guide/complex-animation-sequences.md b/aio/content/guide/complex-animation-sequences.md
index eee10fad75b59..66be5416f8250 100644
--- a/aio/content/guide/complex-animation-sequences.md
+++ b/aio/content/guide/complex-animation-sequences.md
@@ -1,47 +1,52 @@
# Complex animation sequences
-#### Prerequisites
+## Prerequisites
A basic understanding of the following concepts:
-* [Introduction to Angular animations](guide/animations)
-* [Transition and triggers](guide/transition-and-triggers)
+* [Introduction to Angular animations](guide/animations)
+* [Transition and triggers](guide/transition-and-triggers)
-
-
-So far, we've learned simple animations of single HTML elements. Angular also lets you animate coordinated sequences, such as an entire grid or list of elements as they enter and leave a page. You can choose to run multiple animations in parallel, or run discrete animations sequentially, one following another.
+So far, we've learned simple animations of single HTML elements.
+Angular also lets you animate coordinated sequences, such as an entire grid or list of elements as they enter and leave a page.
+You can choose to run multiple animations in parallel, or run discrete animations sequentially, one following another.
The functions that control complex animation sequences are:
-* `query()` finds one or more inner HTML elements.
-* `stagger()` applies a cascading delay to animations for multiple elements.
-* [group](api/animations/group)()
runs multiple animation steps in parallel.
-* `sequence()` runs animation steps one after another.
+| Functions | Details |
+|:--- |:--- |
+| `query()` | Finds one or more inner HTML elements. |
+| `stagger()` | Applies a cascading delay to animations for multiple elements. |
+| [`group()`](api/animations/group) | Runs multiple animation steps in parallel. |
+| `sequence()` | Runs animation steps one after another. |
-{@a complex-sequence}
+
## The query() function
Most complex animations rely on the `query()` function to find child elements and apply animations to them, basic examples of such are:
- - `query()` followed by `animate()`
- used to query simple HTML elements and directly apply animations to them.
- - `query()` followed by `animateChild()`
- used to query child elements which themselves have animations metadata applied to them and trigger such animation (which would be otherwise be blocked by the current/parent element's animation)
-The first argument of `query()` is a [css selector](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Selectors) string which can also contain the following angular-specific tokens:
- - `:enter`/`:leave` for entering/leaving elements
- - `:animating` for elements currently animating
- - `@*`/`@triggerName` for elements with any or a specific trigger
- - `:self` the animating element itself
+| Examples | Details |
+|:--- |:--- |
+| `query()` followed by `animate()` | Used to query simple HTML elements and directly apply animations to them. |
+| `query()` followed by `animateChild()` | Used to query child elements, which themselves have animations metadata applied to them and trigger such animation \(which would be otherwise be blocked by the current/parent element's animation\). |
-
+The first argument of `query()` is a [css selector](https://developer.mozilla.org/docs/Web/CSS/CSS_Selectors) string which can also contain the following Angular-specific tokens:
-
Entering and Leaving Elements
+| Tokens | Details |
+|:--- |:--- |
+| `:enter`
`:leave` | For entering/leaving elements. |
+| `:animating` | For elements currently animating. |
+| `@*`
`@triggerName` | For elements with any —or a specific—trigger. |
+| `:self` | The animating element itself. |
+
+
- Not all child elements are actually considered as entering/leaving, this can at times be counterintuitive and confusing, please see the [query api docs](/api/animations/query#entering-and-leaving-elements) for more information.
+Entering and Leaving Elements
+Not all child elements are actually considered as entering/leaving; this can, at times, be counterintuitive and confusing. Please see the [query api docs](api/animations/query#entering-and-leaving-elements) for more information.
- You can also see an illustration of this in the animations live example (introduced in the animations [introduction section](/guide/animations#about-this-guide)) under the Querying tab.
+You can also see an illustration of this in the animations live example \(introduced in the animations [introduction section](guide/animations#about-this-guide)\) under the Querying tab.
@@ -49,87 +54,108 @@ The first argument of `query()` is a [css selector](https://developer.mozilla.or
After having queried child elements via `query()`, the `stagger()` function lets you define a timing gap between each queried item that is animated and thus animates elements with a delay between them.
-The following example demonstrates how to use the `query()` and `stagger()` functions to animate a list (of heroes) adding each in sequence, with a slight delay, from top to bottom.
+The following example demonstrates how to use the `query()` and `stagger()` functions to animate a list \(of heroes\) adding each in sequence, with a slight delay, from top to bottom.
-* Use `query()` to look for an element entering the page that meets certain criteria.
+* Use `query()` to look for an element entering the page that meets certain criteria
+* For each of these elements, use `style()` to set the same initial style for the element.
+ Make it transparent and use `transform` to move it out of position so that it can slide into place.
-* For each of these elements, use `style()` to set the same initial style for the element. Make it transparent and use `transform` to move it out of position so that it can slide into place.
+* Use `stagger()` to delay each animation by 30 milliseconds
+* Animate each element on screen for 0.5 seconds using a custom-defined easing curve, simultaneously fading it in and un-transforming it
-* Use `stagger()` to delay each animation by 30 milliseconds.
-
-* Animate each element on screen for 0.5 seconds using a custom-defined easing curve, simultaneously fading it in and un-transforming it.
-
-
+
## Parallel animation using group() function
-You've seen how to add a delay between each successive animation. But you might also want to configure animations that happen in parallel. For example, you might want to animate two CSS properties of the same element but use a different `easing` function for each one. For this, you can use the animation
[group](api/animations/group)()
function.
+You've seen how to add a delay between each successive animation.
+But you might also want to configure animations that happen in parallel.
+For example, you might want to animate two CSS properties of the same element but use a different `easing` function for each one.
+For this, you can use the animation [`group()`](api/animations/group) function.
-**Note:** The [group](api/animations/group)()
function is used to group animation *steps*, rather than animated elements.
+**NOTE**:
+The [`group()`](api/animations/group) function is used to group animation *steps*, rather than animated elements.
+
-The following example, uses
[group](api/animations/group)()
s on both `:enter` and `:leave` for two different timing configurations, thus applying two independent animations to the same element in parallel.
+The following example uses [`group()`](api/animations/group)s on both `:enter` and `:leave` for two different timing configurations, thus applying two independent animations to the same element in parallel.
-
+
## Sequential vs. parallel animations
-Complex animations can have many things happening at once. But what if you want to create an animation involving several animations happening one after the other? Earlier you used
[group](api/animations/group)()
to run multiple animations all at the same time, in parallel.
+Complex animations can have many things happening at once.
+But what if you want to create an animation involving several animations happening one after the other? Earlier you used [`group()`](api/animations/group) to run multiple animations all at the same time, in parallel.
-A second function called `sequence()` lets you run those same animations one after the other. Within `sequence()`, the animation steps consist of either `style()` or `animate()` function calls.
+A second function called `sequence()` lets you run those same animations one after the other.
+Within `sequence()`, the animation steps consist of either `style()` or `animate()` function calls.
-* Use `style()` to apply the provided styling data immediately.
-* Use `animate()` to apply styling data over a given time interval.
+* Use `style()` to apply the provided styling data immediately.
+* Use `animate()` to apply styling data over a given time interval.
## Filter animation example
-Take a look at another animation on the live example page. Under the Filter/Stagger tab, enter some text into the **Search Heroes** text box, such as `Magnet` or `tornado`.
+Take a look at another animation on the live example page.
+Under the Filter/Stagger tab, enter some text into the **Search Heroes** text box, such as `Magnet` or `tornado`.
-The filter works in real time as you type. Elements leave the page as you type each new letter and the filter gets progressively stricter. The heroes list gradually re-enters the page as you delete each letter in the filter box.
+The filter works in real time as you type.
+Elements leave the page as you type each new letter and the filter gets progressively stricter.
+The heroes list gradually re-enters the page as you delete each letter in the filter box.
The HTML template contains a trigger called `filterAnimation`.
-
+
The `filterAnimation` in the component's decorator contains three transitions.
-
+
The code in this example performs the following tasks:
-* Skips animations when the user first opens or navigates to this page (the filter animation narrows what is already there, so it only works on elements that already exist in the DOM).
-
-* Filters heroes based on the search input's value.
+* Skips animations when the user first opens or navigates to this page \(the filter animation narrows what is already there, so it only works on elements that already exist in the DOM\)
+* Filters heroes based on the search input's value
For each change:
-* Hides an element leaving the DOM by setting its opacity and width to 0.
-
-* Animates an element entering the DOM over 300 milliseconds. During the animation, the element assumes its default width and opacity.
+* Hides an element leaving the DOM by setting its opacity and width to 0
+* Animates an element entering the DOM over 300 milliseconds.
+ During the animation, the element assumes its default width and opacity.
-* If there are multiple elements entering or leaving the DOM, staggers each animation starting at the top of the page, with a 50-millisecond delay between each element.
+* If there are multiple elements entering or leaving the DOM, staggers each animation starting at the top of the page, with a 50-millisecond delay between each element
## Animating the items of a reordering list
-Although Angular animates correctly `*ngFor` list items out of the box, it will not be able to do so if their ordering changes. This is because it will lose track of which element is which, resulting in broken animations. The only way to help Angular keep track of such elements is by assigning a `TrackByFunction` to the `NgForOf` directive. This makes sure that Angular always knows which element is which, thus allowing it to apply the correct animations to the correct elements all the time.
+Although Angular animates correctly `*ngFor` list items out of the box, it will not be able to do so if their ordering changes.
+This is because it will lose track of which element is which, resulting in broken animations.
+The only way to help Angular keep track of such elements is by assigning a `TrackByFunction` to the `NgForOf` directive.
+This makes sure that Angular always knows which element is which, thus allowing it to apply the correct animations to the correct elements all the time.
-**Rule of Thumb:** If you need to animate the items of an `*ngFor` list and there is a possibility that the order of such items will change during runtime, always use a `TrackByFunction`.
+**IMPORTANT**:
+If you need to animate the items of an `*ngFor` list and there is a possibility that the order of such items will change during runtime, always use a `TrackByFunction`.
## Animation sequence summary
-Angular functions for animating multiple elements start with `query()` to find inner elements; for example, gathering all images within a `
`. The remaining functions, `stagger()`,
[group](api/animations/group)()
, and `sequence()`, apply cascades or lets you control how multiple animation steps are applied.
+Angular functions for animating multiple elements start with `query()` to find inner elements; for example, gathering all images within a `
`.
+The remaining functions, `stagger()`, [`group()`](api/animations/group), and `sequence()`, apply cascades or let you control how multiple animation steps are applied.
## More on Angular animations
You might also be interested in the following:
-* [Introduction to Angular animations](guide/animations)
-* [Transition and triggers](guide/transition-and-triggers)
-* [Reusable animations](guide/reusable-animations)
-* [Route transition animations](guide/route-animations)
+* [Introduction to Angular animations](guide/animations)
+* [Transition and triggers](guide/transition-and-triggers)
+* [Reusable animations](guide/reusable-animations)
+* [Route transition animations](guide/route-animations)
+
+
+
+
+
+
+
+@reviewed 2022-02-28
diff --git a/aio/content/guide/component-interaction.md b/aio/content/guide/component-interaction.md
index 0d71a945f5cb0..e47b7b75ce9dd 100644
--- a/aio/content/guide/component-interaction.md
+++ b/aio/content/guide/component-interaction.md
@@ -1,348 +1,230 @@
# Component interaction
-{@a top}
+
-This cookbook contains recipes for common component communication scenarios
-in which two or more components share information.
-{@a toc}
+This cookbook contains recipes for common component communication scenarios in which two or more components share information.
-
**See the
**.
-{@a parent-to-child}
+
## Pass data from parent to child with input binding
-`HeroChildComponent` has two ***input properties***,
-typically adorned with [@Input() decorator](guide/inputs-outputs#input).
-
-
-
-
-
-
+`HeroChildComponent` has two ***input properties***, typically adorned with [@Input() decorator](guide/inputs-outputs#input).
+
The second `@Input` aliases the child component property name `masterName` as `'master'`.
-The `HeroParentComponent` nests the child `HeroChildComponent` inside an `*ngFor` repeater,
-binding its `master` string property to the child's `master` alias,
-and each iteration's `hero` instance to the child's `hero` property.
-
-
-
-
-
-
+The `HeroParentComponent` nests the child `HeroChildComponent` inside an `*ngFor` repeater, binding its `master` string property to the child's `master` alias, and each iteration's `hero` instance to the child's `hero` property.
+
The running application displays three heroes:
-
-
-
+
+
-
Test it
+### Test it for Pass data from parent to child with input binding
E2E test that all children were instantiated and displayed as expected:
-
-
-
-
-
-
+
[Back to top](guide/component-interaction#top)
-{@a parent-to-child-setter}
+
## Intercept input property changes with a setter
Use an input property setter to intercept and act upon a value from the parent.
-The setter of the `name` input property in the child `NameChildComponent`
-trims the whitespace from a name and replaces an empty value with default text.
-
-
-
-
-
-
+The setter of the `name` input property in the child `NameChildComponent` trims the whitespace from a name and replaces an empty value with default text.
+
Here's the `NameParentComponent` demonstrating name variations including a name with all spaces:
-
-
-
-
-
-
+
-
-
+
+
-
Test it
+### Test it for Intercept input property changes with a setter
E2E tests of input property setter with empty and non-empty names:
-
-
-
-
-
-
+
[Back to top](guide/component-interaction#top)
-{@a parent-to-child-on-changes}
+
-## Intercept input property changes with *ngOnChanges()*
+## Intercept input property changes with `ngOnChanges()`
Detect and act upon changes to input property values with the `ngOnChanges()` method of the `OnChanges` lifecycle hook interface.
-
-
You might prefer this approach to the property setter when watching multiple, interacting input properties.
Learn about `ngOnChanges()` in the [Lifecycle Hooks](guide/lifecycle-hooks) chapter.
-
-
This `VersionChildComponent` detects changes to the `major` and `minor` input properties and composes a log message reporting these changes:
-
-
-
-
-
-
+
The `VersionParentComponent` supplies the `minor` and `major` values and binds buttons to methods that change them.
-
-
-
-
-
-
+
Here's the output of a button-pushing sequence:
-
-
-
-
-
-
-
Test it
-
-Test that ***both*** input properties are set initially and that button clicks trigger
-the expected `ngOnChanges` calls and values:
+
-
+
-
+### Test it for Intercept input property changes with `ngOnChanges()`
+Test that ***both*** input properties are set initially and that button clicks trigger the expected `ngOnChanges` calls and values:
+
[Back to top](guide/component-interaction#top)
-{@a child-to-parent}
+
## Parent listens for child event
The child component exposes an `EventEmitter` property with which it `emits` events when something happens.
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() decorator](guide/inputs-outputs#output)
- as seen in this `VoterComponent`:
-
-
-
-
-
-
+The child's `EventEmitter` property is an ***output property***, typically adorned with an [@Output() decorator](guide/inputs-outputs#output) as seen in this `VoterComponent`:
+
Clicking a button triggers emission of a `true` or `false`, the boolean *payload*.
-The parent `VoteTakerComponent` binds an event handler called `onVoted()` that responds to the child event
-payload `$event` and updates a counter.
-
-
-
+The parent `VoteTakerComponent` binds an event handler called `onVoted()` that responds to the child event payload `$event` and updates a counter.
-
-
-
-
-The framework passes the event argument—represented by `$event`—to the handler method,
-and the method processes it:
+
+The framework passes the event argument —represented by `$event`— to the handler method, and the method processes it:
-
-
+
+
-
Test it
+### Test it for Parent listens for child event
Test that clicking the *Agree* and *Disagree* buttons update the appropriate counters:
-
-
-
-
-
-
+
[Back to top](guide/component-interaction#top)
-
-
## Parent interacts with child using *local variable*
-A parent component cannot use data binding to read child properties
-or invoke child methods. Do both
-by creating a template reference variable for the child element
-and then reference that variable *within the parent template*
-as seen in the following example.
-
-{@a countdown-timer-example}
-The following is a child `CountdownTimerComponent` that repeatedly counts down to zero and launches a rocket.
-The `start` and `stop` methods control the clock and a
-countdown status message displays in its own template.
-
-
+A parent component cannot use data binding to read child properties or invoke child methods.
+Do both by creating a template reference variable for the child element and then reference that variable *within the parent template* as seen in the following example.
-
+
+The following is a child `CountdownTimerComponent` that repeatedly counts down to zero and launches a rocket.
+The `start` and `stop` methods control the clock and a countdown status message displays in its own template.
+
The `CountdownLocalVarParentComponent` that hosts the timer component is as follows:
+
-
-
-
-
-
-
-The parent component cannot data bind to the child's
-`start` and `stop` methods nor to its `seconds` property.
+The parent component cannot data bind to the child's `start` and `stop` methods nor to its `seconds` property.
Place a local variable, `#timer`, on the tag `
` representing the child component.
-That gives you a reference to the child component and the ability to access
-*any of its properties or methods* from within the parent template.
+That gives you a reference to the child component and the ability to access *any of its properties or methods* from within the parent template.
-This example wires parent buttons to the child's `start` and `stop` and
-uses interpolation to display the child's `seconds` property.
+This example wires parent buttons to the child's `start` and `stop` and uses interpolation to display the child's `seconds` property.
Here, the parent and child are working together.
-
-
-
+
+
-{@a countdown-tests}
-
+
-Test it
+### Test it for Parent interacts with child using *local variable*
-Test that the seconds displayed in the parent template
-match the seconds displayed in the child's status message.
+Test that the seconds displayed in the parent template match the seconds displayed in the child's status message.
Test also that clicking the *Stop* button pauses the countdown timer:
-
-
-
-
-
-
+
[Back to top](guide/component-interaction#top)
-{@a parent-to-view-child}
+
-## Parent calls an _@ViewChild()_
+## Parent calls an `@ViewChild()`
-The *local variable* approach is straightforward. But it is limited because
-the parent-child wiring must be done entirely within the parent template.
+The *local variable* approach is straightforward.
+But it is limited because the parent-child wiring must be done entirely within the parent template.
The parent component *itself* has no access to the child.
-You can't use the *local variable* technique if the parent component's *class* relies on the
-child component's *class*. The parent-child relationship of the components is not established
-within each components respective *class* with the *local variable* technique. Because the *class*
-instances are not connected to one another, the parent *class* cannot access the child *class*
-properties and methods.
+You can't use the *local variable* technique if the parent component's *class* relies on the child component's *class*.
+The parent-child relationship of the components is not established within each components respective *class* with the *local variable* technique.
+Because the *class* instances are not connected to one another, the parent *class* cannot access the child *class* properties and methods.
-When the parent component *class* requires that kind of access,
-***inject*** the child component into the parent as a *ViewChild*.
+When the parent component *class* requires that kind of access, ***inject*** the child component into the parent as a *ViewChild*.
-The following example illustrates this technique with the same
-[Countdown Timer](guide/component-interaction#countdown-timer-example) example.
+The following example illustrates this technique with the same [Countdown Timer](guide/component-interaction#countdown-timer-example) example.
Neither its appearance nor its behavior changes.
The child [CountdownTimerComponent](guide/component-interaction#countdown-timer-example) is the same as well.
-
-
-The switch from the *local variable* to the *ViewChild* technique
-is solely for the purpose of demonstration.
+The switch from the *local variable* to the *ViewChild* technique is solely for the purpose of demonstration.
-
-
Here is the parent, `CountdownViewChildParentComponent`:
-
-
-
-
-
+
It takes a bit more work to get the child view into the parent component *class*.
First, you have to import references to the `ViewChild` decorator and the `AfterViewInit` lifecycle hook.
-Next, inject the child `CountdownTimerComponent` into the private `timerComponent` property
-using the `@ViewChild` property decoration.
+Next, inject the child `CountdownTimerComponent` into the private `timerComponent` property using the `@ViewChild` property decoration.
The `#timer` local variable is gone from the component metadata.
-Instead, bind the buttons to the parent component's own `start` and `stop` methods and
-present the ticking seconds in an interpolation around the parent component's `seconds` method.
+Instead, bind the buttons to the parent component's own `start` and `stop` methods and present the ticking seconds in an interpolation around the parent component's `seconds` method.
These methods access the injected timer component directly.
@@ -350,66 +232,45 @@ The `ngAfterViewInit()` lifecycle hook is an important wrinkle.
The timer component isn't available until *after* Angular displays the parent view.
So it displays `0` seconds initially.
-Then Angular calls the `ngAfterViewInit` lifecycle hook at which time it is *too late*
-to update the parent view's display of the countdown seconds.
-Angular's unidirectional data flow rule prevents updating the parent view's
-in the same cycle. The application must *wait one turn* before it can display the seconds.
+Then Angular calls the `ngAfterViewInit` lifecycle hook at which time it is *too late* to update the parent view's display of the countdown seconds.
+Angular's unidirectional data flow rule prevents updating the parent view's in the same cycle.
+The application must *wait one turn* before it can display the seconds.
-Use `setTimeout()` to wait one tick and then revise the `seconds()` method so
-that it takes future values from the timer component.
+Use `setTimeout()` to wait one tick and then revise the `seconds()` method so that it takes future values from the timer component.
-Test it
+### Test it for Parent calls an `@ViewChild()`
Use [the same countdown timer tests](guide/component-interaction#countdown-tests) as before.
[Back to top](guide/component-interaction#top)
-{@a bidirectional-service}
+
## Parent and children communicate using a service
-A parent component and its children share a service whose interface enables bi-directional communication
-*within the family*.
+A parent component and its children share a service whose interface enables bi-directional communication *within the family*.
The scope of the service instance is the parent component and its children.
Components outside this component subtree have no access to the service or their communications.
This `MissionService` connects the `MissionControlComponent` to multiple `AstronautComponent` children.
+
-
-
-
-
-
-
-The `MissionControlComponent` both provides the instance of the service that it shares with its children
-(through the `providers` metadata array) and injects that instance into itself through its constructor:
-
-
-
-
-
-
+The `MissionControlComponent` both provides the instance of the service that it shares with its children \(through the `providers` metadata array\) and injects that instance into itself through its constructor:
+
The `AstronautComponent` also injects the service in its constructor.
Each `AstronautComponent` is a child of the `MissionControlComponent` and therefore receives its parent's service instance:
-
-
-
-
-
-
+
-
-
Notice that this example captures the `subscription` and `unsubscribe()` when the `AstronautComponent` is destroyed.
-This is a memory-leak guard step. There is no actual risk in this application because the
-lifetime of a `AstronautComponent` is the same as the lifetime of the application itself.
+This is a memory-leak guard step.
+There is no actual risk in this application because the lifetime of a `AstronautComponent` is the same as the lifetime of the application itself.
That *would not* always be true in a more complex application.
You don't add this guard to the `MissionControlComponent` because, as the parent,
@@ -417,31 +278,26 @@ it controls the lifetime of the `MissionService`.
-
-
-The *History* log demonstrates that messages travel in both directions between
-the parent `MissionControlComponent` and the `AstronautComponent` children,
-facilitated by the service:
-
+The *History* log demonstrates that messages travel in both directions between the parent `MissionControlComponent` and the `AstronautComponent` children, facilitated by the service:
-
-
-
+
-Test it
+
-Tests click buttons of both the parent `MissionControlComponent` and the `AstronautComponent` children
-and verify that the history meets expectations:
+### Test it for Parent and children communicate using a service
+Tests click buttons of both the parent `MissionControlComponent` and the `AstronautComponent` children and verify that the history meets expectations:
-
+
-
+[Back to top](guide/component-interaction#top)
+
+
-[Back to top](guide/component-interaction#top)
+
-@reviewed 2021-09-17
+@reviewed 2022-02-28
diff --git a/aio/content/guide/component-overview.md b/aio/content/guide/component-overview.md
index a6b9fd8069985..8e3fe028f4a2e 100644
--- a/aio/content/guide/component-overview.md
+++ b/aio/content/guide/component-overview.md
@@ -1,11 +1,12 @@
# Angular Components Overview
-Components are the main building block for Angular applications. Each component consists of:
+Components are the main building block for Angular applications.
+Each component consists of:
-* An HTML template that declares what renders on the page
-* A TypeScript class that defines behavior
-* A CSS selector that defines how the component is used in a template
-* Optionally, CSS styles applied to the template
+* An HTML template that declares what renders on the page
+* A TypeScript class that defines behavior
+* A CSS selector that defines how the component is used in a template
+* Optionally, CSS styles applied to the template
This topic describes how to create and configure an Angular component.
@@ -19,28 +20,29 @@ To view or download the example code used in this topic, see the
<
To create a component, verify that you have met the following prerequisites:
-1. [Install the Angular CLI.](guide/setup-local#install-the-angular-cli)
-1. [Create an Angular workspace](guide/setup-local#create-a-workspace-and-initial-application) with initial application.
- If you don't have a project, create one using `ng new `, where `` is the name of your Angular application.
+1. [Install the Angular CLI.](guide/setup-local#install-the-angular-cli)
+1. [Create an Angular workspace](guide/setup-local#create-a-workspace-and-initial-application) with initial application.
+ If you don't have a project, create one using `ng new `, where `` is the name of your Angular application.
## Creating a component
-The best way to create a component is with the Angular CLI. You can also create a component manually.
+The best way to create a component is with the Angular CLI.
+You can also create a component manually.
### Creating a component using the Angular CLI
To create a component using the Angular CLI:
-1. From a terminal window, navigate to the directory containing your application.
-1. Run the `ng generate component ` command, where `` is the name of your new component.
+1. From a terminal window, navigate to the directory containing your application.
+1. Run the `ng generate component ` command, where `` is the name of your new component.
By default, this command creates the following:
-* A folder named after the component
-* A component file, `.component.ts`
-* A template file, `.component.html`
-* A CSS file, `.component.css`
-* A testing specification file, `.component.spec.ts`
+* A folder named after the component
+* A component file, `.component.ts`
+* A template file, `.component.html`
+* A CSS file, `.component.css`
+* A testing specification file, `.component.spec.ts`
Where `` is the name of your component.
@@ -58,66 +60,47 @@ This section describes how to create the core component file within an existing
To create a new component manually:
-1. Navigate to your Angular project directory.
-1. Create a new file, `.component.ts`.
-1. At the top of the file, add the following import statement.
+1. Navigate to your Angular project directory.
+1. Create a new file, `.component.ts`.
+1. At the top of the file, add the following import statement.
-
-
+
-1. After the `import` statement, add a `@Component` decorator.
+1. After the `import` statement, add a `@Component` decorator.
-
-
+
-1. Choose a CSS selector for the component.
+1. Choose a CSS selector for the component.
-
-
+
- For more information on choosing a selector, see [Specifying a component's selector](#specifying-a-components-css-selector).
+ For more information on choosing a selector, see [Specifying a component's selector](#specifying-a-components-css-selector).
-1. Define the HTML template that the component uses to display information.
- In most cases, this template is a separate HTML file.
+1. Define the HTML template that the component uses to display information.
+ In most cases, this template is a separate HTML file.
-
-
+
- For more information on defining a component's template, see [Defining a component's template](#defining-a-components-template).
+ For more information on defining a component's template, see [Defining a component's template](#defining-a-components-template).
-1. Select the styles for the component's template.
- In most cases, you define the styles for your component's template in a separate file.
+1. Select the styles for the component's template.
+ In most cases, you define the styles for your component's template in a separate file.
-
-
+
-1. Add a `class` statement that includes the code for the component.
+1. Add a `class` statement that includes the code for the component.
-
-
+
## Specifying a component's CSS selector
-Every component requires a CSS _selector_. A selector instructs Angular to instantiate this component wherever it finds the corresponding tag in template HTML. For example, consider a component `hello-world.component.ts` that defines its selector as `app-hello-world`. This selector instructs Angular to instantiate this component any time the tag `` appears in a template.
+Every component requires a CSS *selector*. A selector instructs Angular to instantiate this component wherever it finds the corresponding tag in template HTML.
+For example, consider a component `hello-world.component.ts` that defines its selector as `app-hello-world`.
+This selector instructs Angular to instantiate this component any time the tag `` appears in a template.
Specify a component's selector by adding a `selector` statement to the `@Component` decorator.
-
-
+
## Defining a component's template
@@ -126,58 +109,50 @@ Define a template for your component in one of two ways: by referencing an exter
To define a template as an external file, add a `templateUrl` property to the `@Component` decorator.
-
-
+
To define a template within the component, add a `template` property to the `@Component` decorator that contains the HTML you want to use.
-
-
+
-If you want your template to span multiple lines, use backticks ( `
).
+If you want your template to span multiple lines, use backticks \(`
\).
For example:
-
-
+
-An Angular component requires a template defined using `template` or `templateUrl`. You cannot have both statements in a component.
+An Angular component requires a template defined using `template` or `templateUrl`.
+You cannot have both statements in a component.
## Declaring a component's styles
-Declare component styles uses for its template in one of two ways: by referencing an external file, or directly within the component.
+Declare component styles uses for its template in one of two ways:
+By referencing an external file, or directly within the component.
To declare the styles for a component in a separate file, add a `styleUrls` property to the `@Component` decorator.
-
-
+
To declare the styles within the component, add a `styles` property to the `@Component` decorator that contains the styles you want to use.
-
-
+
The `styles` property takes an array of strings that contain the CSS rule declarations.
-
## Next steps
-* For an architectural overview of components, see [Introduction to components and templates](guide/architecture-components).
-* For additional options to use when creating a component, see [Component](api/core/Component) in the API Reference.
-* For more information on styling components, see [Component styles](guide/component-styles).
-* For more information on templates, see [Template syntax](guide/template-syntax).
+* For an architectural overview of components, see [Introduction to components and templates](guide/architecture-components)
+* For additional options to use when creating a component, see [Component](api/core/Component) in the API Reference
+* For more information on styling components, see [Component styles](guide/component-styles)
+* For more information on templates, see [Template syntax](guide/template-syntax)
+
+
+
+
+
+
-@reviewed 2021-03-18
+@reviewed 2022-02-28
diff --git a/aio/content/guide/component-styles.md b/aio/content/guide/component-styles.md
index f5599981d009b..68fcc1057e968 100644
--- a/aio/content/guide/component-styles.md
+++ b/aio/content/guide/component-styles.md
@@ -1,11 +1,9 @@
# Component styles
-Angular applications are styled with standard CSS. That means you can apply
-everything you know about CSS stylesheets, selectors, rules, and media queries
-directly to Angular applications.
+Angular applications are styled with standard CSS.
+That means you can apply everything you know about CSS stylesheets, selectors, rules, and media queries directly to Angular applications.
-Additionally, Angular can bundle *component styles*
-with components, enabling a more modular design than regular stylesheets.
+Additionally, Angular can bundle *component styles* with components, enabling a more modular design than regular stylesheets.
This page describes how to load and apply these component styles.
@@ -13,25 +11,26 @@ Run the in Stackblitz and download the code from t
## Using component styles
-For every Angular component you write, you can define not only an HTML template,
-but also the CSS styles that go with that template,
-specifying any selectors, rules, and media queries that you need.
+For every Angular component you write, you can define not only an HTML template, but also the CSS styles that go with that template, specifying any selectors, rules, and media queries that you need.
One way to do this is to set the `styles` property in the component metadata.
The `styles` property takes an array of strings that contain CSS code.
Usually you give it one string, as in the following example:
-
+
## Component styling best practices
- See [View Encapsulation](guide/view-encapsulation) for information on how Angular scopes styles to specific components.
+See [View Encapsulation](guide/view-encapsulation) for information on how Angular scopes styles to specific components.
-You should consider the styles of a component to be private implementation details for that component. When consuming a common component, you should not override the component's styles any more than you should access the private members of a TypeScript class. While Angular's default style encapsulation prevents component styles from affecting other components, global styles affect all components on the page. This includes `::ng-deep`, which promotes a component style to a global style.
+You should consider the styles of a component to be private implementation details for that component.
+When consuming a common component, you should not override the component's styles any more than you should access the private members of a TypeScript class.
+While Angular's default style encapsulation prevents component styles from affecting other components, global styles affect all components on the page.
+This includes `::ng-deep`, which promotes a component style to a global style.
### Authoring a component to support customization
@@ -39,124 +38,130 @@ As component author, you can explicitly design a component to accept customizati
#### 1. Use CSS Custom Properties (recommended)
-You can define a supported customization API for your component by defining its styles with CSS Custom Properties, alternatively known as CSS Variables. Anyone using your component can consume this API by defining values for these properties, customizing the final appearance of the component on the rendered page.
+You can define a supported customization API for your component by defining its styles with CSS Custom Properties, alternatively known as CSS Variables.
+Anyone using your component can consume this API by defining values for these properties, customizing the final appearance of the component on the rendered page.
While this requires defining a custom property for each customization point, it creates a clear API contract that works in all style encapsulation modes.
-#### 2. Declare global CSS with @mixin
+#### 2. Declare global CSS with `@mixin`
-While Angular's emulated style encapsulation prevents styles from escaping a component, it does not prevent global CSS from affecting the entire page. While component consumers should avoid directly overwriting the CSS internals of a component, you can offer a supported customization API via a CSS preprocessor like Sass.
+While Angular's emulated style encapsulation prevents styles from escaping a component, it does not prevent global CSS from affecting the entire page.
+While component consumers should avoid directly overwriting the CSS internals of a component, you can offer a supported customization API via a CSS preprocessor like Sass.
-For example, a component may offer one or more supported mixins to customize various aspects of the component's appearance. While this approach uses global styles in it’s implementation, it allows the component author to keep the mixins up to date with changes to the component's private DOM structure and CSS classes.
+For example, a component may offer one or more supported mixins to customize various aspects of the component's appearance.
+While this approach uses global styles in it's implementation, it allows the component author to keep the mixins up to date with changes to the component's private DOM structure and CSS classes.
-#### 3. Customize with CSS ::part
+#### 3. Customize with CSS `::part`
-If your component uses [Shadow DOM](https://developer.mozilla.org/docs/Web/Web_Components/Using_shadow_DOM), you can apply the `part` attribute to specify elements in your component's template. This allows consumers of the component to author arbitrary styles targeting those specific elements with [the `::part` pseudo-element](https://developer.mozilla.org/docs/Web/CSS/::part).
+If your component uses [Shadow DOM](https://developer.mozilla.org/docs/Web/Web_Components/Using_shadow_DOM), you can apply the `part` attribute to specify elements in your component's template.
+This allows consumers of the component to author arbitrary styles targeting those specific elements with [the `::part` pseudo-element](https://developer.mozilla.org/docs/Web/CSS/::part).
-While this lets you limit the elements within your template that consumers can customize, it does not limit which CSS properties are customizable.
+While this lets you limit the elements within your template that consumers can customize, it does not limit which CSS properties are customizable.
#### 4. Provide a TypeScript API
-You can define a TypeScript API for customizing styles, using template bindings to update CSS classes and styles. This is not recommended because the additional JavaScript cost of this style API incurs far more performance cost than CSS.
+You can define a TypeScript API for customizing styles, using template bindings to update CSS classes and styles.
+This is not recommended because the additional JavaScript cost of this style API incurs far more performance cost than CSS.
## Special selectors
-Component styles have a few special *selectors* from the world of shadow DOM style scoping
-(described in the [CSS Scoping Module Level 1](https://www.w3.org/TR/css-scoping-1) page on the
-[W3C](https://www.w3.org) site).
+Component styles have a few special *selectors* from the world of shadow DOM style scoping \(described in the [CSS Scoping Module Level 1](https://www.w3.org/TR/css-scoping-1) page on the [W3C](https://www.w3.org) site\).
The following sections describe these selectors.
-
### :host
-Every component is associated within an element that matches the component's selector. This element, into which the template is rendered,
-is called the _host element_.
+
+Every component is associated within an element that matches the component's selector.
+This element, into which the template is rendered, is called the *host element*.
The `:host` pseudo-class selector may be used to create styles that target the host element itself, as opposed to targeting elements inside the host.
-
-
+
-Creating the following style will target the component's host element. Any rule applied to this selector will affect the host element and all its descendants (in this case, italicizing all contained text).
+Creating the following style will target the component's host element.
+Any rule applied to this selector will affect the host element and all its descendants \(in this case, italicizing all contained text\).
-
+
-The `:host` selector only targets the host element of a component. Any styles within the `:host` block of a child component will *not* affect parent components.
+The `:host` selector only targets the host element of a component.
+Any styles within the `:host` block of a child component will *not* affect parent components.
-Use the *function form* to apply host styles conditionally by
-including another selector inside parentheses after `:host`.
+Use the *function form* to apply host styles conditionally by including another selector inside parentheses after `:host`.
In this example the host's content also becomes bold when the `active` CSS class is applied to the host element.
-
+
The `:host` selector can also be combined with other selectors.
Add selectors behind the `:host` to select child elements, for example using `:host h2` to target all `` elements inside a component's view.
-You should not add selectors (other than `:host-context`) in front of the `:host` selector to style a component based on the outer context of the component's view. Such selectors are not scoped to a component's view and will select the outer context, but it's not built-in behavior. Use `:host-context` selector for that purpose instead.
+You should not add selectors \(other than `:host-context`\) in front of the `:host` selector to style a component based on the outer context of the component's view.
+Such selectors are not scoped to a component's view and will select the outer context, but it's not built-in behavior.
+Use `:host-context` selector for that purpose instead.
### :host-context
-Sometimes it's useful to apply styles to elements within a component's template
-based on some condition in an element that is an ancestor of the host element.
-For example, a CSS theme class could be applied to the document `` element, and
-you want to change how your component looks based on that.
+Sometimes it's useful to apply styles to elements within a component's template based on some condition in an element that is an ancestor of the host element.
+For example, a CSS theme class could be applied to the document `` element, and you want to change how your component looks based on that.
-Use the `:host-context()` pseudo-class selector, which works just like the function
-form of `:host()`. The `:host-context()` selector looks for a CSS class in any ancestor of the component host element,
-up to the document root. The `:host-context()` selector is only useful when combined with another selector.
+Use the `:host-context()` pseudo-class selector, which works just like the function form of `:host()`.
+The `:host-context()` selector looks for a CSS class in any ancestor of the component host element, up to the document root.
+The `:host-context()` selector is only useful when combined with another selector.
The following example italicizes all text inside a component, but only
-if some _ancestor_ element of the host element has the CSS class `active`.
+if some *ancestor* element of the host element has the CSS class `active`.
-
+
-Note that only the host element and its descendants will be affected, not the ancestor with the assigned `active` class.
+
+
+**NOTE**:
+Only the host element and its descendants will be affected, not the ancestor with the assigned `active` class.
+
+
### (deprecated) `/deep/`, `>>>`, and `::ng-deep`
Component styles normally apply only to the HTML in the component's own template.
-Applying the `::ng-deep` pseudo-class to any CSS rule completely disables view-encapsulation for
-that rule. Any style with `::ng-deep` applied becomes a global style. In order to scope the specified style
-to the current component and all its descendants, be sure to include the `:host` selector before
-`::ng-deep`. If the `::ng-deep` combinator is used without the `:host` pseudo-class selector, the style
-can bleed into other components.
+Applying the `::ng-deep` pseudo-class to any CSS rule completely disables view-encapsulation for that rule.
+Any style with `::ng-deep` applied becomes a global style.
+In order to scope the specified style to the current component and all its descendants, be sure to include the `:host` selector before `::ng-deep`.
+If the `::ng-deep` combinator is used without the `:host` pseudo-class selector, the style can bleed into other components.
-The following example targets all `` elements, from the host element down
-through this component to all of its child elements in the DOM.
+The following example targets all `` elements, from the host element down through this component to all of its child elements in the DOM.
-
+
The `/deep/` combinator also has the aliases `>>>`, and `::ng-deep`.
-Use `/deep/`, `>>>` and `::ng-deep` only with *emulated* view encapsulation.
-Emulated is the default and most commonly used view encapsulation. For more information, see the
-[View Encapsulation](guide/view-encapsulation) section.
+Use `/deep/`, `>>>`, and `::ng-deep` only with *emulated* view encapsulation.
+Emulated is the default and most commonly used view encapsulation.
+For more information, see the [View Encapsulation](guide/view-encapsulation) section.
The shadow-piercing descendant combinator is deprecated and [support is being removed from major browsers](https://www.chromestatus.com/feature/6750456638341120) and tools.
-As such we plan to drop support in Angular (for all 3 of `/deep/`, `>>>` and `::ng-deep`).
+As such we plan to drop support in Angular \(for all 3 of `/deep/`, `>>>`, and `::ng-deep`\).
Until then `::ng-deep` should be preferred for a broader compatibility with the tools.
-{@a loading-styles}
+
## Loading component styles
There are several ways to add styles to a component:
-* By setting `styles` or `styleUrls` metadata.
-* Inline in the template HTML.
-* With CSS imports.
+* By setting `styles` or `styleUrls` metadata
+* Inline in the template HTML
+* With CSS imports
The scoping rules outlined earlier apply to each of these loading patterns.
@@ -166,65 +171,65 @@ Add a `styles` array property to the `@Component` decorator.
Each string in the array defines some CSS for this component.
-
-
+
-Reminder: these styles apply _only to this component_.
-They are _not inherited_ by any components nested within the template nor by any content projected into the component.
+Reminder:
+These styles apply *only to this component*.
+They are *not inherited* by any components nested within the template nor by any content projected into the component.
The Angular CLI command [`ng generate component`](cli/generate) defines an empty `styles` array when you create the component with the `--inline-style` flag.
-
+
+
ng generate component hero-app --inline-style
+
### Style files in component metadata
-Load styles from external CSS files by adding a `styleUrls` property
-to a component's `@Component` decorator:
+Load styles from external CSS files by adding a `styleUrls` property to a component's `@Component` decorator:
-
-
+
+
-Reminder: the styles in the style file apply _only to this component_.
-They are _not inherited_ by any components nested within the template nor by any content projected into the component.
+Reminder: the styles in the style file apply *only to this component*.
+They are *not inherited* by any components nested within the template nor by any content projected into the component.
- You can specify more than one styles file or even a combination of `styles` and `styleUrls`.
+You can specify more than one styles file or even a combination of `styles` and `styleUrls`.
When you use the Angular CLI command [`ng generate component`](cli/generate) without the `--inline-style` flag, it creates an empty styles file for you and references that file in the component's generated `styleUrls`.
-
+
+
ng generate component hero-app
+
### Template inline styles
-Embed CSS styles directly into the HTML template by putting them
-inside `
-
-||Reactive|Template-driven|
-|--- |--- |--- |
-|[Setup of form model](#setup) | Explicit, created in component class | Implicit, created by directives |
-|[Data model](#mutability-of-the-data-model) | Structured and immutable | Unstructured and mutable |
-|[Data flow](#data-flow-in-forms) | Synchronous | Asynchronous |
-|[Form validation](#validation) | Functions | Directives |
+| | Reactive | Template-driven |
+|:--- |:--- |:--- |
+| [Setup of form model](#setup) | Explicit, created in component class | Implicit, created by directives |
+| [Data model](#mutability-of-the-data-model) | Structured and immutable | Unstructured and mutable |
+| [Data flow](#data-flow-in-forms) | Synchronous | Asynchronous |
+| [Form validation](#validation) | Functions | Directives |
### Scalability
-If forms are a central part of your application, scalability is very important. Being able to reuse form models across components is critical.
+If forms are a central part of your application, scalability is very important.
+Being able to reuse form models across components is critical.
-Reactive forms are more scalable than template-driven forms. They provide direct access to the underlying form API, and use [synchronous data flow](#data-flow-in-reactive-forms) between the view and the data model, which makes creating large-scale forms easier.
+Reactive forms are more scalable than template-driven forms.
+They provide direct access to the underlying form API, and use [synchronous data flow](#data-flow-in-reactive-forms) between the view and the data model, which makes creating large-scale forms easier.
Reactive forms require less setup for testing, and testing does not require deep understanding of change detection to properly test form updates and validation.
Template-driven forms focus on simple scenarios and are not as reusable.
@@ -52,7 +53,7 @@ They abstract away the underlying form API, and use [asynchronous data flow](#da
The abstraction of template-driven forms also affects testing.
Tests are deeply reliant on manual change detection execution to run properly, and require more setup.
-{@a setup}
+
## Setting up the form model
@@ -63,52 +64,60 @@ The two approaches share underlying building blocks, but differ in how you creat
Both reactive and template-driven forms are built on the following base classes.
-* `FormControl` tracks the value and validation status of an individual form control.
+| Base classes | Details |
+|:--- |:--- |
+| `FormControl` | Tracks the value and validation status of an individual form control. |
+| `FormGroup` | Tracks the same values and status for a collection of form controls. |
+| `FormArray` | Tracks the same values and status for an array of form controls. |
+| `ControlValueAccessor` | Creates a bridge between Angular `FormControl` instances and built-in DOM elements. |
-* `FormGroup` tracks the same values and status for a collection of form controls.
-
-* `FormArray` tracks the same values and status for an array of form controls.
-
-* `ControlValueAccessor` creates a bridge between Angular `FormControl` instances and built-in DOM elements.
-
-{@a setup-the-form-model}
+
### Setup in reactive forms
With reactive forms, you define the form model directly in the component class.
The `[formControl]` directive links the explicitly created `FormControl` instance to a specific form element in the view, using an internal value accessor.
-The following component implements an input field for a single control, using reactive forms. In this example, the form model is the `FormControl` instance.
+The following component implements an input field for a single control, using reactive forms.
+In this example, the form model is the `FormControl` instance.
-
-
+
Figure 1 shows how, in reactive forms, the form model is the source of truth; it provides the value and status of the form element at any given point in time, through the `[formControl]` directive on the input element.
+
+
**Figure 1.** *Direct access to forms model in a reactive form.*
-
+
+
+
### Setup in template-driven forms
-In template-driven forms, the form model is implicit, rather than explicit. The directive `NgModel` creates and manages a `FormControl` instance for a given form element.
+In template-driven forms, the form model is implicit, rather than explicit.
+The directive `NgModel` creates and manages a `FormControl` instance for a given form element.
The following component implements the same input field for a single control, using template-driven forms.
-
-
+
-In a template-driven form the source of truth is the template. You do not have direct programmatic access to the `FormControl` instance, as shown in Figure 2.
+In a template-driven form the source of truth is the template.
+You do not have direct programmatic access to the `FormControl` instance, as shown in Figure 2.
+
+
**Figure 2.** *Indirect access to forms model in a template-driven form.*
-
+
+
+
-{@a data-flow-in-forms}
+
## Data flow in forms
@@ -119,36 +128,41 @@ Similarly, when the program logic changes values in the data model, those values
Reactive and template-driven forms differ in how they handle data flowing from the user or from programmatic changes.
The following diagrams illustrate both kinds of data flow for each type of form, using the favorite-color input field defined above.
-{@a data-flow-in-reactive-forms}
+
### Data flow in reactive forms
-In reactive forms each form element in the view is directly linked to the form model (a `FormControl` instance). Updates from the view to the model and from the model to the view are synchronous and do not depend on how the UI is rendered.
+In reactive forms each form element in the view is directly linked to the form model \(a `FormControl` instance\).
+Updates from the view to the model and from the model to the view are synchronous and do not depend on how the UI is rendered.
The view-to-model diagram shows how data flows when an input field's value is changed from the view through the following steps.
-1. The user types a value into the input element, in this case the favorite color *Blue*.
-1. The form input element emits an "input" event with the latest value.
-1. The control value accessor listening for events on the form input element immediately relays the new value to the `FormControl` instance.
-1. The `FormControl` instance emits the new value through the `valueChanges` observable.
-1. Any subscribers to the `valueChanges` observable receive the new value.
+1. The user types a value into the input element, in this case the favorite color *Blue*.
+1. The form input element emits an "input" event with the latest value.
+1. The control value accessor listening for events on the form input element immediately relays the new value to the `FormControl` instance.
+1. The `FormControl` instance emits the new value through the `valueChanges` observable.
+1. Any subscribers to the `valueChanges` observable receive the new value.
-
+
+
+
The model-to-view diagram shows how a programmatic change to the model is propagated to the view through the following steps.
-1. The user calls the `favoriteColorControl.setValue()` method, which updates the `FormControl` value.
-1. The `FormControl` instance emits the new value through the `valueChanges` observable.
-1. Any subscribers to the `valueChanges` observable receive the new value.
-1. The control value accessor on the form input element updates the element with the new value.
+1. The user calls the `favoriteColorControl.setValue()` method, which updates the `FormControl` value.
+1. The `FormControl` instance emits the new value through the `valueChanges` observable.
+1. Any subscribers to the `valueChanges` observable receive the new value.
+1. The control value accessor on the form input element updates the element with the new value.
-
+
+
+
-{@a data-flow-in-template-driven-forms}
+
### Data flow in template-driven forms
@@ -156,70 +170,72 @@ In template-driven forms, each form element is linked to a directive that manage
The view-to-model diagram shows how data flows when an input field's value is changed from the view through the following steps.
-1. The user types *Blue* into the input element.
-1. The input element emits an "input" event with the value *Blue*.
-1. The control value accessor attached to the input triggers the `setValue()` method on the `FormControl` instance.
-1. The `FormControl` instance emits the new value through the `valueChanges` observable.
-1. Any subscribers to the `valueChanges` observable receive the new value.
-1. The control value accessor also calls the `NgModel.viewToModelUpdate()` method which emits an `ngModelChange` event.
-1. Because the component template uses two-way data binding for the `favoriteColor` property, the `favoriteColor` property in the component
-is updated to the value emitted by the `ngModelChange` event (*Blue*).
+1. The user types *Blue* into the input element.
+1. The input element emits an "input" event with the value *Blue*.
+1. The control value accessor attached to the input triggers the `setValue()` method on the `FormControl` instance.
+1. The `FormControl` instance emits the new value through the `valueChanges` observable.
+1. Any subscribers to the `valueChanges` observable receive the new value.
+1. The control value accessor also calls the `NgModel.viewToModelUpdate()` method which emits an `ngModelChange` event.
+1. Because the component template uses two-way data binding for the `favoriteColor` property, the `favoriteColor` property in the component is updated to the value emitted by the `ngModelChange` event \(*Blue*\).
-
+
+
+
The model-to-view diagram shows how data flows from model to view when the `favoriteColor` changes from *Blue* to *Red*, through the following steps
-1. The `favoriteColor` value is updated in the component.
-1. Change detection begins.
-1. During change detection, the `ngOnChanges` lifecycle hook is called on the `NgModel` directive instance because the value of one of its inputs has changed.
-1. The `ngOnChanges()` method queues an async task to set the value for the internal `FormControl` instance.
-1. Change detection completes.
-1. On the next tick, the task to set the `FormControl` instance value is executed.
-1. The `FormControl` instance emits the latest value through the `valueChanges` observable.
-1. Any subscribers to the `valueChanges` observable receive the new value.
-1. The control value accessor updates the form input element in the view with the latest `favoriteColor` value.
+1. The `favoriteColor` value is updated in the component.
+1. Change detection begins.
+1. During change detection, the `ngOnChanges` lifecycle hook is called on the `NgModel` directive instance because the value of one of its inputs has changed.
+1. The `ngOnChanges()` method queues an async task to set the value for the internal `FormControl` instance.
+1. Change detection completes.
+1. On the next tick, the task to set the `FormControl` instance value is executed.
+1. The `FormControl` instance emits the latest value through the `valueChanges` observable.
+1. Any subscribers to the `valueChanges` observable receive the new value.
+1. The control value accessor updates the form input element in the view with the latest `favoriteColor` value.
-
+
+
+
-{@a mutability-of-the-data-model}
+
### Mutability of the data model
The change-tracking method plays a role in the efficiency of your application.
-* **Reactive forms** keep the data model pure by providing it as an immutable data structure.
-Each time a change is triggered on the data model, the `FormControl` instance returns a new data model rather than updating the existing data model.
-This gives you the ability to track unique changes to the data model through the control's observable.
-Change detection is more efficient because it only needs to update on unique changes.
-Because data updates follow reactive patterns, you can integrate with observable operators to transform data.
-
-* **Template-driven** forms rely on mutability with two-way data binding to update the data model in the component as changes are made in the template.
-Because there are no unique changes to track on the data model when using two-way data binding, change detection is less efficient at determining when updates are required.
+| Forms | Details |
+|:--- |:--- |
+| Reactive forms | Keep the data model pure by providing it as an immutable data structure. Each time a change is triggered on the data model, the `FormControl` instance returns a new data model rather than updating the existing data model. This gives you the ability to track unique changes to the data model through the control's observable. Change detection is more efficient because it only needs to update on unique changes. Because data updates follow reactive patterns, you can integrate with observable operators to transform data. |
+| Template-driven forms | Rely on mutability with two-way data binding to update the data model in the component as changes are made in the template. Because there are no unique changes to track on the data model when using two-way data binding, change detection is less efficient at determining when updates are required. |
The difference is demonstrated in the previous examples that use the favorite-color input element.
-* With reactive forms, the **`FormControl` instance** always returns a new value when the control's value is updated.
+* With reactive forms, the **`FormControl` instance** always returns a new value when the control's value is updated
+* With template-driven forms, the **favorite color property** is always modified to its new value
-* With template-driven forms, the **favorite color property** is always modified to its new value.
-
-{@a validation}
+
## Form validation
-Validation is an integral part of managing any set of forms. Whether you're checking for required fields or querying an external API for an existing username, Angular provides a set of built-in validators as well as the ability to create custom validators.
+Validation is an integral part of managing any set of forms.
+Whether you're checking for required fields or querying an external API for an existing username, Angular provides a set of built-in validators as well as the ability to create custom validators.
-* **Reactive forms** define custom validators as **functions** that receive a control to validate.
-* **Template-driven forms** are tied to template **directives**, and must provide custom validator directives that wrap validation functions.
+| Forms | Details |
+|:--- |:--- |
+| Reactive forms | Define custom validators as **functions** that receive a control to validate |
+| Template-driven forms | Tied to template **directives**, and must provide custom validator directives that wrap validation functions |
For more information, see [Form Validation](guide/form-validation).
## Testing
-Testing plays a large part in complex applications. A simpler testing strategy is useful when validating that your forms function correctly.
+Testing plays a large part in complex applications.
+A simpler testing strategy is useful when validating that your forms function correctly.
Reactive forms and template-driven forms have different levels of reliance on rendering the UI to perform assertions based on form control and form field changes.
The following examples demonstrate the process of testing forms with reactive and template-driven forms.
@@ -230,25 +246,25 @@ In these tests, status and data are queried and manipulated through the control
The following tests use the favorite-color components from previous examples to verify the view-to-model and model-to-view data flows for a reactive form.
+
+
**Verifying view-to-model data flow**
The first example performs the following steps to verify the view-to-model data flow.
-1. Query the view for the form input element, and create a custom "input" event for the test.
-1. Set the new value for the input to *Red*, and dispatch the "input" event on the form input element.
-1. Assert that the component's `favoriteColorControl` value matches the value from the input.
+1. Query the view for the form input element, and create a custom "input" event for the test.
+1. Set the new value for the input to *Red*, and dispatch the "input" event on the form input element.
+1. Assert that the component's `favoriteColorControl` value matches the value from the input.
-
-
+
The next example performs the following steps to verify the model-to-view data flow.
-1. Use the `favoriteColorControl`, a `FormControl` instance, to set the new value.
-1. Query the view for the form input element.
-1. Assert that the new value set on the control matches the value in the input.
+1. Use the `favoriteColorControl`, a `FormControl` instance, to set the new value.
+1. Query the view for the form input element.
+1. Assert that the new value set on the control matches the value in the input.
-
-
+
### Testing template-driven forms
@@ -258,40 +274,45 @@ The following tests use the favorite color components mentioned earlier to verif
The following test verifies the data flow from view to model.
-
-
+
Here are the steps performed in the view to model test.
-1. Query the view for the form input element, and create a custom "input" event for the test.
-1. Set the new value for the input to *Red*, and dispatch the "input" event on the form input element.
-1. Run change detection through the test fixture.
-1. Assert that the component `favoriteColor` property value matches the value from the input.
+1. Query the view for the form input element, and create a custom "input" event for the test.
+1. Set the new value for the input to *Red*, and dispatch the "input" event on the form input element.
+1. Run change detection through the test fixture.
+1. Assert that the component `favoriteColor` property value matches the value from the input.
The following test verifies the data flow from model to view.
-
-
+
Here are the steps performed in the model to view test.
-1. Use the component instance to set the value of the `favoriteColor` property.
-1. Run change detection through the test fixture.
-1. Use the `tick()` method to simulate the passage of time within the `fakeAsync()` task.
-1. Query the view for the form input element.
-1. Assert that the input value matches the value of the `favoriteColor` property in the component instance.
-
+1. Use the component instance to set the value of the `favoriteColor` property.
+1. Run change detection through the test fixture.
+1. Use the `tick()` method to simulate the passage of time within the `fakeAsync()` task.
+1. Query the view for the form input element.
+1. Assert that the input value matches the value of the `favoriteColor` property in the component instance.
## Next steps
To learn more about reactive forms, see the following guides:
-* [Reactive forms](guide/reactive-forms)
-* [Form validation](guide/form-validation#reactive-form-validation)
-* [Dynamic forms](guide/dynamic-form)
+* [Reactive forms](guide/reactive-forms)
+* [Form validation](guide/form-validation#reactive-form-validation)
+* [Dynamic forms](guide/dynamic-form)
To learn more about template-driven forms, see the following guides:
-* [Building a template-driven form](guide/forms) tutorial
-* [Form validation](guide/form-validation#template-driven-validation)
-* `NgForm` directive API reference
+* [Building a template-driven form](guide/forms) tutorial
+* [Form validation](guide/form-validation#template-driven-validation)
+* `NgForm` directive API reference
+
+
+
+
+
+
+
+@reviewed 2022-02-28
diff --git a/aio/content/guide/forms.md b/aio/content/guide/forms.md
index be80e0bb25b22..b1dda33efff17 100644
--- a/aio/content/guide/forms.md
+++ b/aio/content/guide/forms.md
@@ -1,6 +1,6 @@
# Building a template-driven form
-{@a template-driven}
+
This tutorial shows you how to create a template-driven form whose control elements are bound to data properties, with input validation to maintain data integrity and styling to improve the user experience.
@@ -8,23 +8,23 @@ Template-driven forms use [two-way data binding](guide/architecture-components#d
-Angular supports two design approaches for interactive forms. You can build forms by writing templates using Angular [template syntax and directives](guide/glossary#template "Definition of template terms") with the form-specific directives and techniques described in this tutorial, or you can use a reactive (or model-driven) approach to build forms.
+Angular supports two design approaches for interactive forms.
+You can build forms by writing templates using Angular [template syntax and directives](guide/glossary#template "Definition of template terms") with the form-specific directives and techniques described in this tutorial, or you can use a reactive \(or model-driven\) approach to build forms.
Template-driven forms are suitable for small or simple forms, while reactive forms are more scalable and suitable for complex forms.
For a comparison of the two approaches, see [Introduction to Forms](guide/forms-overview "Overview of Angular forms.")
-You can build almost any kind of form with an Angular template—login forms, contact forms, and pretty much any business form.
+You can build almost any kind of form with an Angular template —login forms, contact forms, and pretty much any business form.
You can lay out the controls creatively and bind them to the data in your object model.
-You can specify validation rules and display validation errors,
-conditionally enable or disable specific controls, trigger built-in visual feedback, and much more.
+You can specify validation rules and display validation errors, conditionally enable or disable specific controls, trigger built-in visual feedback, and much more.
This tutorial shows you how to build a form from scratch, using a simplified sample form like the one from the [Tour of Heroes tutorial](tutorial "Tour of Heroes") to illustrate the techniques.
- Run or download the example app: .
+Run or download the example app: .
@@ -32,129 +32,140 @@ This tutorial shows you how to build a form from scratch, using a simplified sam
This tutorial teaches you how to do the following:
-* Build an Angular form with a component and template.
-* 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-reference-variables).
+* Build an Angular form with a component and template
+* 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-reference-variables)
## Prerequisites
Before going further into template-driven forms, you should have a basic understanding of the following.
-* [TypeScript](https://www.typescriptlang.org/ "The TypeScript language") and HTML5 programming.
-* Angular app-design fundamentals, as described in [Angular Concepts](guide/architecture "Introduction to Angular concepts.").
-* The basics of [Angular template syntax](guide/template-syntax "Template syntax guide").
-* The form-design concepts that are presented in [Introduction to Forms](guide/forms-overview "Overview of Angular forms.").
+* [TypeScript](https://www.typescriptlang.org/ "The TypeScript language") and HTML5 programming
+* Angular app-design fundamentals, as described in [Angular Concepts](guide/architecture "Introduction to Angular concepts")
+* The basics of [Angular template syntax](guide/template-syntax "Template syntax guide")
+* The form-design concepts that are presented in [Introduction to Forms](guide/forms-overview "Overview of Angular forms")
-{@a intro}
+
## Build a template-driven form
Template-driven forms rely on directives defined in the `FormsModule`.
-* The `NgModel` directive reconciles value changes in the attached form element with changes in the data model, allowing you to respond to user input with input validation and error handling.
-
-* The `NgForm` directive creates a top-level `FormGroup` instance and binds it to a `
-2. Add these class definitions to a new `forms.css` file.
+To change the appearance in this way, take the following steps.
-3. Add the new file to the project as a sibling to `index.html`:
+1. Add definitions for the `ng-*` CSS classes.
+1. Add these class definitions to a new `forms.css` file.
+1. Add the new file to the project as a sibling to `index.html`:
-
+
-4. In the `index.html` file, update the `` tag to include the new style sheet.
+1. In the `index.html` file, update the `` tag to include the new style sheet.
-
+
### Show and hide validation error messages
@@ -373,30 +332,33 @@ You can provide a helpful message by checking for and responding to the control'
When the user deletes the name, the form should look like this:
-
+
+
+
The **Hero Power** select box is also required, but it doesn't need this kind of error handling because the selection box already constrains the selection to valid values.
To define and show an error message when appropriate, take the following steps.
-1. Extend the `
` tag with a template reference variable that you can use to access the input box's Angular control from within the template. In the example, the variable is `#name="ngModel"`.
+1. Extend the `
` tag with a template reference variable that you can use to access the input box's Angular control from within the template.
+ In the example, the variable is `#name="ngModel"`.
-
+
- The template reference variable (`#name`) is set to `"ngModel"` because that is the value of the [`NgModel.exportAs`](api/core/Directive#exportAs) property. This property tells Angular how to link a reference variable to a directive.
+ The template reference variable \(`#name`\) is set to `"ngModel"` because that is the value of the [`NgModel.exportAs`](api/core/Directive#exportAs) property.
+ This property tells Angular how to link a reference variable to a directive.
-
+
-2. Add a `
` that contains a suitable error message.
-3. Show or hide the error message by binding properties of the `name`
-control to the message `
` element's `hidden` property.
+1. Add a `
` that contains a suitable error message.
+1. Show or hide the error message by binding properties of the `name` control to the message `
` element's `hidden` property.
-
+
-4. Add a conditional error message to the _name_ input box, as in the following example.
+1. Add a conditional error message to the `name` input box, as in the following example.
-
+
@@ -405,8 +367,7 @@ control to the message `
` element's `hidden` property.
In this example, you hide the message when the control is either valid or *pristine*.
Pristine means the user hasn't changed the value since it was displayed in this form.
If you ignore the `pristine` state, you would hide the message only when the value is valid.
-If you arrive in this component with a new (blank) hero or an invalid hero,
-you'll see the error message immediately, before you've done anything.
+If you arrive in this component with a new \(blank\) hero or an invalid hero, you'll see the error message immediately, before you've done anything.
You might want the message to display only when the user makes an invalid change.
Hiding the message while the control is in the `pristine` state achieves that goal.
@@ -419,30 +380,31 @@ You'll see the significance of this choice when you add a new hero to the form i
This exercise shows how you can respond to a native HTML button-click event by adding to the model data.
To let form users add a new hero, you will add a **New Hero** button that responds to a click event.
-1. In the template, place a "New Hero" `
` element at the bottom of the form.
-2. In the component file, add the hero-creation method to the hero data model.
+1. In the template, place a "New Hero" `` element at the bottom of the form.
+1. In the component file, add the hero-creation method to the hero data model.
-
+
-3. Bind the button's click event to a hero-creation method, `newHero()`.
+1. Bind the button's click event to a hero-creation method, `newHero()`.
-
+
-4. Run the application again and click the **New Hero** button.
+1. Run the application again and click the **New Hero** button.
- The form clears, and the *required* bars to the left of the input box are red, indicating invalid `name` and `power` properties.
- Notice that the error messages are hidden. This is because the form is pristine; you haven't changed anything yet.
+ The form clears, and the *required* bars to the left of the input box are red, indicating invalid `name` and `power` properties.
+ Notice that the error messages are hidden.
+ This is because the form is pristine; you haven't changed anything yet.
-5. Enter a name and click **New Hero** again.
+1. Enter a name and click **New Hero** again.
- Now the application displays a _Name is required_ error message, because the input box is no longer pristine.
- The form remembers that you entered a name before clicking **New Hero**.
+ Now the application displays a `Name is required` error message, because the input box is no longer pristine.
+ The form remembers that you entered a name before clicking **New Hero**.
-6. To restore the pristine state of the form controls, clear all of the flags imperatively by calling the form's `reset()` method after calling the `newHero()` method.
+1. To restore the pristine state of the form controls, clear all of the flags imperatively by calling the form's `reset()` method after calling the `newHero()` method.
-
+
- Now clicking **New Hero** resets both the form and its control flags.
+ Now clicking **New Hero** resets both the form and its control flags.
@@ -450,106 +412,86 @@ See the [User Input](guide/user-input) guide for more information about listenin
-## Submit the form with _ngSubmit_
+## Submit the form with `ngSubmit`
The user should be able to submit this form after filling it in.
-The **Submit** button at the bottom of the form does nothing on its own, but it does
-trigger a form-submit event because of its type (`type="submit"`).
+The **Submit** button at the bottom of the form does nothing on its own, but it does trigger a form-submit event because of its type \(`type="submit"`\).
To respond to this event, take the following steps.
-1. Bind the form's [`ngSubmit`](api/forms/NgForm#properties) event property to the hero-form component's `onSubmit()` method.
-
-
+1. Bind the form's [`ngSubmit`](api/forms/NgForm#properties) event property to the hero-form component's `onSubmit()` method.
-2. Use the template reference variable, `#heroForm` to access the form that contains the **Submit** button and create an event binding.
-You will bind the form property that indicates its overall validity to the **Submit** button's `disabled` property.
+
-
+1. Use the template reference variable, `#heroForm` to access the form that contains the **Submit** button and create an event binding.
+ You will bind the form property that indicates its overall validity to the **Submit** button's `disabled` property.
-3. Run the application now. Notice that the button is enabled—although
-it doesn't do anything useful yet.
+
-4. Delete the **Name** value. This violates the "required" rule, so it displays the error message—and notice that it also disables the **Submit** button.
+1. Run the application.
+ Notice that the button is enabled —although it doesn't do anything useful yet.
+1. Delete the **Name** value.
+ This violates the "required" rule, so it displays the error message —and notice that it also disables the **Submit** button.
- You didn't have to explicitly wire the button's enabled state to the form's validity.
- The `FormsModule` did this automatically when you defined a template reference variable on the enhanced form element, then referred to that variable in the button control.
+ You didn't have to explicitly wire the button's enabled state to the form's validity.
+ The `FormsModule` did this automatically when you defined a template reference variable on the enhanced form element, then referred to that variable in the button control.
### Respond to form submission
To show a response to form submission, you can hide the data entry area and display something else in its place.
-1. Wrap the entire form in a `` and bind
-its `hidden` property to the `HeroFormComponent.submitted` property.
+1. Wrap the entire form in a `
` and bind its `hidden` property to the `HeroFormComponent.submitted` property.
-
+
- * The main form is visible from the start because the `submitted` property is false until you submit the form, as this fragment from the `HeroFormComponent` shows:
+ * The main form is visible from the start because the `submitted` property is false until you submit the form, as this fragment from the `HeroFormComponent` shows:
-
+
- * When you click the **Submit** button, the `submitted` flag becomes true and the form disappears.
+ * When you click the **Submit** button, the `submitted` flag becomes true and the form disappears.
-2. To show something else while the form is in the submitted state, add the following HTML below the new `
` wrapper.
+1. To show something else while the form is in the submitted state, add the following HTML below the new `
` wrapper.
-
+
- This `
`, which shows a read-only hero with interpolation bindings, appears only while the component is in the submitted state.
+ This `
`, which shows a read-only hero with interpolation bindings, appears only while the component is in the submitted state.
- The alternative display includes an *Edit* button whose click event is bound to an expression
-that clears the `submitted` flag.
+ The alternative display includes an *Edit* button whose click event is bound to an expression that clears the `submitted` flag.
-3. Click the *Edit* button to switch the display back to the editable form.
+1. Click the *Edit* button to switch the display back to the editable form.
## Summary
The Angular form discussed in this page takes advantage of the following
framework features to provide support for data modification, validation, and more.
-* An Angular HTML form template.
-* A form component class with a `@Component` decorator.
-* Handling form submission by binding to the `NgForm.ngSubmit` event property.
-* Template-reference variables such as `#heroForm` and `#name`.
-* `[(ngModel)]` syntax for two-way data binding.
-* The use of `name` attributes for validation and form-element change tracking.
-* The reference variable’s `valid` property on input controls to check if a control is valid and show or hide error messages.
-* Controlling the **Submit** button's enabled state by binding to `NgForm` validity.
-* Custom CSS classes that provide visual feedback to users about invalid controls.
+* An Angular HTML form template
+* A form component class with a `@Component` decorator
+* Handling form submission by binding to the `NgForm.ngSubmit` event property
+* Template-reference variables such as `#heroForm` and `#name`
+* `[(ngModel)]` syntax for two-way data binding
+* The use of `name` attributes for validation and form-element change tracking
+* The reference variable's `valid` property on input controls to check if a control is valid and show or hide error messages
+* Controlling the **Submit** button's enabled state by binding to `NgForm` validity
+* Custom CSS classes that provide visual feedback to users about invalid controls
-Here’s the code for the final version of the application:
+Here's the code for the final version of the application:
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
+
-
+
-
+@reviewed 2022-02-28
diff --git a/aio/content/guide/frequent-ngmodules.md b/aio/content/guide/frequent-ngmodules.md
index 4e166f04f6cee..7aa8194c05dbb 100644
--- a/aio/content/guide/frequent-ngmodules.md
+++ b/aio/content/guide/frequent-ngmodules.md
@@ -2,81 +2,31 @@
An Angular application needs at least one module that serves as the root module.
As you add features to your app, you can add them in modules.
-The following are frequently used Angular modules with examples
-of some of the things they contain:
-
-
-
-
-
-
- NgModule
-
-
-
- Import it from
-
-
-
- Why you use it
-
-
-
-
- BrowserModule
- @angular/platform-browser
- When you want to run your application in a browser
-
-
-
- CommonModule
- @angular/common
- When you want to use NgIf
, NgFor
-
-
-
- FormsModule
- @angular/forms
- When you want to build template driven forms (includes NgModel
)
-
-
-
- ReactiveFormsModule
- @angular/forms
- When you want to build reactive forms
-
-
-
- RouterModule
- @angular/router
- When you want to use RouterLink
, .forRoot()
, and .forChild()
-
-
-
- HttpClientModule
- @angular/common/http
- When you want to communicate with a server using the HTTP protocol
-
-
-
+The following are frequently used Angular modules with examples of some of the things they contain:
+
+| NgModule | Import it from | Why you use it |
+|:--- |:--- |:--- |
+| `BrowserModule` | `@angular/platform-browser` | To run your application in a browser. |
+| `CommonModule` | `@angular/common` | To use `NgIf` and `NgFor`. |
+| `FormsModule` | `@angular/forms` | To build template driven forms \(includes `NgModel`\). |
+| `ReactiveFormsModule` | `@angular/forms` | To build reactive forms. |
+| `RouterModule` | `@angular/router` | To use `RouterLink`, `.forRoot()`, and `.forChild()`. |
+| `HttpClientModule` | `@angular/common/http` | To communicate with a server using the HTTP protocol. |
## Importing modules
-When you use these Angular modules, import them in `AppModule`,
-or your feature module as appropriate, and list them in the `@NgModule`
-`imports` array. For example, in the basic application generated by the [Angular CLI](cli),
-`BrowserModule` is the first import at the top of the `AppModule`,
-`app.module.ts`.
+When you use these Angular modules, import them in `AppModule`, or your feature module as appropriate, and list them in the `@NgModule` `imports` array.
+For example, in the basic application generated by the [Angular CLI](cli), `BrowserModule` is the first import at the top of the `AppModule`, `app.module.ts`.
+
-```typescript
/* import modules so that AppModule can access them */
-import { BrowserModule } from '@angular/platform-browser';
-import { NgModule } from '@angular/core';
+import { BrowserModule } from '@angular/platform-browser';
+import { NgModule } from '@angular/core';
import { AppComponent } from './app.component';
-@NgModule({
+@NgModule({
declarations: [
AppComponent
],
@@ -87,38 +37,41 @@ import { AppComponent } from './app.component';
bootstrap: [AppComponent]
})
export class AppModule { }
-```
-The imports at the top of the array are JavaScript import statements
-while the `imports` array within `@NgModule` is Angular specific.
-For more information on the difference, see [JavaScript Modules vs. NgModules](guide/ngmodule-vs-jsmodule).
+
+The imports at the top of the array are JavaScript import statements while the `imports` array within `@NgModule` is Angular specific.
+For more information on the difference, see [JavaScript Modules vs. NgModules](guide/ngmodule-vs-jsmodule).
## `BrowserModule` and `CommonModule`
-`BrowserModule` imports `CommonModule`, which contributes many common
-directives such as `ngIf` and `ngFor`. Additionally, `BrowserModule`
-re-exports `CommonModule` making all of its directives available
-to any module that imports `BrowserModule`.
+`BrowserModule` imports `CommonModule`, which contributes many common directives such as `ngIf` and `ngFor`.
+Additionally, `BrowserModule` re-exports `CommonModule` making all of its directives available to any module that imports `BrowserModule`.
-For applications that run in the browser, import `BrowserModule` in the
-root `AppModule` because it provides services that are essential
-to launch and run a browser application. `BrowserModule`’s providers
-are for the whole application so it should only be in the root module,
-not in feature modules. Feature modules only need the common
-directives in `CommonModule`; they don’t need to re-install app-wide providers.
+For applications that run in the browser, import `BrowserModule` in the root `AppModule` because it provides services that are essential to launch and run a browser application.
+`BrowserModule`'s providers are for the whole application so it should only be in the root module, not in feature modules.
+Feature modules only need the common directives in `CommonModule`; they don't need to re-install app-wide providers.
-If you do import `BrowserModule` into a lazy loaded feature module,
-Angular returns an error telling you to use `CommonModule` instead.
+If you do import `BrowserModule` into a lazy loaded feature module, Angular returns an error telling you to use `CommonModule` instead.
-
-
+
+
+
## More on NgModules
You may also be interested in the following:
-* [Bootstrapping](guide/bootstrapping).
-* [NgModules](guide/ngmodules).
-* [JavaScript Modules vs. NgModules](guide/ngmodule-vs-jsmodule).
+
+* [Bootstrapping](guide/bootstrapping)
+* [NgModules](guide/ngmodules)
+* [JavaScript Modules vs. NgModules](guide/ngmodule-vs-jsmodule)
+
+
+
+
+
+
+
+@reviewed 2022-02-28
diff --git a/aio/content/guide/glossary.md b/aio/content/guide/glossary.md
index 7d37acdbc8704..ff7420256b7fb 100644
--- a/aio/content/guide/glossary.md
+++ b/aio/content/guide/glossary.md
@@ -1,162 +1,144 @@
# Glossary
Angular has its own vocabulary.
-Most Angular terms are common English words or computing terms
-that have a specific meaning within the Angular system.
-
-This glossary lists the most prominent terms
-and a few less familiar ones with unusual or
-unexpected definitions.
-
-[A](#A) [B](#B) [C](#C) [D](#D) [E](#E) [F](#F) [G](#G) [H](#H) [I](#I)
-[J](#J) [K](#K) [L](#L) [M](#M) [N](#N) [O](#O) [P](#P) [Q](#Q) [R](#R)
-[S](#S) [T](#T) [U](#U) [V](#V) [W](#W) [X](#X) [Y](#Y) [Z](#Z)
-
-
-{@a A}
-{@a aot}
-
+Most Angular terms are common English words or computing terms that have a specific meaning within the Angular system.
+
+This glossary lists the most prominent terms and a few less familiar ones with unusual or unexpected definitions.
+
+[A][AioGuideGlossaryA]
+[B][AioGuideGlossaryB]
+[C][AioGuideGlossaryC]
+[D][AioGuideGlossaryD]
+[E][AioGuideGlossaryE]
+[F][AioGuideGlossaryF]
+[G][AioGuideGlossaryG]
+[H][AioGuideGlossaryH]
+[I][AioGuideGlossaryI]
+[J][AioGuideGlossaryJ]
+[K][AioGuideGlossaryK]
+[L][AioGuideGlossaryL]
+[M][AioGuideGlossaryM]
+[N][AioGuideGlossaryN]
+[O][AioGuideGlossaryO]
+[P][AioGuideGlossaryP]
+[Q][AioGuideGlossaryQ]
+[R][AioGuideGlossaryR]
+[S][AioGuideGlossaryS]
+[T][AioGuideGlossaryT]
+[U][AioGuideGlossaryU]
+[V][AioGuideGlossaryV]
+[W][AioGuideGlossaryW]
+[X][AioGuideGlossaryX]
+[Y][AioGuideGlossaryY]
+[Z][AioGuideGlossaryZ]
+
+
## ahead-of-time (AOT) compilation
-The Angular ahead-of-time (AOT) compiler converts Angular HTML and TypeScript code
-into efficient JavaScript code during the build phase, before the browser downloads
-and runs that code.
-This is the best compilation mode for production environments, with decreased load time and increased performance compared to [just-in-time (JIT) compilation](#jit).
-
-By compiling your application using the `ngc` command-line tool, you can bootstrap directly to a module factory, so you don't need to include the Angular compiler in your JavaScript bundle.
+The Angular ahead-of-time \(AOT\) compiler converts Angular HTML and TypeScript code into efficient JavaScript code during the build phase, before the browser downloads and runs that code.
+This is the best compilation mode for production environments, with decreased load time and increased performance compared to [just-in-time (JIT) compilation][AioGuideGlossaryJustInTimeJitCompilation].
-{@a angular-element}
+By compiling your application using the `ngc` command-line tool, you can bootstrap directly to a module factory, so you do not need to include the Angular compiler in your JavaScript bundle.
## Angular element
-An Angular [component](#component) packaged as a [custom element](#custom-element).
+An Angular [component][AioGuideGlossaryComponent] packaged as a [custom element][AioGuideGlossaryCustomElement].
-Learn more in [Angular Elements Overview](guide/elements).
-
-{@a apf}
+Learn more in [Angular Elements Overview][AioGuideElements].
## Angular package format (APF)
An Angular specific specification for layout of npm packages that is used by all first-party Angular packages, and most third-party Angular libraries.
-Learn more in the [Angular Package Format specification](guide/angular-package-format).
-
-{@a annotation}
+Learn more in the [Angular Package Format specification][AioGuideAngularPackageFormat].
## annotation
-A structure that provides metadata for a class. See [decorator](#decorator).
-
-{@a app-shell}
+A structure that provides metadata for a class.
+To learn more, see [decorator][AioGuideGlossaryDecoratorDecoration].
## app-shell
App shell is a way to render a portion of your application using a route at build time.
This gives users a meaningful first paint of your application that appears quickly because the browser can render static HTML and CSS without the need to initialize JavaScript.
+To learn more, see [The App Shell Model][GoogleDevelopersWebFundamentalsArchitectureAppShell].
-Learn more in [The App Shell Model](https://developers.google.com/web/fundamentals/architecture/app-shell).
-
-You can use the Angular CLI to [generate](cli/generate#app-shell) an app shell.
-This can improve the user experience by quickly launching a static rendered page (a skeleton common to all pages) while the browser downloads the full client version and switches to it automatically after the code loads.
-
-See also [Service Worker and PWA](guide/service-worker-intro).
-{@a architect}
+You can use the Angular CLI to [generate][AioCliGenerateAppShell] an app shell.
+This can improve the user experience by quickly launching a static rendered page while the browser downloads the full client version and switches to it automatically after the code loads.
+A static rendered page is a skeleton common to all pages.
+To learn more, see [Service Worker and PWA][AioGuideServiceWorkerIntro].
## Architect
-The tool that the CLI uses to perform complex tasks such as compilation and test running, according to a provided configuration.
-Architect is a shell that runs a [builder](#builder) (defined in an [npm package](#npm-package)) with a given [target configuration](#target).
-
-In the [workspace configuration file](guide/workspace-config#project-tool-configuration-options), an "architect" section provides configuration options for Architect builders.
+The tool that the Angular CLI uses to perform complex tasks such as compilation and test running, according to a provided configuration.
+Architect is a shell that runs a [builder][AioGuideGlossaryBuilder] with a given [target configuration][AioGuideGlossaryTarget].
+The [builder][AioGuideGlossaryBuilder] is defined in an [npm package][AioGuideGlossaryNpmPackage].
-For example, a built-in builder for linting is defined in the package `@angular-devkit/build_angular:tslint`, which uses the [TSLint](https://palantir.github.io/tslint/) tool to perform linting, with a configuration specified in a `tslint.json` file.
+In the [workspace configuration file][AioGuideWorkspaceConfigProjectToolConfigurationOptions], an "architect" section provides configuration options for Architect builders.
-Use the [CLI command `ng run`](cli/run) to invoke a builder by specifying a [target configuration](#target) associated with that builder.
-Integrators can add builders to enable tools and workflows to run through the Angular CLI. For example, a custom builder can replace the third-party tools used by the built-in implementations for CLI commands such as `ng build` or `ng test`.
+For example, a built-in builder for linting is defined in the package `@angular-devkit/build_angular:tslint`, which uses the [TSLint][GithubPalantirTslint] tool to perform linting, with a configuration specified in a `tslint.json` file.
-{@a attribute-directive}
+Use the [`ng run`][AioCliRun] Angular CLI command to invoke a builder by specifying a [target configuration][AioGuideGlossaryTarget] associated with that builder.
+Integrators can add builders to enable tools and workflows to run through the Angular CLI.
+For example, a custom builder can replace the third-party tools used by the built-in implementations for Angular CLI commands, such as `ng build` or `ng test`.
+## attribute directive
-{@a attribute-directives}
+A category of [directive][AioGuideGlossaryDirective] that can listen to and modify the behavior of other HTML elements, attributes, properties, and components.
+They are usually represented as HTML attributes, hence the name.
-
-## attribute directives
-
-A category of [directive](#directive) that can listen to and modify the behavior of
-other HTML elements, attributes, properties, and components. They are usually represented
-as HTML attributes, hence the name.
-
-Learn more in [Attribute Directives](guide/attribute-directives).
-
-
-{@a B}
-
-{@a binding}
+Learn more in [Attribute Directives][AioGuideAttributeDirectives].
## binding
Generally, the practice of setting a variable or property to a data value.
-Within Angular, typically refers to [data binding](#data-binding),
-which coordinates DOM object properties with data object properties.
+Within Angular, typically refers to [data binding][AioGuideGlossaryDataBinding], which coordinates DOM object properties with data object properties.
-Sometimes refers to a [dependency-injection](#dependency-injection) binding
-between a [token](#token) and a dependency [provider](#provider).
-
-{@a bootstrap}
+Sometimes refers to a [dependency-injection][AioGuideGlossaryDependencyInjectionDi] binding between a [token][AioGuideGlossaryToken] and a dependency [provider][AioGuideGlossaryProvider].
## bootstrap
A way to initialize and launch an application or system.
-In Angular, an application's root NgModule (`AppModule`) has a `bootstrap` property that identifies the application's top-level [components](#component).
+In Angular, the `AppModule` root NgModule of an application has a `bootstrap` property that identifies the top-level [components][AioGuideGlossaryComponent] of the application.
During the bootstrap process, Angular creates and inserts these components into the `index.html` host web page.
-You can bootstrap multiple applications in the same `index.html`. Each application contains its own components.
-
-Learn more in [Bootstrapping](guide/bootstrapping).
+You can bootstrap multiple applications in the same `index.html`.
+Each application contains its own components.
-{@a builder}
+Learn more in [Bootstrapping][AioGuideBootstrapping].
## builder
-A function that uses the [Architect](#architect) API to perform a complex process such as "build" or "test".
-The builder code is defined in an [npm package](#npm-package).
+A function that uses the [Architect][AioGuideGlossaryArchitect] API to perform a complex process such as "build" or "test".
+The builder code is defined in an [npm package][AioGuideGlossaryNpmPackage].
-For example, [BrowserBuilder](https://github.com/angular/angular-cli/tree/master/packages/angular_devkit/build_angular/src/browser) runs a [webpack](https://webpack.js.org/) build for a browser target and [KarmaBuilder](https://github.com/angular/angular-cli/tree/master/packages/angular_devkit/build_angular/src/karma) starts the Karma server and runs a webpack build for unit tests.
+For example, [BrowserBuilder][GithubAngularAngularCliTreePrimaryPackagesAngularDevkitBuildAngularSrcBuildersBrowser] runs a [webpack][JsWebpackMain] build for a browser target and [KarmaBuilder][GithubAngularAngularCliTreePrimaryPackagesAngularDevkitBuildAngularSrcBuildersKarma] starts the Karma server and runs a webpack build for unit tests.
-The [CLI command `ng run`](cli/run) invokes a builder with a specific [target configuration](#target).
-The [workspace configuration](guide/workspace-config) file, `angular.json`, contains default configurations for built-in builders.
+The [`ng run`][AioCliRun] Angular CLI command invokes a builder with a specific [target configuration][AioGuideGlossaryTarget].
+The [workspace configuration][AioGuideWorkspaceConfig] file, `angular.json`, contains default configurations for built-in builders.
-{@a C}
+
-{@a case-conventions}
-{@a dash-case}
-{@a camelcase}
-{@a kebab-case}
+
+
## case types
-Angular uses capitalization conventions to distinguish the names of various types, as described in the [naming guidelines section](guide/styleguide#02-01) of the Style Guide. Here's a summary of the case types:
-
-* camelCase : Symbols, properties, methods, pipe names, non-component directive selectors, constants.
-Standard or lower camel case uses lowercase on the first letter of the item. For example, "selectedHero".
-
-* UpperCamelCase (or PascalCase): Class names, including classes that define components, interfaces, NgModules, directives, and pipes,
-Upper camel case uses uppercase on the first letter of the item. For example, "HeroListComponent".
-
-* dash-case (or "kebab-case"): Descriptive part of file names, component selectors. For example, "app-hero-list".
-
-* underscore_case (or "snake_case"): Not typically used in Angular. Snake case uses words connected with underscores.
-For example, "convert_link_mode".
+Angular uses capitalization conventions to distinguish the names of various types, as described in the [naming guidelines section][AioGuideStyleguide0201] of the Style Guide.
+Here is a summary of the case types:
-* UPPER_UNDERSCORE_CASE (or UPPER_SNAKE_CASE, or SCREAMING_SNAKE_CASE): Traditional for constants (acceptable, but prefer camelCase).
-Upper snake case uses words in all capital letters connected with underscores. For example, "FIX_ME".
-
-{@a change-detection}
+| | Details | example |
+|:--- |:--- |:--- |
+| camelCase | Symbols, properties, methods, pipe names, non-component directive selectors, constants.
Standard or lower camel case uses lowercase on the first letter of the item. | `selectedHero` |
+| UpperCamelCase
PascalCase | Class names, including classes that define components, interfaces, NgModules, directives, and pipes.
Upper camel case uses uppercase on the first letter of the item. | `HeroListComponent` |
+| dash-case
kebab-case | Descriptive part of file names, component selectors. | `app-hero-list` |
+| underscore_case
snake_case | Not typically used in Angular.
Snake case uses words connected with underscores. | `convert_link_mode` |
+| UPPER_UNDERSCORE_CASE
UPPER_SNAKE_CASE
SCREAMING_SNAKE_CASE | Traditional for constants.
This case is acceptable, but camelCase is preferred.
Upper snake case uses words in all capital letters connected with underscores. | `FIX_ME` |
## change detection
-The mechanism by which the Angular framework synchronizes the state of an application's UI with the state of the data.
+The mechanism by which the Angular framework synchronizes the state of the UI of an application with the state of the data.
The change detector checks the current state of the data model whenever it runs, and maintains it as the previous state to compare on the next iteration.
As the application logic updates component data, values that are bound to DOM properties in the view can change.
@@ -164,689 +146,571 @@ The change detector is responsible for updating the view to reflect the current
Similarly, the user can interact with the UI, causing events that change the state of the data model.
These events can trigger change detection.
-Using the default change-detection strategy, the change detector goes through the [view hierarchy](#view-tree) on each VM turn to check every [data-bound property](#data-binding) in the template. In the first phase, it compares the current state of the dependent data with the previous state, and collects changes.
+Using the default change-detection strategy, the change detector goes through the [view hierarchy][AioGuideGlossaryViewHierarchy] on each VM turn to check every [data-bound property][AioGuideGlossaryDataBinding] in the template.
+In the first phase, it compares the current state of the dependent data with the previous state, and collects changes.
In the second phase, it updates the page DOM to reflect any new data values.
-If you set the `OnPush` change-detection strategy, the change detector runs only when [explicitly invoked](api/core/ChangeDetectorRef), or when it is triggered by an `Input` reference change or event handler. This typically improves performance. For more information, see [Optimize Angular's change detection](https://web.dev/faster-angular-change-detection/).
+If you set the `OnPush` change-detection strategy, the change detector runs only when [explicitly invoked][AioApiCoreChangedetectorref], or when it is triggered by an `Input` reference change or event handler.
+This typically improves performance.
+To learn more, see [Optimize the change detection in Angular][WebDevFasterAngularChangeDetection].
-{@a class-decorator}
+
## class decorator
-A [decorator](#decorator) that appears immediately before a class definition, which declares the class to be of the given type, and provides metadata suitable to the type.
-
-The following decorators can declare Angular class types:
-* `@Component()`
-* `@Directive()`
-* `@Pipe()`
-* `@Injectable()`
-* `@NgModule()`
+A [decorator][AioGuideGlossaryDecoratorDecoration] that appears immediately before a class definition, which declares the class to be of the given type, and provides metadata suitable to the type.
+The following decorators can declare Angular class types.
-{@a class-field-decorator}
+* `@Component()`
+* `@Directive()`
+* `@Pipe()`
+* `@Injectable()`
+* `@NgModule()`
## class field decorator
-A [decorator](#decorator) statement immediately before a field in a class definition that declares the type of that field. Some examples are `@Input` and `@Output`.
-
-{@a collection}
+A [decorator][AioGuideGlossaryDecoratorDecoration] statement immediately before a field in a class definition that declares the type of that field.
+Some examples are `@Input` and `@Output`.
## collection
-In Angular, a set of related [schematics](#schematic) collected in an [npm package](#npm-package).
+In Angular, a set of related [schematics][AioGuideGlossarySchematic] collected in an [npm package][AioGuideGlossaryNpmPackage].
-{@a cli}
+
## command-line interface (CLI)
-The [Angular CLI](cli) is a command-line tool for managing the Angular development cycle. Use it to create the initial filesystem scaffolding for a [workspace](#workspace) or [project](#project), and to run [schematics](#schematic) that add and modify code for initial generic versions of various elements. The CLI supports all stages of the development cycle, including building, testing, bundling, and deployment.
+The [Angular CLI][AioCliMain] is a command-line tool for managing the Angular development cycle.
+Use it to create the initial filesystem scaffolding for a [workspace][AioGuideGlossaryWorkspace] or [project][AioGuideGlossaryProject], and to run [schematics][AioGuideGlossarySchematic] that add and modify code for initial generic versions of various elements.
+The Angular CLI supports all stages of the development cycle, including building, testing, bundling, and deployment.
-* To begin using the CLI for a new project, see [Local Environment Setup](guide/setup-local "Setting up for Local Development").
-* To learn more about the full capabilities of the CLI, see the [CLI command reference](cli).
+* To begin using the Angular CLI for a new project, see [Local Environment Setup][AioGuideSetupLocal].
+* To learn more about the full capabilities of the Angular CLI, see the [Angular CLI command reference][AioCliMain].
-See also [Schematics CLI](#schematics-cli).
-
-{@a component}
+See also [Schematics CLI][AioGuideGlossarySchematicsCli].
## component
-A class with the `@Component()` [decorator](#decorator) that associates it with a companion [template](#template). Together, the component class and template define a [view](#view).
-A component is a special type of [directive](#directive).
+A class with the `@Component()` [decorator][AioGuideGlossaryDecoratorDecoration] that associates it with a companion [template][AioGuideGlossaryTemplate].
+Together, the component class and template define a [view][AioGuideGlossaryView].
+A component is a special type of [directive][AioGuideGlossaryDirective].
The `@Component()` decorator extends the `@Directive()` decorator with template-oriented features.
-An Angular component class is responsible for exposing data and handling most of the view's display and user-interaction logic through [data binding](#data-binding).
-
-Read more about component classes, templates, and views in [Introduction to Angular concepts](guide/architecture).
+An Angular component class is responsible for exposing data and handling most of the display and user-interaction logic of the view through [data binding][AioGuideGlossaryDataBinding].
+Read more about component classes, templates, and views in [Introduction to Angular concepts][AioGuideArchitecture].
## configuration
-See [workspace configuration](#cli-config)
-
-{@a content-projection}
+See [workspace configuration][AioGuideGlossaryWorkspaceConfig]
## content projection
-A way to insert DOM content from outside a component into the component's view in a designated spot.
+A way to insert DOM content from outside a component into the view of the component in a designated spot.
-For more information, see [Responding to changes in content](guide/lifecycle-hooks#content-projection).
-
-{@a custom-element}
+To learn more, see [Responding to changes in content][AioGuideLifecycleHooksRespondingToProjectedContentChanges].
## custom element
-A web platform feature, currently supported by most browsers and available in other browsers through polyfills (see [Browser support](guide/browser-support)).
-
-The custom element feature extends HTML by allowing you to define a tag whose content is created and controlled by JavaScript code. A custom element (also called a *web component*) is recognized by a browser when it's added to the [CustomElementRegistry](https://developer.mozilla.org/en-US/docs/Web/API/CustomElementRegistry).
-
-You can use the API to transform an Angular component so that it can be registered with the browser and used in any HTML that you add directly to the DOM within an Angular application. The custom element tag inserts the component's view, with change-detection and data-binding functionality, into content that would otherwise be displayed without Angular processing.
-
-See [Angular element](#angular-element).
-
-See also [dynamic component loading](#dynamic-components).
-
+A web platform feature, currently supported by most browsers and available in other browsers through polyfills.
+See [Browser support][AioGuideBrowserSupport].
-{@a D}
+The custom element feature extends HTML by allowing you to define a tag whose content is created and controlled by JavaScript code.
+A custom element is recognized by a browser when it is added to the [CustomElementRegistry][MdnDocsWebApiCustomelementregistry].
+A custom element is also refernced as a *web component*.
-{@a data-binding}
+You can use the API to transform an Angular component so that it can be registered with the browser and used in any HTML that you add directly to the DOM within an Angular application.
+The custom element tag inserts the view of the component, with change-detection and data-binding functionality, into content that would otherwise be displayed without Angular processing.
+See [Angular element][AioGuideGlossaryAngularElement].
+See also [dynamic component loading][AioGuideGlossaryDynamicComponentLoading].
## data binding
-A process that allows applications to display data values to a user and respond to user
-actions (such as clicks, touches, and keystrokes).
+A process that allows applications to display data values to a user and respond to user actions.
+User actions include clicks, touches, keystrokes, and so on.
-In data binding, you declare the relationship between an HTML widget and a data source
-and let the framework handle the details.
-Data binding is an alternative to manually pushing application data values into HTML, attaching
-event listeners, pulling changed values from the screen, and
-updating application data values.
+In data binding, you declare the relationship between an HTML widget and a data source and let the framework handle the details.
+Data binding is an alternative to manually pushing application data values into HTML, attaching event listeners, pulling changed values from the screen, and updating application data values.
-Read about the following forms of binding in Angular's [Template Syntax](guide/template-syntax):
+Read about the following forms of binding of the [Template Syntax][AioGuideTemplateSyntax] in Angular:
- * [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}
+* [Interpolation][AioGuideInterpolation]
+* [Property binding][AioGuidePropertyBinding]
+* [Event binding][AioGuideEventBinding]
+* [Attribute binding][AioGuideAttributeBinding]
+* [Class binding][AioGuideAttributeBindingBindingToTheClassAttribute]
+* [Style binding][AioGuideAttributeBindingBindingToTheStyleAttribute]
+* [Two-way data binding with ngModel][AioGuideBuiltInDirectivesDisplayingAndUpdatingPropertiesWithNgmodel]
## declarable
-A class type that you can add to the `declarations` list of an [NgModule](#ngmodule).
-You can declare [components](#component), [directives](#directive), and [pipes](#pipe).
-
-Don't declare the following:
-* A class that's already declared in another NgModule
-* An array of directives imported from another package. For example, don't declare `FORMS_DIRECTIVES` from `@angular/forms`
-* NgModule classes
-* Service classes
-* Non-Angular classes and objects, such as strings, numbers, functions, entity models, configurations, business logic, and helper classes
+A class type that you can add to the `declarations` list of an [NgModule][AioGuideGlossaryNgmodule].
+You can declare [components][AioGuideGlossaryComponent], [directives][AioGuideGlossaryDirective], and [pipes][AioGuideGlossaryPipe].
+Do not declare the following:
-{@a decorator}
+* A class that is already declared in another NgModule
+* An array of directives imported from another package.
+ For example, do not declare `FORMS_DIRECTIVES` from `@angular/forms`
-{@a decoration}
+* NgModule classes
+* Service classes
+* Non-Angular classes and objects, such as strings, numbers, functions, entity models, configurations, business logic, and helper classes
## decorator | decoration
-A function that modifies a class or property definition. Decorators (also called *annotations*) are an experimental (stage 2) [JavaScript language feature](https://github.com/wycats/javascript-decorators).
+A function that modifies a class or property definition.
+Decorators are an experimental \(stage 2\) [JavaScript language feature][GithubWycatsJavascriptDecorators].
+A decorator is also referenced as an *annotation*.
TypeScript adds support for decorators.
-Angular defines decorators that attach metadata to classes or properties
-so that it knows what those classes or properties mean and how they should work.
-
-See [class decorator](#class-decorator), [class field decorator](#class-field-decorator).
+Angular defines decorators that attach metadata to classes or properties so that it knows what those classes or properties mean and how they should work.
-{@a di}
-
-{@a dependency-injection}
+To learn more, see [class decorator][AioGuideGlossaryClassDecorator].
+See also [class field decorator][AioGuideGlossaryClassFieldDecorator].
## dependency injection (DI)
-A design pattern and mechanism for creating and delivering some parts of an application (dependencies) to other parts of an application that require them.
+A design pattern and mechanism for creating and delivering some parts of an application \(dependencies\) to other parts of an application that require them.
In Angular, dependencies are typically services, but they also can be values, such as strings or functions.
-An [injector](#injector) for an application (created automatically during bootstrap) instantiates dependencies when needed, using a configured [provider](#provider) of the service or value.
-
-Learn more in [Dependency Injection in Angular](guide/dependency-injection).
-
-{@a di-token}
+An [injector][AioGuideGlossaryInjector] for an application \(created automatically during bootstrap\) instantiates dependencies when needed, using a configured [provider][AioGuideGlossaryProvider] of the service or value.
+Learn more in [Dependency Injection in Angular][AioGuideDependencyInjection].
## DI token
-A lookup token associated with a dependency [provider](#provider), for use with the [dependency injection](#di) system.
-
-{@a directive}
-{@a directives}
+A lookup token associated with a dependency [provider][AioGuideGlossaryProvider], for use with the [dependency injection][AioGuideGlossaryDependencyInjectionDi] system.
## directive
-A class that can modify the structure of the DOM or modify attributes in the DOM and component data model. A directive class definition is immediately preceded by a `@Directive()` [decorator](#decorator) that supplies metadata.
+A class that can modify the structure of the DOM or modify attributes in the DOM and component data model.
+A directive class definition is immediately preceded by a `@Directive()` [decorator][AioGuideGlossaryDecoratorDecoration] that supplies metadata.
-A directive class is usually associated with an HTML element or attribute, and that element or attribute is often referred to as the directive itself. When Angular finds a directive in an HTML [template](#template), it creates the matching directive class instance and gives the instance control over that portion of the browser DOM.
+A directive class is usually associated with an HTML element or attribute, and that element or attribute is often referred to as the directive itself.
+When Angular finds a directive in an HTML [template][AioGuideGlossaryTemplate], it creates the matching directive class instance and gives the instance control over that portion of the browser DOM.
There are three categories of directive:
-* [Components](#component) use `@Component()` (an extension of `@Directive()`) to associate a template with a class.
-* [Attribute directives](#attribute-directive) modify behavior and appearance of page elements.
+* [Components][AioGuideGlossaryComponent] use `@Component()` to associate a template with a class.
+ `@Component()` is an extension of `@Directive()`.
-* [Structural directives](#structural-directive) modify the structure of the DOM.
+* [Attribute directives][AioGuideGlossaryAttributeDirective] modify behavior and appearance of page elements.
+* [Structural directives][AioGuideGlossaryStructuralDirective] modify the structure of the DOM.
Angular supplies a number of built-in directives that begin with the `ng` prefix.
You can also create new directives to implement your own functionality.
-You associate a *selector* (an HTML tag such as `
`) with a custom directive; this extends the [template syntax](guide/template-syntax) that you can use in your applications.
+You associate a *selector* with a custom directive; this extends the [template syntax][AioGuideTemplateSyntax] that you can use in your applications.
+A *selector* is an HTML tag, such as ``.
**UpperCamelCase**, such as `NgIf`, refers to a directive class.
You can use **UpperCamelCase** when describing properties and directive behavior.
-**lowerCamelCase**, such as `ngIf` refers to a directive's attribute name.
+**lowerCamelCase**, such as `ngIf` refers to the attribute name of a directive.
You can use **lowerCamelCase** when describing how to apply the directive to an element in the HTML template.
-{@a dom}
-
## domain-specific language (DSL)
-A special-purpose library or API; see [Domain-specific language](https://en.wikipedia.org/wiki/Domain-specific_language).
-Angular extends TypeScript with domain-specific languages for a number of domains relevant to Angular applications, defined in NgModules such as [animations](guide/animations), [forms](guide/forms), and [routing and navigation](guide/router).
-
-{@a dynamic-components}
+A special-purpose library or API.
+To learn more, see [Domain-specific language][WikipediaWikiDomainSpecificLanguage].
+Angular extends TypeScript with domain-specific languages for a number of domains relevant to Angular applications, defined in NgModules such as [animations][AioGuideAnimations], [forms][AioGuideForms], and [routing and navigation][AioGuideRouter].
## dynamic component loading
-A technique for adding a component to the DOM at run time. Requires that you exclude the component from compilation and then connect it to Angular's change-detection and event-handling framework when you add it to the DOM.
-
-See also [custom element](#custom-element), which provides an easier path with the same result.
-
+A technique for adding a component to the DOM at run time.
+Requires that you exclude the component from compilation and then connect it to the change-detection and event-handling framework of Angular when you add it to the DOM.
-{@a E}
-
-{@a eager-loading}
+See also [custom element][AioGuideGlossaryCustomElement], which provides an easier path with the same result.
## eager loading
-NgModules or components that are loaded on launch are called eager-loaded, to distinguish them from those
-that are loaded at run time (lazy-loaded).
-See [lazy loading](#lazy-load).
-
-
-{@a ecma}
+NgModules or components that are loaded on launch are referenced as eager-loaded, to distinguish them from those that are loaded at run time that are refernced as lazy-loaded.
+See also [lazy loading][AioGuideGlossaryLazyLoading].
## ECMAScript
-The [official JavaScript language specification](https://en.wikipedia.org/wiki/ECMAScript).
-
-Not all browsers support the latest ECMAScript standard, but you can use a [transpiler](#transpile) (like [TypeScript](#typescript)) to write code using the latest features, which will then be transpiled to code that runs on versions that are supported by browsers.
-
-To learn more, see [Browser Support](guide/browser-support).
-
+The [official JavaScript language specification][WikipediaWikiEcmascript].
-{@a element}
+Not all browsers support the latest ECMAScript standard, but you can use a [transpiler][AioGuideGlossaryTranspile] to write code using the latest features, which will then be transpiled to code that runs on versions that are supported by browsers.
+A example of a [transpiler][AioGuideGlossaryTranspile] is [TypeScript][AioGuideGlossaryTypescript].
+To learn more, see [Browser Support][AioGuideBrowserSupport].
## element
Angular defines an `ElementRef` class to wrap render-specific native UI elements.
-In most cases, this allows you to use Angular templates and data binding to access DOM elements
-without reference to the native element.
+In most cases, this allows you to use Angular templates and data binding to access DOM elements without reference to the native element.
-The documentation generally refers to *elements* (`ElementRef` instances), as distinct from *DOM elements*
-(which can be accessed directly if necessary).
+The documentation generally refers to *elements* as distinct from *DOM elements*.
+*Elements* are instances of a `ElementRef` class.
+*DOM elements* are able to be accessed directly, if necessary.
-Compare to [custom element](#custom-element).
-
-{@a entry-point}
+To learn more, see also [custom element][AioGuideGlossaryCustomElement].
## entry point
-A [JavaScript module](#module) that is intended to be imported by a user of [an
-npm package](guide/npm-packages). An entry-point module typically re-exports
-symbols from other internal modules. A package can contain multiple
-entry points. For example, the `@angular/core` package has two entry-point
-modules, which can be imported using the module names `@angular/core` and
-`@angular/core/testing`.
-
-{@a F}
-
-{@a form-control}
+A [JavaScript module][AioGuideGlossaryModule] that is intended to be imported by a user of an [npm package][AioGuideNpmPackages].
+An entry-point module typically re-exports symbols from other internal modules.
+A package can contain multiple entry points.
+For example, the `@angular/core` package has two entry-point modules, which can be imported using the module names `@angular/core` and `@angular/core/testing`.
## form control
-A instance of `FormControl`, which is a fundamental building block for Angular forms. Together with `FormGroup` and `FormArray`, tracks the value, validation, and status of a form input element.
+A instance of `FormControl`, which is a fundamental building block for Angular forms.
+Together with `FormGroup` and `FormArray`, tracks the value, validation, and status of a form input element.
-Read more forms in the [Introduction to forms in Angular](guide/forms-overview).
-
-{@a form-model}
+Read more forms in the [Introduction to forms in Angular][AioGuideFormsOverview].
## form model
-The "source of truth" for the value and validation status of a form input element at a given point in time. When using [reactive forms](#reactive-forms), the form model is created explicitly in the component class. When using [template-driven forms](#template-driven-forms), the form model is implicitly created by directives.
-
-Learn more about reactive and template-driven forms in the [Introduction to forms in Angular](guide/forms-overview).
+The "source of truth" for the value and validation status of a form input element at a given point in time.
+When using [reactive forms][AioGuideGlossaryReactiveForms], the form model is created explicitly in the component class.
+When using [template-driven forms][AioGuideGlossaryTemplateDrivenForms], the form model is implicitly created by directives.
-{@a form-validation}
+Learn more about reactive and template-driven forms in the [Introduction to forms in Angular][AioGuideFormsOverview].
## form validation
-A check that runs when form values change and reports whether the given values are correct and complete, according to the defined constraints. Reactive forms apply [validator functions](guide/form-validation#adding-to-reactive-forms). Template-driven forms use [validator directives](guide/form-validation#adding-to-template-driven-forms).
-
+A check that runs when form values change and reports whether the given values are correct and complete, according to the defined constraints.
+Reactive forms apply [validator functions][AioGuideFormValidationAddingCustomValidatorsToReactiveForms].
+Template-driven forms use [validator directives][AioGuideFormValidationAddingCustomValidatorsToTemplateDrivenForms].
-To learn more, see [Form Validation](guide/form-validation).
-
-{@a G}
-
-
-{@a H}
-
-{@a I}
-
-
-{@a immutability}
+To learn more, see [Form Validation][AioGuideFormValidation].
## immutability
-The inability to alter the state of a value after its creation. [Reactive forms](#reactive-forms) perform immutable changes in that
-each change to the data model produces a new data model rather than modifying the existing one. [Template-driven forms](#template-driven-forms) perform mutable changes with `NgModel` and [two-way data binding](#data-binding) to modify the existing data model in place.
-
-{@a injectable}
+The inability to alter the state of a value after its creation.
+[Reactive forms][AioGuideGlossaryReactiveForms] perform immutable changes in that each change to the data model produces a new data model rather than modifying the existing one.
+[Template-driven forms][AioGuideGlossaryTemplateDrivenForms] perform mutable changes with `NgModel` and [two-way data binding][AioGuideGlossaryDataBinding] to modify the existing data model in place.
## injectable
-An Angular class or other definition that provides a dependency using the [dependency injection](#di) mechanism. An injectable [service](#service) class must be marked by the `@Injectable()` [decorator](#decorator). Other items, such as constant values, can also be injectable.
-
-{@a injector}
+An Angular class or other definition that provides a dependency using the [dependency injection][AioGuideGlossaryDependencyInjectionDi] mechanism.
+An injectable [service][AioGuideGlossaryService] class must be marked by the `@Injectable()` [decorator][AioGuideGlossaryDecoratorDecoration].
+Other items, such as constant values, can also be injectable.
## injector
-An object in the Angular [dependency-injection](#dependency-injection) system
-that can find a named dependency in its cache or create a dependency
-using a configured [provider](#provider).
-Injectors are created for NgModules automatically as part of the bootstrap process
-and are inherited through the component hierarchy.
-
-* An injector provides a singleton instance of a dependency, and can inject this same instance in multiple components.
-
-* A hierarchy of injectors at the NgModule and component level can provide different instances of a dependency to their own components and child components.
-
-* You can configure injectors with different providers that can provide different implementations of the same dependency.
+An object in the Angular [dependency-injection][AioGuideGlossaryDependencyInjectionDi] system that can find a named dependency in its cache or create a dependency using a configured [provider][AioGuideGlossaryProvider].
+Injectors are created for NgModules automatically as part of the bootstrap process and are inherited through the component hierarchy.
-Learn more about the injector hierarchy in [Hierarchical Dependency Injectors](guide/hierarchical-dependency-injection).
+* An injector provides a singleton instance of a dependency, and can inject this same instance in multiple components.
+* A hierarchy of injectors at the NgModule and component level can provide different instances of a dependency to their own components and child components.
+* You can configure injectors with different providers that can provide different implementations of the same dependency.
-{@a input}
+Learn more about the injector hierarchy in [Hierarchical Dependency Injectors][AioGuideHierarchicalDependencyInjection].
## 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/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.
+When defining a [directive][AioGuideGlossaryDirective], the `@Input()` decorator on a directive property makes that property available as a *target* of a [property binding][AioGuidePropertyBinding].
+Data values flow into an input property from the data source identified in the [template expression][AioGuideGlossaryTemplateExpression] to the right of the equal sign.
-To learn more, see [input and output properties](guide/inputs-outputs).
-
-{@a interpolation}
+To learn more, see [`@Input()` and `@Output()` decorator functions][AioGuideInputsOutputs].
## interpolation
-A form of property [data binding](#data-binding) in which a [template expression](#template-expression) between double-curly braces renders as text.
-That text can be concatenated with neighboring text before it is assigned to an element property
-or displayed between element tags, as in this example.
+A form of property [data binding][AioGuideGlossaryDataBinding] in which a [template expression][AioGuideGlossaryTemplateExpression] between double-curly braces renders as text.
+That text can be concatenated with neighboring text before it is assigned to an element property or displayed between element tags, as in this example.
-```html
-My current hero is {{hero.name}}
-```
+
+<label>My current hero is {{hero.name}}</label>
-Read more in the [Interpolation](guide/interpolation) guide.
+
-{@a ivy}
+Read more in the [Interpolation][AioGuideInterpolation] guide.
## Ivy
-Ivy is the historical code name for Angular's current
-[compilation and rendering pipeline](https://blog.angular.io/a-plan-for-version-8-0-and-ivy-b3318dfc19f7).
+Ivy is the historical code name for the current [compilation and rendering pipeline][AngularBlogAPlanForVersion80AndIvyB3318dfc19f7] in Angular.
It is now the only supported engine, so everything uses Ivy.
-
-{@a J}
-
-{@a javascript}
-
## JavaScript
-See [ECMAScript](#ecma), [TypeScript](#typescript).
-
-
-{@a jit}
+To learn more, see [ECMAScript][AioGuideGlossaryEcmascript].
+To learn more, see also [TypeScript][AioGuideGlossaryTypescript].
+
## just-in-time (JIT) compilation
-The Angular just-in-time (JIT) compiler converts your Angular HTML and TypeScript code into
-efficient JavaScript code at run time, as part of bootstrapping.
-
-JIT compilation is the default (as opposed to AOT compilation) when you run Angular's `ng build` and `ng serve` CLI commands, and is a good choice during development.
-JIT mode is strongly discouraged for production use
-because it results in large application payloads that hinder the bootstrap performance.
-
-Compare to [ahead-of-time (AOT) compilation](#aot).
-
-
-{@a K}
-
+The Angular just-in-time \(JIT\) compiler converts your Angular HTML and TypeScript code into efficient JavaScript code at run time, as part of bootstrapping.
-{@a L}
+JIT compilation is the default \(as opposed to AOT compilation\) when you run the `ng build` and `ng serve` Angular CLI commands, and is a good choice during development.
+JIT mode is strongly discouraged for production use because it results in large application payloads that hinder the bootstrap performance.
-{@a lazy-load}
+Compare to [ahead-of-time (AOT) compilation][AioGuideGlossaryAheadOfTimeAotCompilation].
## lazy loading
A process that speeds up application load time by splitting the application into multiple bundles and loading them on demand.
-For example, dependencies can be lazy loaded as needed—as opposed to [eager-loaded](#eager-loading) modules that are required by the root module and are thus loaded on launch.
+For example, dependencies can be lazy loaded as needed.
+The example differs from [eager-loaded][AioGuideGlossaryEagerLoading] modules that are required by the root module and are loaded on launch.
-The [router](#router) makes use of lazy loading to load child views only when the parent view is activated.
+The [router][AioGuideGlossaryRouter] makes use of lazy loading to load child views only when the parent view is activated.
Similarly, you can build custom elements that can be loaded into an Angular application when needed.
-{@a library}
-
## library
-In Angular, a [project](#project) that provides functionality that can be included in other Angular applications.
-A library isn't a complete Angular application and can't run independently.
-(To add re-usable Angular functionality to non-Angular web applications, you can use Angular [custom elements](#angular-element).)
-
-* Library developers can use the [Angular CLI](#cli) to `generate` scaffolding for a new library in an existing [workspace](#workspace), and can publish a library as an `npm` package.
+In Angular, a [project][AioGuideGlossaryProject] that provides functionality that can be included in other Angular applications.
+A library is not a complete Angular application and cannot run independently.
-* Application developers can use the [Angular CLI](#cli) to `add` a published library for use with an application in the same [workspace](#workspace).
+To add re-usable Angular functionality to non-Angular web applications, use Angular [custom elements][AioGuideGlossaryAngularElement].
-See also [schematic](#schematic).
+* Library developers can use the [Angular CLI][AioGuideGlossaryCommandLineInterfaceCli] to `generate` scaffolding for a new library in an existing [workspace][AioGuideGlossaryWorkspace], and can publish a library as an `npm` package.
+* Application developers can use the [Angular CLI][AioGuideGlossaryCommandLineInterfaceCli] to `add` a published library for use with an application in the same [workspace][AioGuideGlossaryWorkspace].
-{@a lifecycle-hook}
+See also [schematic][AioGuideGlossarySchematic].
## lifecycle hook
-An interface that allows you to tap into the lifecycle of [directives](#directive) and [components](#component) as they are created, updated, and destroyed.
+An interface that allows you to tap into the lifecycle of [directives][AioGuideGlossaryDirective] and [components][AioGuideGlossaryComponent] as they are created, updated, and destroyed.
Each interface has a single hook method whose name is the interface name prefixed with `ng`.
For example, the `OnInit` interface has a hook method named `ngOnInit`.
-Angular calls these hook methods in the following order:
-
-* `ngOnChanges`: When an [input](#input) binding value changes.
-* `ngOnInit`: After the first `ngOnChanges`.
-* `ngDoCheck`: Developer's custom change detection.
-* `ngAfterContentInit`: After component content initialized.
-* `ngAfterContentChecked`: After every check of component content.
-* `ngAfterViewInit`: After a component's views are initialized.
-* `ngAfterViewChecked`: After every check of a component's views.
-* `ngOnDestroy`: Just before the directive is destroyed.
+Angular runs these hook methods in the following order:
-To learn more, see [Lifecycle Hooks](guide/lifecycle-hooks).
+| | hook method | Details |
+|:--- |:--- |:--- |
+| 1 | `ngOnChanges` | When an [input][AioGuideGlossaryInput] or [output][AioGuideGlossaryOutput] binding value changes. |
+| 2 | `ngOnInit` | After the first `ngOnChanges`. |
+| 3 | `ngDoCheck` | Developer's custom change detection. |
+| 4 | `ngAfterContentInit` | After component content initialized. |
+| 5 | `ngAfterContentChecked` | After every check of component content. |
+| 6 | `ngAfterViewInit` | After the views of a component are initialized. |
+| 7 | `ngAfterViewChecked` | After every check of the views of a component. |
+| 8 | `ngOnDestroy` | Just before the directive is destroyed. |
-{@a M}
-
-{@a module}
+To learn more, see [Lifecycle Hooks][AioGuideLifecycleHooks].
## module
-In general, a module collects a block of code dedicated to a single purpose. Angular uses standard JavaScript modules and also defines an Angular module, `NgModule`.
-
-In JavaScript (ECMAScript), each file is a module and all objects defined in the file belong to that module. Objects can be exported, making them public, and public objects can be imported for use by other modules.
-
-Angular ships as a collection of JavaScript modules (also called libraries). Each Angular library name begins with the `@angular` prefix. Install Angular libraries with the [npm package manager](https://docs.npmjs.com/getting-started/what-is-npm) and import parts of them with JavaScript `import` declarations.
+In general, a module collects a block of code dedicated to a single purpose.
+Angular uses standard JavaScript modules and also defines an Angular module, `NgModule`.
-Compare to [NgModule](#ngmodule).
+In JavaScript, or ECMAScript, each file is a module and all objects defined in the file belong to that module.
+Objects can be exported, making them public, and public objects can be imported for use by other modules.
+Angular ships as a collection of JavaScript modules.
+A collection of JavaScript modules are also referenced as a library.
+Each Angular library name begins with the `@angular` prefix.
+Install Angular libraries with the [npm package manager][NpmjsDocsAboutNpm] and import parts of them with JavaScript `import` declarations.
-{@a N}
-
-{@a ngcc}
+Compare to [NgModule][AioGuideGlossaryNgmodule].
## ngcc
Angular compatibility compiler.
-If you build your application using [Ivy](#ivy), but it depends on libraries that have not been compiled with Ivy, the CLI uses `ngcc` to automatically update the dependent libraries to use Ivy.
-
-
-{@a ngmodule}
+If you build your application using [Ivy][AioGuideGlossaryIvy], but it depends on libraries that have not been compiled with Ivy, the Angular CLI uses `ngcc` to automatically update the dependent libraries to use Ivy.
## NgModule
-A class definition preceded by the `@NgModule()` [decorator](#decorator), which declares and serves as a manifest for a block of code dedicated to an application domain, a workflow, or a closely related set of capabilities.
+A class definition preceded by the `@NgModule()` [decorator][AioGuideGlossaryDecoratorDecoration], which declares and serves as a manifest for a block of code dedicated to an application domain, a workflow, or a closely related set of capabilities.
-Like a [JavaScript module](#module), an NgModule can export functionality for use by other NgModules and import public functionality from other NgModules.
-The metadata for an NgModule class collects components, directives, and pipes that the application uses along with the list of imports and exports. See also [declarable](#declarable).
+Like a [JavaScript module][AioGuideGlossaryModule], an NgModule can export functionality for use by other NgModules and import public functionality from other NgModules.
+The metadata for an NgModule class collects components, directives, and pipes that the application uses along with the list of imports and exports.
+See also [declarable][AioGuideGlossaryDeclarable].
-NgModules are typically named after the file in which the exported thing is defined. For example, the Angular [DatePipe](api/common/DatePipe) class belongs to a feature module named `date_pipe` in the file `date_pipe.ts`. You import them from an Angular [scoped package](#scoped-package) such as `@angular/core`.
+NgModules are typically named after the file in which the exported thing is defined.
+For example, the Angular [DatePipe][AioApiCommonDatepipe] class belongs to a feature module named `date_pipe` in the file `date_pipe.ts`.
+You import them from an Angular [scoped package][AioGuideGlossaryScopedPackage] such as `@angular/core`.
-Every Angular application has a root module. By convention, the class is called `AppModule` and resides in a file named `app.module.ts`.
+Every Angular application has a root module.
+By convention, the class is named `AppModule` and resides in a file named `app.module.ts`.
-To learn more, see [NgModules](guide/ngmodules).
-
-{@a npm-package}
+To learn more, see [NgModules][AioGuideNgmodules].
## npm package
-The [npm package manager](https://docs.npmjs.com/getting-started/what-is-npm) is used to distribute and load Angular modules and libraries.
-
-Learn more about how Angular uses [Npm Packages](guide/npm-packages).
+The [npm package manager][NpmjsDocsAboutNpm] is used to distribute and load Angular modules and libraries.
-{@a ngc}
+Learn more about how Angular uses [Npm Packages][AioGuideNpmPackages].
## ngc
-`ngc` is a Typescript-to-Javascript transpiler that processes Angular decorators, metadata, and templates, and emits JavaScript code.
-The most recent implementation is internally referred to as `ngtsc` because it's a minimalistic wrapper around the TypeScript compiler `tsc` that adds a transform for processing Angular code.
-
-{@a O}
-{@a observable}
+`ngc` is a Typescript-to-Javascript transpiler that processes Angular decorators, metadata, and templates, and emits JavaScript code.
+The most recent implementation is internally referred to as `ngtsc` because it is a minimalistic wrapper around the TypeScript compiler `tsc` that adds a transform for processing Angular code.
## observable
-A producer of multiple values, which it pushes to [subscribers](#subscriber). Used for asynchronous event handling throughout Angular. You execute an observable by subscribing to it with its `subscribe()` method, passing callbacks for notifications of new values, errors, or completion.
+A producer of multiple values, which it pushes to [subscribers][AioGuideGlossarySubscriber].
+Used for asynchronous event handling throughout Angular.
+You execute an observable by subscribing to it with its `subscribe()` method, passing callbacks for notifications of new values, errors, or completion.
-Observables can deliver single or multiple values of any type to subscribers, either synchronously (as a function delivers a value to its caller) or on a schedule. A subscriber receives notification of new values as they are produced and notification of either normal completion or error completion.
+Observables can deliver in one the following ways a single value or multiple values of any type to subscribers.
-Angular uses a third-party library called [Reactive Extensions (RxJS)](https://rxjs.dev/).
+* Synchronously as a function delivers a value to the requester
+* Scheduled
-To learn more, see [Observables](guide/observables).
+A subscriber receives notification of new values as they are produced and notification of either normal completion or error completion.
-
-{@a observer}
+Angular uses a third-party library named [Reactive Extensions (RxJS)][RxjsMain].
+To learn more, see [Observables][AioGuideObservables].
## observer
-An object passed to the `subscribe()` method for an [observable](#observable). The object defines the callbacks for the [subscriber](#subscriber).
-
-{@a output}
+An object passed to the `subscribe()` method for an [observable][AioGuideGlossaryObservable].
+The object defines the callbacks for the [subscriber][AioGuideGlossarySubscriber].
## output
-When defining a [directive](#directive), the `@Output{}` decorator on a directive property
-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/inputs-outputs).
+When defining a [directive][AioGuideGlossaryDirective], the `@Output{}` decorator on a directive property makes that property available as a *target* of [event binding][AioGuideEventBinding].
+Events stream *out* of this property to the receiver identified in the [template expression][AioGuideGlossaryTemplateExpression] to the right of the equal sign.
-
-{@a P}
-
-{@a pipe}
+To learn more, see [`@Input()` and `@Output()` decorator functions][AioGuideInputsOutputs].
## pipe
-A class which is preceded by the `@Pipe{}` decorator and which defines a function that transforms input values to output values for display in a [view](#view). Angular defines various pipes, and you can define new pipes.
-
-To learn more, see [Pipes](guide/pipes).
+A class which is preceded by the `@Pipe{}` decorator and which defines a function that transforms input values to output values for display in a [view][AioGuideGlossaryView].
+Angular defines various pipes, and you can define new pipes.
-{@a platform}
+To learn more, see [Pipes][AioGuidePipes].
## platform
In Angular terminology, a platform is the context in which an Angular application runs.
The most common platform for Angular applications is a web browser, but it can also be an operating system for a mobile device, or a web server.
-Support for the various Angular run-time platforms is provided by the `@angular/platform-*` packages. These packages allow applications that make use of `@angular/core` and `@angular/common` to execute in different environments by providing implementation for gathering user input and rendering UIs for the given platform. Isolating platform-specific functionality allows the developer to make platform-independent use of the rest of the framework.
+Support for the various Angular run-time platforms is provided by the `@angular/platform-*` packages.
+These packages allow applications that make use of `@angular/core` and `@angular/common` to execute in different environments by providing implementation for gathering user input and rendering UIs for the given platform.
+Isolating platform-specific functionality allows the developer to make platform-independent use of the rest of the framework.
-* When running in a web browser, [`BrowserModule`](api/platform-browser/BrowserModule) is imported from the `platform-browser` package, and supports services that simplify security and event processing, and allows applications to access browser-specific features, such as interpreting keyboard input and controlling the title of the document being displayed. All applications running in the browser use the same platform service.
+* When running in a web browser, [`BrowserModule`][AioApiPlatformBrowserBrowsermodule] is imported from the `platform-browser` package, and supports services that simplify security and event processing, and allows applications to access browser-specific features, such as interpreting keyboard input and controlling the title of the document being displayed.
+ All applications running in the browser use the same platform service.
-* When [server-side rendering](#server-side-rendering) (SSR) is used, the [`platform-server`](api/platform-server) package provides web server implementations of the `DOM`, `XMLHttpRequest`, and other low-level features that don't rely on a browser.
-
-{@a polyfill}
+* When [server-side rendering (SSR)][AioGuideGlossaryServerSideRendering] is used, the [`platform-server`][AioApiPlatformServer] package provides web server implementations of the `DOM`, `XMLHttpRequest`, and other low-level features that do not rely on a browser.
## polyfill
-An [npm package](guide/npm-packages) that plugs gaps in a browser's JavaScript implementation.
-See [Browser Support](guide/browser-support) for polyfills that support particular functionality for particular platforms.
-
-{@a project}
+An [npm package][AioGuideNpmPackages] that plugs gaps in the JavaScript implementation of a browser.
+See [Browser Support][AioGuideBrowserSupport] for polyfills that support particular functionality for particular platforms.
## project
-In the Angular CLI, a standalone application or [library](#library) that can be created or modified by a CLI command.
-
-A project, as generated by the [`ng new`](cli/new), contains the set of source files, resources, and configuration files that you need to develop and test the application using the CLI. Projects can also be created with the `ng generate application` and `ng generate library` commands.
+In the Angular CLI, a standalone application or [library][AioGuideGlossaryLibrary] that can be created or modified by a Angular CLI command.
-For more information, see [Project File Structure](guide/file-structure).
+A project, as generated by the [`ng new`][AioCliNew], contains the set of source files, resources, and configuration files that you need to develop and test the application using the Angular CLI.
+Projects can also be created with the `ng generate application` and `ng generate library` commands.
-The [`angular.json`](guide/workspace-config) file configures all projects in a [workspace](#workspace).
+To learn more, see [Project File Structure][AioGuideFileStructure].
-{@a provider}
+The [`angular.json`][AioGuideWorkspaceConfig] file configures all projects in a [workspace][AioGuideGlossaryWorkspace].
## provider
-An object that implements one of the [`Provider`](api/core/Provider) interfaces. A provider object defines how to obtain an injectable dependency associated with a [DI token](#token).
-An [injector](#injector) uses the provider to create a new instance of a dependency
-for a class that requires it.
+An object that implements one of the [`Provider`][AioApiCoreProvider] interfaces.
+A provider object defines how to obtain an injectable dependency associated with a [DI token][AioGuideGlossaryDiToken].
+An [injector][AioGuideGlossaryInjector] uses the provider to create a new instance of a dependency for a class that requires it.
Angular registers its own providers with every injector, for services that Angular defines.
You can register your own providers for services that your application needs.
-See also [service](#service), [dependency injection](#di).
+See also [service][AioGuideGlossaryService].
+See also [dependency injection][AioGuideGlossaryDependencyInjectionDi].
-Learn more in [Dependency Injection](guide/dependency-injection).
-
-
-{@a Q}
-
-{@a R}
-
-{@a reactive-forms}
+Learn more in [Dependency Injection][AioGuideDependencyInjection].
## reactive forms
A framework for building Angular forms through code in a component.
-The alternative is a [template-driven form](#template-driven-forms).
+The alternative is a [template-driven form][AioGuideGlossaryTemplateDrivenForms].
When using reactive forms:
-* The "source of truth", the form model, is defined in the component class.
-* Validation is set up through validation functions rather than validation directives.
-* Each control is explicitly created in the component class by creating a `FormControl` instance manually or with `FormBuilder`.
-* The template input elements do *not* use `ngModel`.
-* The associated Angular directives are prefixed with `form`, such as `formControl`, `formGroup`, and `formControlName`.
-
-The alternative is a template-driven form. For an introduction and comparison of both forms approaches, see [Introduction to Angular Forms](guide/forms-overview).
+* The "source of truth", the form model, is defined in the component class.
+* Validation is set up through validation functions rather than validation directives.
+* Each control is explicitly created in the component class by creating a `FormControl` instance manually or with `FormBuilder`.
+* The template input elements do *not* use `ngModel`.
+* The associated Angular directives are prefixed with `form`, such as `formControl`, `formGroup`, and `formControlName`.
-{@a resolver}
+The alternative is a template-driven form.
+For an introduction and comparison of both forms approaches, see [Introduction to Angular Forms][AioGuideFormsOverview].
## resolver
-A class that implements the [Resolve](api/router/Resolve "API reference") interface (or a function with the same signature as the [resolve() method](api/router/Resolve#resolve "API reference")) that you use to produce or retrieve data that is needed before navigation to a requested route can be completed.
-
-Resolvers run after all [route guards](#route-guard "Definition") for a route tree have been executed and have succeeded.
+A class that implements the [Resolve][AioApiRouterResolve] interface that you use to produce or retrieve data that is needed before navigation to a requested route can be completed.
+You may use a function with the same signature as the [resolve()][AioApiRouterResolve] method in place of the [Resolve][AioApiRouterResolve] interface.
+Resolvers run after all [route guards][AioGuideGlossaryRouteGuard] for a route tree have been executed and have succeeded.
-See an example of using a [resolve guard](guide/router-tutorial-toh#resolve-guard "Routing techniques tutorial") to retrieve dynamic data.
-
-{@a route-guard}
+See an example of using a [resolve guard][AioGuideRouterTutorialTohResolvePreFetchingComponentData] to retrieve dynamic data.
## route guard
A method that controls navigation to a requested route in a routing application.
Guards determine whether a route can be activated or deactivated, and whether a lazy-loaded module can be loaded.
-Learn more in the [Routing and Navigation](guide/router#preventing-unauthorized-access "Examples") guide.
-
-
-{@a router}
-{@a router-module}
+Learn more in the [Routing and Navigation][AioGuideRouterPreventingUnauthorizedAccess] guide.
## router
-A tool that configures and implements navigation among states and [views](#view) within an Angular application.
+A tool that configures and implements navigation among states and [views][AioGuideGlossaryView] within an Angular application.
-The `Router` module is an [NgModule](#ngmodule) that provides the necessary service providers and directives for navigating through application views. A [routing component](#routing-component) is one that imports the `Router` module and whose template contains a `RouterOutlet` element where it can display views produced by the router.
+The `Router` module is an [NgModule][AioGuideGlossaryNgmodule] that provides the necessary service providers and directives for navigating through application views.
+A [routing component][AioGuideGlossaryRoutingComponent] is one that imports the `Router` module and whose template contains a `RouterOutlet` element where it can display views produced by the router.
-The router defines navigation among views on a single page, as opposed to navigation among pages. It interprets URL-like links to determine which views to create or destroy, and which components to load or unload. It allows you to take advantage of [lazy loading](#lazy-load) in your Angular applications.
+The router defines navigation among views on a single page, as opposed to navigation among pages.
+It interprets URL-like links to determine which views to create or destroy, and which components to load or unload.
+It allows you to take advantage of [lazy loading][AioGuideGlossaryLazyLoading] in your Angular applications.
-To learn more, see [Routing and Navigation](guide/router).
-
-{@a router-outlet}
+To learn more, see [Routing and Navigation][AioGuideRouter].
## router outlet
-A [directive](#directive) that acts as a placeholder in a routing component's template. Angular dynamically renders the template based on the current router state.
-
-{@a router-component}
+A [directive][AioGuideGlossaryDirective] that acts as a placeholder in the template of a routing component.
+Angular dynamically renders the template based on the current router state.
## routing component
-An Angular [component](#component) with a `RouterOutlet` directive in its template that displays views based on router navigations.
+An Angular [component][AioGuideGlossaryComponent] with a `RouterOutlet` directive in its template that displays views based on router navigations.
-For more information, see [Routing and Navigation](guide/router).
-
-{@a rule}
+To learn more, see [Routing and Navigation][AioGuideRouter].
## rule
-In [schematics](#schematic), a function that operates on a [file tree](#file-tree) to create, delete, or modify files in a specific manner.
-
-{@a S}
-
-{@a schematic}
+In [schematics][AioGuideGlossarySchematic], a function that operates on a [file tree][AioGuideGlossaryTree] to create, delete, or modify files in a specific manner.
## schematic
A scaffolding library that defines how to generate or transform a programming project by creating, modifying, refactoring, or moving files and code.
-A schematic defines [rules](#rule) that operate on a virtual file system called a [tree](#file-tree).
+A schematic defines [rules][AioGuideGlossaryRule] that operate on a virtual file system referenced as a [tree][AioGuideGlossaryTree].
-The [Angular CLI](#cli) uses schematics to generate and modify [Angular projects](#project) and parts of projects.
+The [Angular CLI][AioGuideGlossaryCommandLineInterfaceCli] uses schematics to generate and modify [Angular projects][AioGuideGlossaryProject] and parts of projects.
-* Angular provides a set of schematics for use with the CLI. See the [Angular CLI command reference](cli). The [`ng add`](cli/add) command runs schematics as part of adding a library to your project. The [`ng generate`](cli/generate) command runs schematics to create applications, libraries, and Angular code constructs.
+* Angular provides a set of schematics for use with the Angular CLI.
+ See the [Angular CLI command reference][AioCliMain].
+ The [`ng add`][AioCliAdd] Angular [CLI][AioGuideGlossaryCommandLineInterfaceCli] command runs schematics as part of adding a library to your project.
+ The [`ng generate`][AioCliGenerate] Angular [CLI][AioGuideGlossaryCommandLineInterfaceCli] command runs schematics to create applications, libraries, and Angular code constructs.
-* [Library](#library) developers can create schematics that enable the Angular CLI to add and update their published libraries, and to generate artifacts the library defines.
-Add these schematics to the npm package that you use to publish and share your library.
+* [Library][AioGuideGlossaryLibrary] developers can create schematics that enable the Angular CLI to add and update their published libraries, and to generate artifacts the library defines.
+ Add these schematics to the npm package that you use to publish and share your library.
-For more information, see [Schematics](guide/schematics) and [Integrating Libraries with the CLI](guide/creating-libraries#integrating-with-the-cli).
-
-{@a schematics-cli}
+To learn more, see [Schematics][AioGuideSchematics].
+To learn more, see also [Integrating Libraries with the CLI][AioGuideCreatingLibrariesIntegratingWithTheCliUsingCodeGenerationSchematics].
## Schematics CLI
Schematics come with their own command-line tool.
-Using Node 6.9 or above, install the Schematics CLI globally:
+Use Node 6.9 or above to install the Schematics CLI globally.
+
+
-
npm install -g @angular-devkit/schematics-cli
-
-This installs the `schematics` executable, which you can use to create a new schematics [collection](#collection) with an initial named schematic. The collection folder is a workspace for schematics. You can also use the `schematics` command to add a new schematic to an existing collection, or extend an existing schematic.
+
-{@a scoped-package}
+This installs the `schematics` executable, which you can use to create a new schematics [collection][AioGuideGlossaryCollection] with an initial named schematic.
+The collection directory is a workspace for schematics.
+You can also use the `schematics` command to add a new schematic to an existing collection, or extend an existing schematic.
## scoped package
-A way to group related [npm packages](guide/npm-packages).
-NgModules are delivered within scoped packages whose names begin with the Angular *scope name* `@angular`. For example, `@angular/core`, `@angular/common`, `@angular/forms`, and `@angular/router`.
+A way to group related [npm packages][AioGuideNpmPackages].
+NgModules are delivered within scoped packages whose names begin with the Angular *scope name* `@angular`.
+For example, `@angular/core`, `@angular/common`, `@angular/forms`, and `@angular/router`.
Import a scoped package in the same way that you import a normal package.
-
-
-
-
-{@a server-side-rendering}
+
## server-side rendering
@@ -856,281 +720,477 @@ It can also pre-generate pages as HTML files that you serve later.
This technique can improve performance on mobile and low-powered devices and improve the user experience by showing a static first page quickly while the client-side application is loading.
The static version can also make your application more visible to web crawlers.
-You can easily prepare an application for server-side rendering by using the [CLI](#cli) to run the [Angular Universal](#universal) tool, using the `@nguniversal/express-engine` [schematic](#schematic).
-
-
-{@a service}
+You can easily prepare an application for server-side rendering by using the [Angular CLI][AioGuideGlossaryCommandLineInterfaceCli] to run the [Angular Universal][AioGuideGlossaryUniversal] tool, using the `@nguniversal/express-engine` [schematic][AioGuideGlossarySchematic].
## service
-In Angular, a class with the [@Injectable()](#injectable) decorator that encapsulates non-UI logic and code that can be reused across an application.
+In Angular, a class with the [@Injectable()][AioGuideGlossaryInjectable] decorator that encapsulates non-UI logic and code that can be reused across an application.
Angular distinguishes components from services to increase modularity and reusability.
-The `@Injectable()` metadata allows the service class to be used with the [dependency injection](#di) mechanism.
-The injectable class is instantiated by a [provider](#provider).
-[Injectors](#injector) maintain lists of providers and use them to provide service instances when they are required by components or other services.
+The `@Injectable()` metadata allows the service class to be used with the [dependency injection][AioGuideGlossaryDependencyInjectionDi] mechanism.
+The injectable class is instantiated by a [provider][AioGuideGlossaryProvider].
+[Injectors][AioGuideGlossaryInjector] maintain lists of providers and use them to provide service instances when they are required by components or other services.
-To learn more, see [Introduction to Services and Dependency Injection](guide/architecture-services).
+For To learn more, see [Introduction to Services and Dependency Injection][AioGuideArchitectureServices].
-{@a structural-directive}
-{@a structural-directives}
+## structural directive
-## structural directives
+A category of [directive][AioGuideGlossaryDirective] that is responsible for shaping HTML layout by modifying the DOM.
+Modification of the DOM includes, adding, removing, or manipulating elements and the associated children.
-A category of [directive](#directive) that is responsible for shaping HTML layout by modifying the DOM—that is, adding, removing, or manipulating elements and their children.
-
-To learn more, see [Structural Directives](guide/structural-directives).
-
-{@a subscriber}
+To learn more, see [Structural Directives][AioGuideStructuralDirectives].
## subscriber
-A function that defines how to obtain or generate values or messages to be published. This function is executed when a consumer calls the `subscribe()` method of an [observable](#observable).
+A function that defines how to obtain or generate values or messages to be published.
+This function is executed when a consumer runs the `subscribe()` method of an [observable][AioGuideGlossaryObservable].
The act of subscribing to an observable triggers its execution, associates callbacks with it, and creates a `Subscription` object that lets you unsubscribe.
-The `subscribe()` method takes a JavaScript object (called an [observer](#observer)) with up to three callbacks, one for each type of notification that an observable can deliver:
-
-* The `next` notification sends a value such as a number, a string, or an object.
-* The `error` notification sends a JavaScript Error or exception.
-* The `complete` notification doesn't send a value, but the handler is called when the call completes. Scheduled values can continue to be returned after the call completes.
+The `subscribe()` method takes an [observer][AioGuideGlossaryObserver] JavaScript object with up to three callbacks, one for each type of notification that an observable can deliver.
-{@a T}
-
-{@a target}
+* The `next` notification sends a value such as a number, a string, or an object.
+* The `error` notification sends a JavaScript Error or exception.
+* The `complete` notification does not send a value, but the handler is run when the method completes.
+ Scheduled values can continue to be returned after the method completes.
## target
-A buildable or runnable subset of a [project](#project), configured as an object in the [workspace configuration file](guide/workspace-config#project-tool-configuration-options), and executed by an [Architect](#architect) [builder](#builder).
-
-In the `angular.json` file, each project has an "architect" section that contains targets which configure builders. Some of these targets correspond to [CLI commands](#cli), such as `build`, `serve`, `test`, and `lint`.
+A buildable or runnable subset of a [project][AioGuideGlossaryProject], configured as an object in the [workspace configuration file][AioGuideWorkspaceConfigProjectToolConfigurationOptions], and executed by an [Architect][AioGuideGlossaryArchitect] [builder][AioGuideGlossaryBuilder].
-For example, the Architect builder invoked by the `ng build` command to compile a project uses a particular build tool, and has a default configuration with values that you can override on the command line. The `build` target also defines an alternate configuration for a "development" build, which you can invoke with the `--configuration development` flag on the `build` command.
+In the `angular.json` file, each project has an "architect" section that contains targets which configure builders.
+Some of these targets correspond to Angular [CLI][AioGuideGlossaryCommandLineInterfaceCli] command, such as `build`, `serve`, `test`, and `lint`.
-The Architect tool provides a set of builders. The [`ng new` command](cli/new) provides a set of targets for the initial application project. The [`ng generate application`](cli/generate#application) and [`ng generate library`](cli/generate#library) commands provide a set of targets for each new [project](#project). These targets, their options and configurations, can be customized to meet the needs of your project. For example, you may want to add a "staging" or "testing" configuration to a project's "build" target.
+For example, the Architect builder invoked by the `ng build` command to compile a project uses a particular build tool, and has a default configuration with values that you can override on the command line.
+The `build` target also defines an alternate configuration for a "development" build, which you can invoke with the `--configuration development` flag on the `build` command.
-You can also define a custom builder, and add a target to the project configuration that uses your custom builder. You can then run the target using the [`ng run`](cli/run) CLI command.
+The Architect tool provides a set of builders.
+The [`ng new`][AioCliNew] Angular [CLI][AioGuideGlossaryCommandLineInterfaceCli] command provides a set of targets for the initial application project.
+The [`ng generate application`][AioCliGenerateApplication] and [`ng generate library`][AioCliGenerateLibrary] Angular [CLI][AioGuideGlossaryCommandLineInterfaceCli] commands provide a set of targets for each new [project][AioGuideGlossaryProject].
+These targets, their options and configurations, can be customized to meet the needs of your project.
+For example, you may want to add a "staging" or "testing" configuration to the "build" target of a project.
-{@a template}
+You can also define a custom builder, and add a target to the project configuration that uses your custom builder.
+You can then run the target using the [`ng run`][AioCliRun] Angular [CLI][AioGuideGlossaryCommandLineInterfaceCli] command.
## template
-Code that defines how to render a component's [view](#view).
+Code that defines how to render the [view][AioGuideGlossaryView] of a component.
-A template combines straight HTML with Angular [data-binding](#data-binding) syntax, [directives](#directive),
-and [template expressions](#template-expression) (logical constructs).
-The Angular elements insert or calculate values that modify the HTML elements before the page is displayed. Learn more about Angular template language in the [Template Syntax](guide/template-syntax) guide.
+A template combines straight HTML with Angular [data-binding][AioGuideGlossaryDataBinding] syntax, [directives][AioGuideGlossaryDirective], and [template expressions][AioGuideGlossaryTemplateExpression] \(logical constructs\).
+The Angular elements insert or calculate values that modify the HTML elements before the page is displayed.
+Learn more about Angular template language in the [Template Syntax][AioGuideTemplateSyntax] guide.
-A template is associated with a [component class](#component) through the `@Component()` [decorator](#decorator). The template code can be provided inline, as the value of the `template` property, or in a separate HTML file linked through the `templateUrl` property.
+A template is associated with a [component class][AioGuideGlossaryComponent] through the `@Component()` [decorator][AioGuideGlossaryDecoratorDecoration].
+The template code can be provided inline, as the value of the `template` property, or in a separate HTML file linked through the `templateUrl` property.
Additional templates, represented by `TemplateRef` objects, can define alternative or *embedded* views, which can be referenced from multiple components.
-{@a template-driven-forms}
-
## template-driven forms
A format for building Angular forms using HTML forms and input elements in the view.
-The alternative format uses the [reactive forms](#reactive-forms) framework.
+The alternative format uses the [reactive forms][AioGuideGlossaryReactiveForms] framework.
When using template-driven forms:
-* The "source of truth" is the template. The validation is defined using attributes on the individual input elements.
-* [Two-way binding](#data-binding) with `ngModel` keeps the component model synchronized with the user's entry into the input elements.
-* Behind the scenes, Angular creates a new control for each input element, provided you have set up a `name` attribute and two-way binding for each input.
-* The associated Angular directives are prefixed with `ng` such as `ngForm`, `ngModel`, and `ngModelGroup`.
+* The "source of truth" is the template.
+ The validation is defined using attributes on the individual input elements.
-The alternative is a reactive form. For an introduction and comparison of both forms approaches, see [Introduction to Angular Forms](guide/forms-overview).
+* [Two-way binding][AioGuideGlossaryDataBinding] with `ngModel` keeps the component model synchronized with the user's entry into the input elements.
+* Behind the scenes, Angular creates a new control for each input element, provided you have set up a `name` attribute and two-way binding for each input.
+* The associated Angular directives are prefixed with `ng` such as `ngForm`, `ngModel`, and `ngModelGroup`.
-{@a template-expression}
+The alternative is a reactive form.
+For an introduction and comparison of both forms approaches, see [Introduction to Angular Forms][AioGuideFormsOverview].
## template expression
-A TypeScript-like syntax that Angular evaluates within a [data binding](#data-binding).
+A TypeScript-like syntax that Angular evaluates within a [data binding][AioGuideGlossaryDataBinding].
-Read about how to write template expressions in the [template expressions](guide/interpolation#template-expressions) section of the [Interpolation](guide/interpolation) guide.
-
-{@a template-reference-variable}
+Read about how to write template expressions in the [template expressions][AioGuideInterpolationTemplateExpressions] section of the [Interpolation][AioGuideInterpolation] guide.
## template reference variable
A variable defined in a template that references an instance associated with an element, such as a directive instance, component instance, template as in `TemplateRef`, or DOM element.
-After declaring a template reference variable on an element in a template,
-you can access values from that variable elsewhere within the same template.
+After declaring a template reference variable on an element in a template, you can access values from that variable elsewhere within the same template.
The following example defines a template reference variable named `#phone`.
-For more information, see the [Template reference variable](guide/template-reference-variables) guide.
-
-
-{@a template-input-variable}
+To learn more, see [Template reference variable][AioGuideTemplateReferenceVariables].
## template input variable
-A template input variable is a variable you can reference within a single instance of the template. You declare a template input variable using the `let` keyword as in `let customer`.
+A template input variable is a variable you can reference within a single instance of the template.
+You declare a template input variable using the `let` keyword as in `let customer`.
-```
-
- {{customer.customerNo}}
- {{customer.name}}
- {{customer.address}}
- {{customer.city}}
- {{customer.state}}
- Select
-
-```
+
-Read and learn more about [template input variables](guide/template-reference-variables#template-input-variable).
+<tr *ngFor="let customer of customers;">
+ <td>{{customer.customerNo}}</td>
+ <td>{{customer.name}}</td>
+ <td>{{customer.address}}</td>
+ <td>{{customer.city}}</td>
+ <td>{{customer.state}}</td>
+ <button (click)="selectedCustomer=customer">Select</button>
+</tr>
+
-{@a token}
+Read and learn more about [template input variables][AioGuideTemplateReferenceVariablesTemplateInputVariable].
## token
-An opaque identifier used for efficient table lookup. In Angular, a [DI token](#di-token) is used to find [providers](#provider) of dependencies in the [dependency injection](#di) system.
-
-{@a transpile}
+An opaque identifier used for efficient table lookup.
+In Angular, a [DI token][AioGuideGlossaryDiToken] is used to find [providers][AioGuideGlossaryProvider] of dependencies in the [dependency injection][AioGuideGlossaryDependencyInjectionDi] system.
## transpile
The translation process that transforms one version of JavaScript to another version; for example, down-leveling ES2015 to the older ES5 version.
-{@a file-tree}
-
## tree
-In [schematics](#schematic), a virtual file system represented by the `Tree` class.
-Schematic [rules](#rule) take a tree object as input, operate on them, and return a new tree object.
-
-{@a typescript}
+In [schematics][AioGuideGlossarySchematic], a virtual file system represented by the `Tree` class.
+Schematic [rules][AioGuideGlossaryRule] take a tree object as input, operate on them, and return a new tree object.
## TypeScript
A programming language based on JavaScript that is notable for its optional typing system.
-TypeScript provides compile-time type checking and strong tooling support (such as
-code completion, refactoring, inline documentation, and intelligent search).
+TypeScript provides compile-time type checking and strong tooling support
+The type checking and toooling support include code completion, refactoring, inline documentation, and intelligent search.
Many code editors and IDEs support TypeScript either natively or with plug-ins.
TypeScript is the preferred language for Angular development.
-Read more about TypeScript at [typescriptlang.org](https://www.typescriptlang.org/).
+To learn more about TypeScript, see [typescriptlang.org][TypescriptlangMain].
## TypeScript configuration file
-A file specifies the root files and the compiler options required to compile a TypeScript project. For more information, see [TypeScript configuration](/guide/typescript-configuration).
-
-
-{@a U}
-
-{@a unidirectional-data-flow}
+A file specifies the root files and the compiler options required to compile a TypeScript project.
+To learn more, see [TypeScript configuration][AioGuideTypescriptConfiguration].
## unidirectional data flow
-A data flow model where the component tree is always checked for changes in one direction (parent to child), which prevents cycles in the change detection graph.
+A data flow model where the component tree is always checked for changes in one direction from parent to child, which prevents cycles in the change detection graph.
In practice, this means that data in Angular flows downward during change detection.
A parent component can easily change values in its child components because the parent is checked first.
-A failure could occur, however, if a child component tries to change a value in its parent during change detection (inverting the expected data flow), because the parent component has already been rendered.
+A failure could occur, however, if a child component tries to change a value in its parent during change detection \(inverting the expected data flow\), because the parent component has already been rendered.
In development mode, Angular throws the `ExpressionChangedAfterItHasBeenCheckedError` error if your application attempts to do this, rather than silently failing to render the new value.
-To avoid this error, a [lifecycle hook](guide/lifecycle-hooks) method that seeks to make such a change should trigger a new change detection run. The new run follows the same direction as before, but succeeds in picking up the new value.
-
-{@a universal}
+To avoid this error, a [lifecycle hook][AioGuideLifecycleHooks] method that seeks to make such a change should trigger a new change detection run.
+The new run follows the same direction as before, but succeeds in picking up the new value.
## Universal
-A tool for implementing [server-side rendering](#server-side-rendering) of an Angular application.
+A tool for implementing [server-side rendering][AioGuideGlossaryServerSideRendering] of an Angular application.
When integrated with an app, Universal generates and serves static pages on the server in response to requests from browsers.
The initial static page serves as a fast-loading placeholder while the full application is being prepared for normal execution in the browser.
-
-To learn more, see [Angular Universal: server-side rendering](guide/universal).
-
-{@a V}
-
-{@a view}
+To learn more, see [Angular Universal: server-side rendering][AioGuideUniversal].
## view
The smallest grouping of display elements that can be created and destroyed together.
-Angular renders a view under the control of one or more [directives](#directive).
+Angular renders a view under the control of one or more [directives][AioGuideGlossaryDirective].
-A [component](#component) class and its associated [template](#template) define a view.
+A [component][AioGuideGlossaryComponent] class and its associated [template][AioGuideGlossaryTemplate] define a view.
A view is specifically represented by a `ViewRef` instance associated with a component.
-A view that belongs immediately to a component is called a *host view*.
-Views are typically collected into [view hierarchies](#view-tree).
+A view that belongs immediately to a component is referenced as a *host view*.
+Views are typically collected into [view hierarchies][AioGuideGlossaryViewHierarchy].
-Properties of elements in a view can change dynamically, in response to user actions;
-the structure (number and order) of elements in a view can't.
+Properties of elements in a view can change dynamically, in response to user actions; the structure \(number and order\) of elements in a view cannot.
You can change the structure of elements by inserting, moving, or removing nested views within their view containers.
-View hierarchies can be loaded and unloaded dynamically as the user navigates through the application, typically under the control of a [router](#router).
+View hierarchies can be loaded and unloaded dynamically as the user navigates through the application, typically under the control of a [router][AioGuideGlossaryRouter].
-{@a ve}
+
## View Engine
-A previous compilation and rendering pipeline used by Angular. It has since been replaced by
-[Ivy](#ivy) and is no longer in use. View Engine was deprecated in version 9 and removed in version
-13.
+A previous compilation and rendering pipeline used by Angular.
+It has since been replaced by [Ivy][AioGuideGlossaryIvy] and is no longer in use.
+View Engine was deprecated in version 9 and removed in version 13.
-
-{@a view-tree}
+
## view hierarchy
-A tree of related views that can be acted on as a unit. The root view is a component's *host view*. A host view can be the root of a tree of *embedded views*, collected in a *view container* (`ViewContainerRef`) attached to an anchor element in the hosting component. The view hierarchy is a key part of Angular [change detection](#change-detection).
-
-The view hierarchy doesn't imply a component hierarchy. Views that are embedded in the context of a particular hierarchy can be host views of other components. Those components can be in the same NgModule as the hosting component, or belong to other NgModules.
+A tree of related views that can be acted on as a unit.
+The root view referenced as the *host view* of a component.
+A host view is the root of a tree of *embedded views*, collected in a `ViewContainerRef` view container attached to an anchor element in the hosting component.
+The view hierarchy is a key part of Angular [change detection][AioGuideGlossaryChangeDetection].
-{@a W}
-{@a web-component}
+The view hierarchy does not imply a component hierarchy.
+Views that are embedded in the context of a particular hierarchy can be host views of other components.
+Those components can be in the same NgModule as the hosting component, or belong to other NgModules.
## web component
-See [custom element](#custom-element).
-
-{@a workspace}
+See [custom element][AioGuideGlossaryCustomElement].
## workspace
-A collection of Angular [projects](#project) (that is, applications and libraries) powered by the [Angular CLI](#cli) that are typically co-located in a single source-control repository (such as [git](https://git-scm.com/)).
+A collection of Angular [projects][AioGuideGlossaryProject] \(that is, applications and libraries\) powered by the Angular [CLI][AioGuideGlossaryCommandLineInterfaceCli] that are typically co-located in a single source-control repository \(such as [git][GitScmMain]\).
-The [CLI](#cli) [`ng new` command](cli/new) creates a file system directory (the "workspace root").
-In the workspace root, it also creates the workspace [configuration file](#configuration) (`angular.json`) and, by default, an initial application project with the same name.
+The [`ng new`][AioCliNew] Angular [CLI][AioGuideGlossaryCommandLineInterfaceCli] command creates a file system directory \(the "workspace root"\).
+In the workspace root, it also creates the workspace [configuration file][AioGuideGlossaryConfiguration] \(`angular.json`\) and, by default, an initial application project with the same name.
-Commands that create or operate on applications and libraries (such as `add` and `generate`) must be executed from within a workspace folder.
+Commands that create or operate on applications and libraries \(such as `add` and `generate`\) must be executed from within a workspace directory.
+To learn more, see [Workspace Configuration][AioGuideWorkspaceConfig].
-For more information, see [Workspace Configuration](guide/workspace-config).
+## workspace configuration
-{@a cli-config}
+A file named `angular.json` at the root level of an Angular [workspace][AioGuideGlossaryWorkspace] provides workspace-wide and project-specific configuration defaults for build and development tools that are provided by or integrated with the [Angular CLI][AioGuideGlossaryCommandLineInterfaceCli].
+To learn more, see [Workspace Configuration][AioGuideWorkspaceConfig].
-{@a config}
+Additional project-specific configuration files are used by tools, such as `package.json` for the [npm package manager][AioGuideGlossaryNpmPackage], `tsconfig.json` for [TypeScript transpilation][AioGuideGlossaryTranspile], and `tslint.json` for [TSLint][GithubPalantirTslint].
+To learn more, see [Workspace and Project File Structure][AioGuideFileStructure].
-## workspace configuration
+## zone
-A file named `angular.json` at the root level of an Angular [workspace](#workspace) provides workspace-wide and project-specific configuration defaults for build and development tools that are provided by or integrated with the [Angular CLI](#cli).
+An execution context for a set of asynchronous tasks.
+Useful for debugging, profiling, and testing applications that include asynchronous operations such as event processing, promises, and runs to remote servers.
-For more information, see [Workspace Configuration](guide/workspace-config).
+An Angular application runs in a zone where it can respond to asynchronous events by checking for data changes and updating the information it displays by resolving [data bindings][AioGuideGlossaryDataBinding].
-Additional project-specific configuration files are used by tools, such as `package.json` for the [npm package manager](#npm-package), `tsconfig.json` for [TypeScript transpilation](#transpile), and `tslint.json` for [TSLint](https://palantir.github.io/tslint/).
+A zone client can take action before and after an async operation completes.
-For more information, see [Workspace and Project File Structure](guide/file-structure).
+Learn more about zones in this [Brian Ford video][YoutubeWatchV3iqtmusceU].
-{@a X}
+
+[AioApiCommonDatepipe]: api/common/DatePipe "DatePipe | @angular/common - API | Angular"
-{@a Y}
+[AioApiCoreChangedetectorref]: api/core/ChangeDetectorRef "ChangeDetectorRef | @angular/core - API | Angular"
+[AioApiCoreProvider]: api/core/Provider "Provider | @angular/core - API | Angular"
-{@a Z}
-{@a zone}
+[AioApiPlatformBrowserBrowsermodule]: api/platform-browser/BrowserModule "BrowserModule | @angular/platform-browser - API | Angular"
-## zone
+[AioApiPlatformServer]: api/platform-server "@angular/platform-server | API | Angular"
-An execution context for a set of asynchronous tasks. Useful for debugging, profiling, and testing applications that include asynchronous operations such as event processing, promises, and calls to remote servers.
+[AioApiRouterResolve]: api/router/Resolve "Resolve | @angular/router - API | Angular"
-An Angular application runs in a zone where it can respond to asynchronous events by checking for data changes and updating the information it displays by resolving [data bindings](#data-binding).
+[AioCliAdd]: cli/add "ng add | CLI | Angular"
-A zone client can take action before and after an async operation completes.
+[AioCliGenerate]: cli/generate "ng generate | CLI | Angular"
+[AioCliGenerateApplication]: cli/generate#application "application - ng generate | CLI | Angular"
+[AioCliGenerateAppShell]: cli/generate#app-shell "app-shell - ng generate | CLI | Angular"
+[AioCliGenerateLibrary]: cli/generate#library "library - ng generate | CLI | Angular"
+
+[AioCliMain]: cli "CLI Overview and Command Reference | Angular"
+
+[AioCliNew]: cli/new "ng new | CLI | Angular"
+
+[AioCliRun]: cli/run "ng run | CLI | Angular"
+
+[AioGuideAngularPackageFormat]: guide/angular-package-format "Angular Package Format | Angular"
+
+[AioGuideAnimations]: guide/animations "Introduction to Angular animations | Angular"
+
+[AioGuideArchitecture]: guide/architecture "Introduction to Angular concepts | Angular"
+
+[AioGuideArchitectureServices]: guide/architecture-services "Introduction to services and dependency injection | Angular"
+
+[AioGuideAttributeBinding]: guide/attribute-binding "Attribute, class, and style bindings | Angular"
+[AioGuideAttributeBindingBindingToTheClassAttribute]: guide/attribute-binding#binding-to-the-class-attribute "Binding to the class attribute - Attribute, class, and style bindings | Angular"
+[AioGuideAttributeBindingBindingToTheStyleAttribute]: guide/attribute-binding#binding-to-the-style-attribute "Binding to the style attribute - Attribute, class, and style bindings | Angular"
+
+[AioGuideAttributeDirectives]: guide/attribute-directives "Attribute directives | Angular"
+
+[AioGuideBootstrapping]: guide/bootstrapping "Launching your app with a root module | Angular"
+
+[AioGuideBrowserSupport]: guide/browser-support "Browser support | Angular"
+
+[AioGuideBuiltInDirectivesDisplayingAndUpdatingPropertiesWithNgmodel]: guide/built-in-directives#displaying-and-updating-properties-with-ngmodel "Displaying and updating properties with ngModel - Built-in directives | Angular"
+
+[AioGuideLifecycleHooks]: guide/lifecycle-hooks "Lifecycle Hooks | Angular"
+
+[AioGuideLifecycleHooksRespondingToProjectedContentChanges]: guide/lifecycle-hooks#responding-to-projected-content-changes "Responding to projected content changes - Lifecycle Hooks | Angular"
+
+[AioGuideInputsOutputs]: guide/inputs-outputs "Sharing data between child and parent directives and components | Angular"
+
+[AioGuideCreatingLibrariesIntegratingWithTheCliUsingCodeGenerationSchematics]: guide/creating-libraries#integrating-with-the-cli-using-code-generation-schematics "Integrating with the CLI using code-generation schematics - Creating libraries | Angular"
+
+[AioGuideDependencyInjection]: guide/dependency-injection "Dependency injection in Angular | Angular"
+
+[AioGuideElements]: guide/elements "Angular elements overview | Angular"
+
+[AioGuideEventBinding]: guide/event-binding "Event binding | Angular"
+
+[AioGuideForms]: guide/forms "Building a template-driven form | Angular"
+
+[AioGuideFileStructure]: guide/file-structure "Workspace and project file structure | Angular"
+
+[AioGuideFormsOverview]: guide/forms-overview "Introduction to forms in Angular | Angular"
+
+[AioGuideFormValidation]: guide/form-validation "Validating form input | Angular"
+[AioGuideFormValidationAddingCustomValidatorsToReactiveForms]: guide/form-validation#adding-custom-validators-to-reactive-forms "Adding custom validators to reactive forms - Validating form input | Angular"
+[AioGuideFormValidationAddingCustomValidatorsToTemplateDrivenForms]: guide/form-validation#adding-custom-validators-to-template-driven-forms "Adding custom validators to template-driven forms - Validating form input | Angular"
+
+[AioGuideGlossaryA]: guide/glossary#ahead-of-time-aot-compilation "A - Glossary | Angular"
+[AioGuideGlossaryAheadOfTimeAotCompilation]: guide/glossary#ahead-of-time-aot-compilation "ahead-of-time (AOT) compilation - Glossary | Angular"
+[AioGuideGlossaryAngularElement]: guide/glossary#angular-element "Angular element - Glossary | Angular"
+[AioGuideGlossaryArchitect]: guide/glossary#architect "Architect - Glossary | Angular"
+[AioGuideGlossaryAttributeDirective]: guide/glossary#attribute-directive "attribute directive - Glossary | Angular"
+[AioGuideGlossaryB]: guide/glossary#binding "B - Glossary | Angular"
+[AioGuideGlossaryBuilder]: guide/glossary#builder "builder - Glossary | Angular"
+[AioGuideGlossaryC]: guide/glossary#case-types "C - Glossary | Angular"
+[AioGuideGlossaryChangeDetection]: guide/glossary#change-detection " change detection - Glossary | Angular"
+[AioGuideGlossaryClassDecorator]: guide/glossary#class-decorator "class decorator - Glossary | Angular"
+[AioGuideGlossaryClassFieldDecorator]: guide/glossary#class-field-decorator "class field decorator - Glossary | Angular"
+[AioGuideGlossaryCollection]: guide/glossary#collection "collection - Glossary | Angular"
+[AioGuideGlossaryCommandLineInterfaceCli]: guide/glossary#command-line-interface-cli "command-line interface (CLI) - Glossary | Angular"
+[AioGuideGlossaryComponent]: guide/glossary#component "component - Glossary | Angular"
+[AioGuideGlossaryConfiguration]: guide/glossary#configuration "configuration - Glossary | Angular"
+[AioGuideGlossaryCustomElement]: guide/glossary#custom-element "custom element - Glossary | Angular"
+[AioGuideGlossaryD]: guide/glossary#data-binding "D - Glossary | Angular"
+[AioGuideGlossaryDataBinding]: guide/glossary#data-binding "data binding - Glossary | Angular"
+[AioGuideGlossaryDeclarable]: guide/glossary#declarable "declarable - Glossary | Angular"
+[AioGuideGlossaryDecoratorDecoration]: guide/glossary#decorator--decoration "decorator | decoration - Glossary | Angular"
+[AioGuideGlossaryDependencyInjectionDi]: guide/glossary#dependency-injection-di "dependency injection (DI) - Glossary | Angular"
+[AioGuideGlossaryDirective]: guide/glossary#directive "directive - Glossary | Angular"
+[AioGuideGlossaryDiToken]: guide/glossary#di-token "DI token - Glossary | Angular"
+[AioGuideGlossaryDynamicComponentLoading]: guide/glossary#dynamic-component-loading "dynamic component loading - Glossary | Angular"
+[AioGuideGlossaryE]: guide/glossary#eager-loading "E - Glossary | Angular"
+[AioGuideGlossaryEagerLoading]: guide/glossary#eager-loading "eager loading - Glossary | Angular"
+[AioGuideGlossaryEcmascript]: guide/glossary#ecmascript "ECMAScript - Glossary | Angular"
+[AioGuideGlossaryF]: guide/glossary#form-control "F - Glossary | Angular"
+[AioGuideGlossaryG]: guide/glossary#immutability "G - Glossary | Angular"
+[AioGuideGlossaryH]: guide/glossary#immutability "H - Glossary | Angular"
+[AioGuideGlossaryI]: guide/glossary#immutability "I - Glossary | Angular"
+[AioGuideGlossaryInjectable]: guide/glossary#injectable "injectable - Glossary | Angular"
+[AioGuideGlossaryInjector]: guide/glossary#injector "injector - Glossary | Angular"
+[AioGuideGlossaryInput]: guide/glossary#input "input - Glossary | Angular"
+[AioGuideGlossaryIvy]: guide/glossary#ivy "Ivy - Glossary | Angular"
+[AioGuideGlossaryJ]: guide/glossary#javascript "J - Glossary | Angular"
+[AioGuideGlossaryJustInTimeJitCompilation]: guide/glossary#just-in-time-jit-compilation "just-in-time (JIT) compilation - Glossary | Angular"
+[AioGuideGlossaryK]: guide/glossary#lazy-loading "K - Glossary | Angular"
+[AioGuideGlossaryL]: guide/glossary#lazy-loading "L - Glossary | Angular"
+[AioGuideGlossaryLazyLoading]: guide/glossary#lazy-loading "lazy loading - Glossary | Angular"
+[AioGuideGlossaryLibrary]: guide/glossary#library "library - Glossary | Angular"
+[AioGuideGlossaryM]: guide/glossary#module "M - Glossary | Angular"
+[AioGuideGlossaryModule]: guide/glossary#module "module - Glossary | Angular"
+[AioGuideGlossaryN]: guide/glossary#ngcc "N - Glossary | Angular"
+[AioGuideGlossaryNgmodule]: guide/glossary#ngmodule "NgModule - Glossary | Angular"
+[AioGuideGlossaryNpmPackage]: guide/glossary#npm-package "npm package - Glossary | Angular"
+[AioGuideGlossaryO]: guide/glossary#observable "O - Glossary | Angular"
+[AioGuideGlossaryObservable]: guide/glossary#observable "observable - Glossary | Angular"
+[AioGuideGlossaryObserver]: guide/glossary#observer "observer - Glossary | Angular"
+[AioGuideGlossaryOutput]: guide/glossary#output "output - Glossary | Angular"
+[AioGuideGlossaryP]: guide/glossary#pipe "P - Glossary | Angular"
+[AioGuideGlossaryPipe]: guide/glossary#pipe "pipe - Glossary | Angular"
+[AioGuideGlossaryProject]: guide/glossary#project "project - Glossary | Angular"
+[AioGuideGlossaryProvider]: guide/glossary#provider "provider - Glossary | Angular"
+[AioGuideGlossaryQ]: guide/glossary#reactive-forms "Q - Glossary | Angular"
+[AioGuideGlossaryR]: guide/glossary#reactive-forms "R - Glossary | Angular"
+[AioGuideGlossaryReactiveForms]: guide/glossary#reactive-forms "reactive forms - Glossary | Angular"
+[AioGuideGlossaryRouteGuard]: guide/glossary#route-guard "route guard - Glossary | Angular"
+[AioGuideGlossaryRouter]: guide/glossary#router "router - Glossary | Angular"
+[AioGuideGlossaryRoutingComponent]: guide/glossary#routing-component "routing component - Glossary | Angular"
+[AioGuideGlossaryRule]: guide/glossary#rule "rule - Glossary | Angular"
+[AioGuideGlossaryS]: guide/glossary#schematic "S - Glossary | Angular"
+[AioGuideGlossarySchematic]: guide/glossary#schematic "schematic - Glossary | Angular"
+[AioGuideGlossarySchematicsCli]: guide/glossary#schematics-cli "Schematics CLI - Glossary | Angular"
+[AioGuideGlossaryScopedPackage]: guide/glossary#scoped-package "scoped package - Glossary | Angular"
+[AioGuideGlossaryServerSideRendering]: guide/glossary#server-side-rendering "server-side rendering - Glossary | Angular"
+[AioGuideGlossaryService]: guide/glossary#service "service - Glossary | Angular"
+[AioGuideGlossaryStructuralDirective]: guide/glossary#structural-directive "structural directive - Glossary | Angular"
+[AioGuideGlossarySubscriber]: guide/glossary#subscriber "subscriber - Glossary | Angular"
+[AioGuideGlossaryT]: guide/glossary#target "T - Glossary | Angular"
+[AioGuideGlossaryTarget]: guide/glossary#target "target - Glossary | Angular"
+[AioGuideGlossaryTemplate]: guide/glossary#template "template - Glossary | Angular"
+[AioGuideGlossaryTemplateDrivenForms]: guide/glossary#template-driven-forms "template-driven forms - Glossary | Angular"
+[AioGuideGlossaryTemplateExpression]: guide/glossary#template-expression "template expression - Glossary | Angular"
+[AioGuideGlossaryToken]: guide/glossary#token "token - Glossary | Angular"
+[AioGuideGlossaryTranspile]: guide/glossary#transpile "transpile - Glossary | Angular"
+[AioGuideGlossaryTree]: guide/glossary#tree "tree - Glossary | Angular"
+[AioGuideGlossaryTypescript]: guide/glossary#typescript "TypeScript - Glossary | Angular"
+[AioGuideGlossaryU]: guide/glossary#unidirectional-data-flow "U - Glossary | Angular"
+[AioGuideGlossaryUniversal]: guide/glossary#universal "Universal - Glossary | Angular"
+[AioGuideGlossaryV]: guide/glossary#view "V - Glossary | Angular"
+[AioGuideGlossaryView]: guide/glossary#view "view - Glossary | Angular"
+[AioGuideGlossaryViewHierarchy]: guide/glossary#view-hierarchy "view hierarchy - Glossary | Angular"
+[AioGuideGlossaryW]: guide/glossary#web-component "W - Glossary | Angular"
+[AioGuideGlossaryWorkspace]: guide/glossary#workspace "workspace - Glossary | Angular"
+[AioGuideGlossaryWorkspaceConfig]: guide/glossary#workspace-configuration "workspace configuration - Glossary | Angular"
+[AioGuideGlossaryX]: guide/glossary#zone "X - Glossary | Angular"
+[AioGuideGlossaryY]: guide/glossary#zone "Y - Glossary | Angular"
+[AioGuideGlossaryZ]: guide/glossary#zone "Z - Glossary | Angular"
+
+[AioGuideHierarchicalDependencyInjection]: guide/hierarchical-dependency-injection "Hierarchical injectors | Angular"
+
+[AioGuideInterpolation]: guide/interpolation "Text interpolation | Angular"
+[AioGuideInterpolationTemplateExpressions]: guide/interpolation#template-expressions "Template expressions - Text interpolation | Angular"
+
+[AioGuideNgmodules]: guide/ngmodules "NgModules | Angular"
+
+[AioGuideNpmPackages]: guide/npm-packages "Workspace npm dependencies | Angular"
+
+[AioGuideObservables]: guide/observables "Using observables to pass values | Angular"
+
+[AioGuidePipes]: guide/pipes "Transforming Data Using Pipes | Angular"
+
+[AioGuidePropertyBinding]: guide/property-binding "Property binding | Angular"
+
+[AioGuideRouter]: guide/router "Common Routing Tasks | Angular"
+[AioGuideRouterPreventingUnauthorizedAccess]: guide/router#preventing-unauthorized-access "Preventing unauthorized access - Common Routing Tasks | Angular"
+
+[AioGuideRouterTutorialTohResolvePreFetchingComponentData]: guide/router-tutorial-toh#resolve-pre-fetching-component-data "Resolve: pre-fetching component data - Router tutorial: tour of heroes | Angular"
+
+[AioGuideSchematics]: guide/schematics "Generating code using schematics | Angular"
+
+[AioGuideServiceWorkerIntro]: guide/service-worker-intro "Angular service worker introduction | Angular"
+
+[AioGuideSetupLocal]: guide/setup-local "Setting up the local environment and workspace | Angular"
+
+[AioGuideStructuralDirectives]: guide/structural-directives "Writing structural directives | Angular"
+
+[AioGuideStyleguide0201]: guide/styleguide#02-01 "Style 02-01 - Angular coding style guide | Angular"
+
+[AioGuideTemplateReferenceVariables]: guide/template-reference-variables "Template variables | Angular"
+[AioGuideTemplateReferenceVariablesTemplateInputVariable]: guide/template-reference-variables#template-input-variable "Template input variable - Template variables | Angular"
+
+[AioGuideTemplateSyntax]: guide/template-syntax "Template syntax | Angular"
+
+[AioGuideTypescriptConfiguration]: guide/typescript-configuration "TypeScript configuration | Angular"
+
+[AioGuideUniversal]: guide/universal "Server-side rendering (SSR) with Angular Universal | Angular"
+
+[AioGuideWorkspaceConfig]: guide/workspace-config "Angular workspace configuration | Angular"
+[AioGuideWorkspaceConfigProjectToolConfigurationOptions]: guide/workspace-config#project-tool-configuration-options "Project tool configuration options - Angular workspace configuration | Angular"
+
+
+
+[AngularBlogAPlanForVersion80AndIvyB3318dfc19f7]: https://blog.angular.io/a-plan-for-version-8-0-and-ivy-b3318dfc19f7 "A plan for version 8.0 and Ivy | Angular Blog"
+
+[GithubAngularAngularCliTreePrimaryPackagesAngularDevkitBuildAngularSrcBuildersBrowser]: https://github.com/angular/angular-cli/tree/master/packages/angular_devkit/build_angular/src/builders/browser "packages/angular_devkit/build_angular/src/builders/browser | angular/angular-cli | GitHub"
+[GithubAngularAngularCliTreePrimaryPackagesAngularDevkitBuildAngularSrcBuildersKarma]: https://github.com/angular/angular-cli/tree/master/packages/angular_devkit/build_angular/src/builders/karma "packages/angular_devkit/build_angular/src/builders/karma | angular/angular-cli | GitHub"
+
+[GithubPalantirTslint]: https://palantir.github.io/tslint "TSLint | Palantir | GitHub"
+
+[GithubWycatsJavascriptDecorators]: https://github.com/wycats/javascript-decorators "wycats/javascript-decorators | GitHub"
+
+[GitScmMain]: https://git-scm.com "Git"
+
+[GoogleDevelopersWebFundamentalsArchitectureAppShell]: https://developers.google.com/web/fundamentals/architecture/app-shell "The App Shell Model | Web Fundamentals | Google Developers"
+
+[JsWebpackMain]: https://webpack.js.org "webpack | JS.ORG"
+
+[MdnDocsWebApiCustomelementregistry]: https://developer.mozilla.org/docs/Web/API/CustomElementRegistry "CustomElementRegistry | MDN"
+
+[NpmjsDocsAboutNpm]: https://docs.npmjs.com/about-npm "About npm | npm"
+
+[RxjsMain]: https://rxjs.dev "RxJS"
+
+[TypescriptlangMain]: https://www.typescriptlang.org "TypeScript"
+
+[WebDevFasterAngularChangeDetection]: https://web.dev/faster-angular-change-detection "Optimize Angular's change detection | web.dev"
+
+[WikipediaWikiDomainSpecificLanguage]: https://en.wikipedia.org/wiki/Domain-specific_language "Domain-specific language | Wikipedia"
+[WikipediaWikiEcmascript]: https://en.wikipedia.org/wiki/ECMAScript "ECMAScript | Wikipedia"
+
+[YoutubeWatchV3iqtmusceU]: https://www.youtube.com/watch?v=3IqtmUscE_U "Brian Ford - Zones - NG-Conf 2014 | YouTube"
+
+
-Learn more about zones in this
-[Brian Ford video](https://www.youtube.com/watch?v=3IqtmUscE_U).
+@reviewed 2022-02-28
diff --git a/aio/content/guide/hierarchical-dependency-injection.md b/aio/content/guide/hierarchical-dependency-injection.md
index d2165e1d653e2..0c5ec730cf139 100644
--- a/aio/content/guide/hierarchical-dependency-injection.md
+++ b/aio/content/guide/hierarchical-dependency-injection.md
@@ -1,144 +1,125 @@
# Hierarchical injectors
-Injectors in Angular have rules that you can leverage to
-achieve the desired visibility of injectables in your applications.
-By understanding these rules, you can determine in which
-NgModule, Component or Directive you should declare a provider.
+Injectors in Angular have rules that you can leverage to achieve the desired visibility of injectables in your applications.
+By understanding these rules, you can determine in which NgModule, Component or Directive you should declare a provider.
+
+
+
+**NOTE**:
+This topic uses the following pictographs.
+
+| html entities | pictographs |
+|:--- |:--- |
+| 🌺
| red hibiscus \(`🌺`\) |
+| 🌻
| sunflower \(`🌻`\) |
+| 🌼
| yellow flower \(`🌼`\) |
+| 🌿
| fern \(`🌿`\) |
+| 🍁
| maple leaf \(`🍁`\) |
+| 🐳
| whale \(`🐳`\) |
+| 🐶
| dog \(`🐶`\) |
+| 🦔
| hedgehog \(`🦔`\) |
+
+
## Two injector hierarchies
There are two injector hierarchies in Angular:
-1. `ModuleInjector` hierarchy—configure a `ModuleInjector`
-in this hierarchy using an `@NgModule()` or `@Injectable()` annotation.
-1. `ElementInjector` hierarchy—created implicitly at each
-DOM element. An `ElementInjector` is empty by default
-unless you configure it in the `providers` property on
-`@Directive()` or `@Component()`.
+| Injector hierarchies | Details |
+|:--- |:--- |
+| `ModuleInjector` hierarchy | Configure a `ModuleInjector` in this hierarchy using an `@NgModule()` or `@Injectable()` annotation. |
+| `ElementInjector` hierarchy | Created implicitly at each DOM element. An `ElementInjector` is empty by default unless you configure it in the `providers` property on `@Directive()` or `@Component()`. |
-{@a register-providers-injectable}
+
### `ModuleInjector`
The `ModuleInjector` can be configured in one of two ways:
-* Using the `@Injectable()` `providedIn` property to
-refer to `@NgModule()`, or `root`.
-* Using the `@NgModule()` `providers` array.
+* Using the `@Injectable()` `providedIn` property to refer to `@NgModule()`, or `root`
+* Using the `@NgModule()` `providers` array
-
Tree-shaking and @Injectable()
+Tree-shaking and @Injectable()
-Using the `@Injectable()` `providedIn` property is preferable
-to the `@NgModule()` `providers`
-array because with `@Injectable()` `providedIn`, optimization
-tools can perform
-tree-shaking, which removes services that your application isn't
-using and results in smaller bundle sizes.
+Using the `@Injectable()` `providedIn` property is preferable to the `@NgModule()` `providers` array because with `@Injectable()` `providedIn`, optimization tools can perform tree-shaking, which removes services that your application isn't using and results in smaller bundle sizes.
-Tree-shaking is especially useful for a library
-because the application which uses the library may not have
-a need to inject it. Read more
-about [tree-shakable providers](guide/architecture-services#providing-services)
-in [Introduction to services and dependency injection](guide/architecture-services).
+Tree-shaking is especially useful for a library because the application which uses the library may not have a need to inject it.
+Read more about [tree-shakable providers](guide/architecture-services#providing-services) in [Introduction to services and dependency injection](guide/architecture-services).
-`ModuleInjector` is configured by the `@NgModule.providers` and
-`NgModule.imports` property. `ModuleInjector` is a flattening of
-all of the providers arrays which can be reached by following the
-`NgModule.imports` recursively.
+`ModuleInjector` is configured by the `@NgModule.providers` and `NgModule.imports` property.
+`ModuleInjector` is a flattening of all of the providers arrays which can be reached by following the `NgModule.imports` recursively.
Child `ModuleInjector`s are created when lazy loading other `@NgModules`.
Provide services with the `providedIn` property of `@Injectable()` as follows:
-```ts
+
-import { Injectable } from '@angular/core';
+import { Injectable } from '@angular/core';
-@Injectable({
- providedIn: 'root' // <--provides this service in the root ModuleInjector
+@Injectable({
+ providedIn: 'root' // <--provides this service in the root ModuleInjector
})
export class ItemService {
name = 'telephone';
}
-```
+
The `@Injectable()` decorator identifies a service class.
-The `providedIn` property configures a specific `ModuleInjector`,
-here `root`, which makes the service available in the `root` `ModuleInjector`.
+The `providedIn` property configures a specific `ModuleInjector`, here `root`, which makes the service available in the `root` `ModuleInjector`.
#### Platform injector
-There are two more injectors above `root`, an
-additional `ModuleInjector` and `NullInjector()`.
+There are two more injectors above `root`, an additional `ModuleInjector` and `NullInjector()`.
+
+Consider how Angular bootstraps the application with the following in `main.ts`:
+
+
-Consider how Angular bootstraps the application with the
-following in `main.ts`:
+platformBrowserDynamic().bootstrapModule(AppModule).then(ref => {…})
-```javascript
-platformBrowserDynamic().bootstrapModule(AppModule).then(ref => {...})
-```
+
-The `bootstrapModule()` method creates a child injector of
-the platform injector which is configured by the `AppModule`.
+The `bootstrapModule()` method creates a child injector of the platform injector which is configured by the `AppModule`.
This is the `root` `ModuleInjector`.
-The `platformBrowserDynamic()` method creates an injector
-configured by a `PlatformModule`, which contains platform-specific
-dependencies. This allows multiple applications to share a platform
-configuration.
-For example, a browser has only one URL bar, no matter how
-many applications you have running.
-You can configure additional platform-specific providers at the
-platform level by supplying `extraProviders` using the `platformBrowser()` function.
-
-The next parent injector in the hierarchy is the `NullInjector()`,
-which is the top of the tree. If you've gone so far up the tree
-that you are looking for a service in the `NullInjector()`, you'll
-get an error unless you've used `@Optional()` because ultimately,
-everything ends at the `NullInjector()` and it returns an error or,
-in the case of `@Optional()`, `null`. For more information on
-`@Optional()`, see the [`@Optional()` section](guide/hierarchical-dependency-injection#optional) of this guide.
-
-The following diagram represents the relationship between the
-`root` `ModuleInjector` and its parent injectors as the
-previous paragraphs describe.
+The `platformBrowserDynamic()` method creates an injector configured by a `PlatformModule`, which contains platform-specific dependencies.
+This allows multiple applications to share a platform configuration.
+For example, a browser has only one URL bar, no matter how many applications you have running.
+You can configure additional platform-specific providers at the platform level by supplying `extraProviders` using the `platformBrowser()` function.
+
+The next parent injector in the hierarchy is the `NullInjector()`, which is the top of the tree.
+If you've gone so far up the tree that you are looking for a service in the `NullInjector()`, you'll get an error unless you've used `@Optional()` because ultimately, everything ends at the `NullInjector()` and it returns an error or, in the case of `@Optional()`, `null`.
+For more information on `@Optional()`, see the [`@Optional()` section](guide/hierarchical-dependency-injection#optional) of this guide.
+
+The following diagram represents the relationship between the `root` `ModuleInjector` and its parent injectors as the previous paragraphs describe.
-
+
+
+
-While the name `root` is a special alias, other `ModuleInjector`s
-don't have aliases. You have the option to create `ModuleInjector`s
-whenever a dynamically loaded component is created, such as with
-the Router, which will create child `ModuleInjector`s.
+While the name `root` is a special alias, other `ModuleInjector`s don't have aliases.
+You have the option to create `ModuleInjector`s whenever a dynamically loaded component is created, such as with the Router, which will create child `ModuleInjector`s.
-All requests forward up to the root injector, whether you configured it
-with the `bootstrapModule()` method, or registered all providers
-with `root` in their own services.
+All requests forward up to the root injector, whether you configured it with the `bootstrapModule()` method, or registered all providers with `root` in their own services.
-
@Injectable()
vs. @NgModule()
-
-If you configure an app-wide provider in the `@NgModule()` of
-`AppModule`, it overrides one configured for `root` in the
-`@Injectable()` metadata. You can do this to configure a
-non-default provider of a service that is shared with multiple applications.
+@Injectable()
vs. @NgModule()
-Here is an example of the case where the component router
-configuration includes
-a non-default [location strategy](guide/router#location-strategy)
-by listing its provider
-in the `providers` list of the `AppModule`.
+If you configure an app-wide provider in the `@NgModule()` of `AppModule`, it overrides one configured for `root` in the `@Injectable()` metadata.
+You can do this to configure a non-default provider of a service that is shared with multiple applications.
-
+Here is an example of the case where the component router configuration includes a non-default [location strategy](guide/router#location-strategy) by listing its provider in the `providers` list of the `AppModule`.
-
+
@@ -146,904 +127,748 @@ in the `providers` list of the `AppModule`.
Angular creates `ElementInjector`s implicitly for each DOM element.
-Providing a service in the `@Component()` decorator using
-its `providers` or `viewProviders`
-property configures an `ElementInjector`.
-For example, the following `TestComponent` configures the `ElementInjector`
-by providing the service as follows:
+Providing a service in the `@Component()` decorator using its `providers` or `viewProviders` property configures an `ElementInjector`.
+For example, the following `TestComponent` configures the `ElementInjector` by providing the service as follows:
+
+
-```ts
-@Component({
- ...
+@Component({
+ …
providers: [{ provide: ItemService, useValue: { name: 'lamp' } }]
})
export class TestComponent
-```
+
-**Note:** See the
-[resolution rules](guide/hierarchical-dependency-injection#resolution-rules)
-section to understand the relationship between the `ModuleInjector` tree and
-the `ElementInjector` tree.
+**NOTE**:
+See the [resolution rules](guide/hierarchical-dependency-injection#resolution-rules) section to understand the relationship between the `ModuleInjector` tree and the `ElementInjector` tree.
-
-When you provide services in a component, that service is available by way of
-the `ElementInjector` at that component instance.
-It may also be visible at
-child component/directives based on visibility rules described in the [resolution rules](guide/hierarchical-dependency-injection#resolution-rules) section.
+When you provide services in a component, that service is available by way of the `ElementInjector` at that component instance.
+It may also be visible at child component/directives based on visibility rules described in the [resolution rules](guide/hierarchical-dependency-injection#resolution-rules) section.
When the component instance is destroyed, so is that service instance.
#### `@Directive()` and `@Component()`
-A component is a special type of directive, which means that
-just as `@Directive()` has a `providers` property, `@Component()` does too.
-This means that directives as well as components can configure
-providers, using the `providers` property.
-When you configure a provider for a component or directive
-using the `providers` property,
-that provider belongs to the `ElementInjector` of that component or
-directive.
+A component is a special type of directive, which means that just as `@Directive()` has a `providers` property, `@Component()` does too.
+This means that directives as well as components can configure providers, using the `providers` property.
+When you configure a provider for a component or directive using the `providers` property, that provider belongs to the `ElementInjector` of that component or directive.
Components and directives on the same element share an injector.
-
-{@a resolution-rules}
+
## Resolution rules
-When resolving a token for a component/directive, Angular
-resolves it in two phases:
+When resolving a token for a component/directive, Angular resolves it in two phases:
-1. Against the `ElementInjector` hierarchy (its parents)
-1. Against the `ModuleInjector` hierarchy (its parents)
+1. Against the `ElementInjector` hierarchy \(its parents\).
+1. Against the `ModuleInjector` hierarchy \(its parents\).
-When a component declares a dependency, Angular tries to satisfy that
-dependency with its own `ElementInjector`.
-If the component's injector lacks the provider, it passes the request
-up to its parent component's `ElementInjector`.
+When a component declares a dependency, Angular tries to satisfy that dependency with its own `ElementInjector`.
+If the component's injector lacks the provider, it passes the request up to its parent component's `ElementInjector`.
-The requests keep forwarding up until Angular finds an injector that can
-handle the request or runs out of ancestor `ElementInjector`s.
+The requests keep forwarding up until Angular finds an injector that can handle the request or runs out of ancestor `ElementInjector`s.
-If Angular doesn't find the provider in any `ElementInjector`s,
-it goes back to the element where the request originated and looks
-in the `ModuleInjector` hierarchy.
+If Angular doesn't find the provider in any `ElementInjector`s, it goes back to the element where the request originated and looks in the `ModuleInjector` hierarchy.
If Angular still doesn't find the provider, it throws an error.
-If you have registered a provider for the same DI token at
-different levels, the first one Angular encounters is the one
-it uses to resolve the dependency. If, for example, a provider
-is registered locally in the component that needs a service,
+If you have registered a provider for the same DI token at different levels, the first one Angular encounters is the one it uses to resolve the dependency.
+If, for example, a provider is registered locally in the component that needs a service,
Angular doesn't look for another provider of the same service.
-
## Resolution modifiers
-Angular's resolution behavior can be modified with `@Optional()`, `@Self()`,
-`@SkipSelf()` and `@Host()`. Import each of them from `@angular/core`
-and use each in the component class constructor when you inject your service.
+Angular's resolution behavior can be modified with `@Optional()`, `@Self()`, `@SkipSelf()` and `@Host()`.
+Import each of them from `@angular/core` and use each in the component class constructor when you inject your service.
-For a working application showcasing the resolution modifiers that
-this section covers, see the resolution modifiers example .
+For a working application showcasing the resolution modifiers that this section covers, see the resolution modifiers example .
### Types of modifiers
Resolution modifiers fall into three categories:
-1. What to do if Angular doesn't find what you're
-looking for, that is `@Optional()`
-2. Where to start looking, that is `@SkipSelf()`
-3. Where to stop looking, `@Host()` and `@Self()`
+* What to do if Angular doesn't find what you're looking for, that is `@Optional()`
+* Where to start looking, that is `@SkipSelf()`
+* Where to stop looking, `@Host()` and `@Self()`
-By default, Angular always starts at the current `Injector` and keeps
-searching all the way up. Modifiers allow you to change the starting
-(self) or ending location.
+By default, Angular always starts at the current `Injector` and keeps searching all the way up.
+Modifiers allow you to change the starting \(self\) or ending location.
Additionally, you can combine all of the modifiers except `@Host()` and `@Self()` and of course `@SkipSelf()` and `@Self()`.
-{@a optional}
+
### `@Optional()`
`@Optional()` allows Angular to consider a service you inject to be optional.
-This way, if it can't be resolved at runtime, Angular resolves the service as `null`, rather than throwing an error. In
-the following example, the service, `OptionalService`, isn't provided in
-the service, `@NgModule()`, or component class, so it isn't available
-anywhere in the app.
-
-
-
-
+This way, if it can't be resolved at runtime, Angular resolves the service as `null`, rather than throwing an error.
+In the following example, the service, `OptionalService`, isn't provided in the service, `@NgModule()`, or component class, so it isn't available anywhere in the app.
+
### `@Self()`
Use `@Self()` so that Angular will only look at the `ElementInjector` for the current component or directive.
-A good use case for `@Self()` is to inject a service but only if it is
-available on the current host element. To avoid errors in this situation,
-combine `@Self()` with `@Optional()`.
+A good use case for `@Self()` is to inject a service but only if it is available on the current host element.
+To avoid errors in this situation, combine `@Self()` with `@Optional()`.
-For example, in the following `SelfComponent`, notice
-the injected `LeafService` in
-the constructor.
+For example, in the following `SelfComponent`, notice the injected `LeafService` in the constructor.
-
+
-
-
-In this example, there is a parent provider and injecting the
-service will return the value, however, injecting the service
-with `@Self()` and `@Optional()` will return `null` because
-`@Self()` tells the injector to stop searching in the current
-host element.
-
-Another example shows the component class with a provider
-for `FlowerService`. In this case, the injector looks no further
-than the current `ElementInjector` because it finds the `FlowerService` and returns the yellow flower 🌼.
+In this example, there is a parent provider and injecting the service will return the value, however, injecting the service with `@Self()` and `@Optional()` will return `null` because `@Self()` tells the injector to stop searching in the current host element.
+Another example shows the component class with a provider for `FlowerService`.
+In this case, the injector looks no further than the current `ElementInjector` because it finds the `FlowerService` and returns the yellow flower \(🌼
\).
-
-
-
+
### `@SkipSelf()`
-`@SkipSelf()` is the opposite of `@Self()`. With `@SkipSelf()`, Angular
-starts its search for a service in the parent `ElementInjector`, rather than
-in the current one. So if the parent `ElementInjector` were using the value `🌿` (fern)
-for `emoji` , but you had `🍁` (maple leaf) in the component's `providers` array,
-Angular would ignore `🍁` (maple leaf) and use `🌿` (fern).
+`@SkipSelf()` is the opposite of `@Self()`.
+With `@SkipSelf()`, Angular starts its search for a service in the parent `ElementInjector`, rather than in the current one.
+So if the parent `ElementInjector` were using the fern \(🌿
\) value for `emoji`, but you had maple leaf \(🍁
\) in the component's `providers` array, Angular would ignore maple leaf \(🍁
\) and use fern \(🌿
\).
To see this in code, assume that the following value for `emoji` is what the parent component were using, as in this service:
-
-
-
-
-Imagine that in the child component, you had a different value, `🍁` (maple leaf) but you wanted to use the parent's value instead. This is when you'd use `@SkipSelf()`:
+
-
+Imagine that in the child component, you had a different value, maple leaf \(🍁
\) but you wanted to use the parent's value instead.
+This is when you'd use `@SkipSelf()`:
-
+
-In this case, the value you'd get for `emoji` would be `🌿` (fern), not `🍁` (maple leaf).
+In this case, the value you'd get for `emoji` would be fern \(🌿
\), not maple leaf \(🍁
\).
#### `@SkipSelf()` with `@Optional()`
-Use `@SkipSelf()` with `@Optional()` to prevent an error if the value is `null`. In the following example, the `Person` service is injected in the constructor. `@SkipSelf()` tells Angular to skip the current injector and `@Optional()` will prevent an error should the `Person` service be `null`.
+Use `@SkipSelf()` with `@Optional()` to prevent an error if the value is `null`.
+In the following example, the `Person` service is injected in the constructor.
+`@SkipSelf()` tells Angular to skip the current injector and `@Optional()` will prevent an error should the `Person` service be `null`.
+
+
-``` ts
class Person {
- constructor(@Optional() @SkipSelf() parent?: Person) {}
+ constructor(@Optional() @SkipSelf() parent?: Person) {}
}
-```
-
-### `@Host()`
-
-`@Host()` lets you designate a component as the last stop in the injector tree when searching for providers. Even if there is a service instance further up the tree, Angular won't continue looking. Use `@Host()` as follows:
-
-
+### `@Host()`
+
+`@Host()` lets you designate a component as the last stop in the injector tree when searching for providers.
+Even if there is a service instance further up the tree, Angular won't continue looking
+Use `@Host()` as follows:
-Since `HostComponent` has `@Host()` in its constructor, no
-matter what the parent of `HostComponent` might have as a
-`flower.emoji` value,
-the `HostComponent` will use `🌼` (yellow flower).
+
+Since `HostComponent` has `@Host()` in its constructor, no matter what the parent of `HostComponent` might have as a `flower.emoji` value, the `HostComponent` will use yellow flower \(🌼
\).
## Logical structure of the template
-When you provide services in the component class, services are
-visible within the `ElementInjector` tree relative to where
-and how you provide those services.
+When you provide services in the component class, services are visible within the `ElementInjector` tree relative to where and how you provide those services.
-Understanding the underlying logical structure of the Angular
-template will give you a foundation for configuring services
-and in turn control their visibility.
+Understanding the underlying logical structure of the Angular template will give you a foundation for configuring services and in turn control their visibility.
Components are used in your templates, as in the following example:
-```
-
-
-
-```
+
+
+<app-root>
+ <app-child></app-child>
+</app-root>
+
+
-**Note:** Usually, you declare the components and their
-templates in separate files. For the purposes of understanding
-how the injection system works, it is useful to look at them
-from the point of view of a combined logical tree. The term
-logical distinguishes it from the render tree (your application
-DOM tree). To mark the locations of where the component
-templates are located, this guide uses the `<#VIEW>`
-pseudo element, which doesn't actually exist in the render tree
-and is present for mental model purposes only.
+**NOTE**:
+Usually, you declare the components and their templates in separate files.
+For the purposes of understanding how the injection system works, it is useful to look at them from the point of view of a combined logical tree.
+The term logical distinguishes it from the render tree \(your application DOM tree\).
+To mark the locations of where the component templates are located, this guide uses the `<#VIEW>` pseudo element, which doesn't actually exist in the render tree and is present for mental model purposes only.
The following is an example of how the `` and `` view trees are combined into a single logical tree:
-```
-
- <#VIEW>
-
- <#VIEW>
- ...content goes here...
- #VIEW>
-
- #VIEW>
-
- ```
+
+
+<app-root>
+ <#VIEW>
+ <app-child>
+ <#VIEW>
+ …content goes here…
+ </#VIEW>
+ </app-child>
+ </#VIEW>
+</app-root>
+
+
Understanding the idea of the `<#VIEW>` demarcation is especially significant when you configure services in the component class.
## Providing services in `@Component()`
-How you provide services using a `@Component()` (or `@Directive()`)
-decorator determines their visibility. The following sections
-demonstrate `providers` and `viewProviders` along with ways to
-modify service visibility with `@SkipSelf()` and `@Host()`.
+How you provide services using a `@Component()` \(or `@Directive()`\) decorator determines their visibility.
+The following sections demonstrate `providers` and `viewProviders` along with ways to modify service visibility with `@SkipSelf()` and `@Host()`.
A component class can provide services in two ways:
-1. with a `providers` array
-
-```typescript=
-@Component({
- ...
- providers: [
- {provide: FlowerService, useValue: {emoji: '🌺'}}
- ]
-})
-```
-
-2. with a `viewProviders` array
-
-```typescript=
-@Component({
- ...
- viewProviders: [
- {provide: AnimalService, useValue: {emoji: '🐶'}}
- ]
-})
-```
+| Arrays | Details |
+|:--- |:--- |
+| With a `providers` array | @Component({ 
 … 
 providers: [ 
 {provide: FlowerService, useValue: {emoji: '🌺'}} 
 ] 
}) |
+| With a `viewProviders` array | @Component({ 
 … 
 viewProviders: [ 
 {provide: AnimalService, useValue: {emoji: '🐶'}} 
 ] 
}) |
-To understand how the `providers` and `viewProviders` influence service
-visibility differently, the following sections build
-a
-step-by-step and compare the use of `providers` and `viewProviders`
-in code and a logical tree.
+To understand how the `providers` and `viewProviders` influence service visibility differently, the following sections build a step-by-step and compare the use of `providers` and `viewProviders` in code and a logical tree.
-**NOTE:** In the logical tree, you'll see `@Provide`, `@Inject`, and
-`@NgModule`, which are not real HTML attributes but are here to demonstrate
-what is going on under the hood.
+**NOTE**:
+In the logical tree, you'll see `@Provide`, `@Inject`, and `@NgModule`, which are not real HTML attributes but are here to demonstrate what is going on under the hood.
-- `@Inject(Token)=>Value` demonstrates that if `Token` is injected at
-this location in the logical tree its value would be `Value`.
-- `@Provide(Token=Value)` demonstrates that there is a declaration of
-`Token` provider with value `Value` at this location in the logical tree.
-- `@NgModule(Token)` demonstrates that a fallback `NgModule` injector
-should be used at this location.
+| Angular service attribute | Details |
+|:--- |:--- |
+| @Inject(Token)=>Value | Demonstrates that if `Token` is injected at this location in the logical tree its value would be `Value`. |
+| @Provide(Token=Value) | Demonstrates that there is a declaration of `Token` provider with value `Value` at this location in the logical tree. |
+| @NgModule(Token) | Demonstrates that a fallback `NgModule` injector should be used at this location. |
-
### Example app structure
-The example application has a `FlowerService` provided in `root` with an `emoji`
-value of `🌺` (red hibiscus).
+The example application has a `FlowerService` provided in `root` with an `emoji` value of red hibiscus \(🌺
\).
+
+
+
+Consider an application with only an `AppComponent` and a `ChildComponent`.
+The most basic rendered view would look like nested HTML elements such as the following:
+
+
-
+<app-root> <!-- AppComponent selector -->
+ <app-child> <!-- ChildComponent selector -->
+ </app-child>
+</app-root>
-Consider an application with only an `AppComponent` and a `ChildComponent`.
-The most basic rendered view would look like nested HTML elements such as
-the following:
-
-```
-
-
-
-
-```
-
-However, behind the scenes, Angular uses a logical view
-representation as follows when resolving injection requests:
-
-```
-
- <#VIEW>
-
- <#VIEW>
- #VIEW>
-
- #VIEW>
-
- ```
+However, behind the scenes, Angular uses a logical view representation as follows when resolving injection requests:
+
+
+
+<app-root> <!-- AppComponent selector -->
+ <#VIEW>
+ <app-child> <!-- ChildComponent selector -->
+ <#VIEW>
+ </#VIEW>
+ </app-child>
+ </#VIEW>
+</app-root>
+
+
The `<#VIEW>` here represents an instance of a template.
Notice that each component has its own `<#VIEW>`.
-Knowledge of this structure can inform how you provide and
-inject your services, and give you complete control of service visibility.
+Knowledge of this structure can inform how you provide and inject your services, and give you complete control of service visibility.
Now, consider that `` injects the `FlowerService`:
+
-
+Add a binding to the `` template to visualize the result:
-
+
-Add a binding to the `` template to visualize the result:
+The output in the view would be:
+
+
-
+Emoji from FlowerService: 🌺
+In the logical tree, this would be represented as follows:
-The output in the view would be:
+
-```
-Emoji from FlowerService: 🌺
-```
+<app-root @NgModule(AppModule)
+ @Inject(FlowerService) flower=>"🌺">
+ <#VIEW>
+ <p>Emoji from FlowerService: {{flower.emoji}} (🌺)</p>
+ <app-child>
+ <#VIEW>
+ </#VIEW>
+ </app-child>
+ </#VIEW>
+</app-root>
-In the logical tree, this would be represented as follows:
+
+
+When `` requests the `FlowerService`, it is the injector's job to resolve the `FlowerService` token.
+The resolution of the token happens in two phases:
+
+1. The injector determines the starting location in the logical tree and an ending location of the search.
+ The injector begins with the starting location and looks for the token at each level in the logical tree.
+ If the token is found it is returned.
-```
-"🌺">
- <#VIEW>
- Emoji from FlowerService: {{flower.emoji}} (🌺)
-
- <#VIEW>
- #VIEW>
-
- #VIEW>
-
-```
-
-When `` requests the `FlowerService`, it is the injector's job
-to resolve the `FlowerService` token. The resolution of the token happens
-in two phases:
-
-1. The injector determines the starting location in the logical tree and
-an ending location of the search. The injector begins with the starting
-location and looks for the token at each level in the logical tree. If
-the token is found it is returned.
-2. If the token is not found, the injector looks for the closest
-parent `@NgModule()` to delegate the request to.
+1. If the token is not found, the injector looks for the closest parent `@NgModule()` to delegate the request to.
In the example case, the constraints are:
-1. Start with `<#VIEW>` belonging to `` and end with ``.
+1. Start with `<#VIEW>` belonging to `` and end with ``.
- - Normally the starting point for search is at the point
- of injection. However, in this case `` `@Component`s
- are special in that they also include their own `viewProviders`,
- which is why the search starts at `<#VIEW>` belonging to ``.
- (This would not be the case for a directive matched at the same location).
- - The ending location happens to be the same as the component
- itself, because it is the topmost component in this application.
+ * Normally the starting point for search is at the point of injection.
+ However, in this case `` `@Component`s are special in that they also include their own `viewProviders`, which is why the search starts at `<#VIEW>` belonging to ``.
+ \(This would not be the case for a directive matched at the same location.\)
-2. The `AppModule` acts as the fallback injector when the
-injection token can't be found in the `ElementInjector`s.
+ * The ending location happens to be the same as the component itself, because it is the topmost component in this application.
-### Using the `providers` array
+1. The `AppModule` acts as the fallback injector when the injection token can't be found in the `ElementInjector`s.
-Now, in the `ChildComponent` class, add a provider for `FlowerService`
-to demonstrate more complex resolution rules in the upcoming sections:
+### Using the `providers` array
-
+Now, in the `ChildComponent` class, add a provider for `FlowerService` to demonstrate more complex resolution rules in the upcoming sections:
-
+
-Now that the `FlowerService` is provided in the `@Component()` decorator,
-when the `` requests the service, the injector has only to look
-as far as the ``'s own `ElementInjector`. It won't have to
-continue the search any further through the injector tree.
+Now that the `FlowerService` is provided in the `@Component()` decorator, when the `` requests the service, the injector has only to look as far as the ``'s own `ElementInjector`.
+It won't have to continue the search any further through the injector tree.
The next step is to add a binding to the `ChildComponent` template.
-
+
-
+To render the new values, add `` to the bottom of the `AppComponent` template so the view also displays the sunflower:
-To render the new values, add `` to the bottom of
-the `AppComponent` template so the view also displays the sunflower:
+
-```
Child Component
-Emoji from FlowerService: 🌻
-```
+Emoji from FlowerService: 🌻
-In the logical tree, this would be represented as follows:
+
-```
-"🌺">
- <#VIEW>
- Emoji from FlowerService: {{flower.emoji}} (🌺)
- "🌻">
- <#VIEW>
- Parent Component
- Emoji from FlowerService: {{flower.emoji}} (🌻)
- #VIEW>
-
- #VIEW>
-
-```
-
-When `` requests the `FlowerService`, the injector begins
-its search at the `<#VIEW>` belonging to `` (`<#VIEW>` is
-included because it is injected from `@Component()`) and ends with
-``. In this case, the `FlowerService` is resolved in the
-``'s `providers` array with sunflower 🌻. The injector doesn't
-have to look any further in the injector tree. It stops as soon as it
-finds the `FlowerService` and never sees the 🌺 (red hibiscus).
-
-
-{@a use-view-providers}
+In the logical tree, this would be represented as follows:
-### Using the `viewProviders` array
+
+
+<app-root @NgModule(AppModule)
+ @Inject(FlowerService) flower=>"🌺">
+ <#VIEW>
+ <p>Emoji from FlowerService: {{flower.emoji}} (🌺)</p>
+ <app-child @Provide(FlowerService="🌻")
+ @Inject(FlowerService)=>"🌻"> <!-- search ends here -->
+ <#VIEW> <!-- search starts here -->
+ <h2>Parent Component</h2>
+ <p>Emoji from FlowerService: {{flower.emoji}} (🌻)</p>
+ </#VIEW>
+ </app-child>
+ </#VIEW>
+</app-root>
-Use the `viewProviders` array as another way to provide services in the
-`@Component()` decorator. Using `viewProviders` makes services
-visible in the `<#VIEW>`.
+
-
+When `
` requests the `FlowerService`, the injector begins its search at the `<#VIEW>` belonging to `` \(`<#VIEW>` is included because it is injected from `@Component()`\) and ends with ``.
+In this case, the `FlowerService` is resolved in the ``'s `providers` array with sunflower \(🌻
\).
+The injector doesn't have to look any further in the injector tree.
+It stops as soon as it finds the `FlowerService` and never sees the red hibiscus \(🌺
\).
-The steps are the same as using the `providers` array,
-with the exception of using the `viewProviders` array instead.
+
-For step-by-step instructions, continue with this section. If you can
-set it up on your own, skip ahead to [Modifying service availability](guide/hierarchical-dependency-injection#modify-visibility).
+### Using the `viewProviders` array
-
+Use the `viewProviders` array as another way to provide services in the `@Component()` decorator.
+Using `viewProviders` makes services visible in the `<#VIEW>`.
+
-The example application features a second service, the `AnimalService` to
-demonstrate `viewProviders`.
+The steps are the same as using the `providers` array, with the exception of using the `viewProviders` array instead.
-First, create an `AnimalService` with an `emoji` property of 🐳 (whale):
+For step-by-step instructions, continue with this section.
+If you can set it up on your own, skip ahead to [Modifying service availability](guide/hierarchical-dependency-injection#modify-visibility).
-
+
-
+The example application features a second service, the `AnimalService` to demonstrate `viewProviders`.
+First, create an `AnimalService` with an `emoji` property of whale \(🐳
\):
-Following the same pattern as with the `FlowerService`, inject the
-`AnimalService` in the `AppComponent` class:
+
-
+Following the same pattern as with the `FlowerService`, inject the `AnimalService` in the `AppComponent` class:
-
+
-**Note:** You can leave all the `FlowerService` related code in place
-as it will allow a comparison with the `AnimalService`.
+**NOTE**:
+You can leave all the `FlowerService` related code in place as it will allow a comparison with the `AnimalService`.
-Add a `viewProviders` array and inject the `AnimalService` in the
-`` class, too, but give `emoji` a different value. Here,
-it has a value of 🐶 (puppy).
-
-
-
+Add a `viewProviders` array and inject the `AnimalService` in the `` class, too, but give `emoji` a different value.
+Here, it has a value of dog \(🐶
\).
-
+
Add bindings to the `ChildComponent` and the `AppComponent` templates.
In the `ChildComponent` template, add the following binding:
-
-
-
+
Additionally, add the same to the `AppComponent` template:
-
-
-
+
Now you should see both values in the browser:
-```
+
+
AppComponent
-Emoji from AnimalService: 🐳
+Emoji from AnimalService: 🐳
Child Component
-Emoji from AnimalService: 🐶
+Emoji from AnimalService: 🐶
-```
+
The logic tree for this example of `viewProviders` is as follows:
+
+
+<app-root @NgModule(AppModule)
+ @Inject(AnimalService) animal=>"🐳">
+ <#VIEW>
+ <app-child>
+ <#VIEW @Provide(AnimalService="🐶")
+ @Inject(AnimalService=>"🐶")>
+ <!-- ^^using viewProviders means AnimalService is available in <#VIEW>-->
+ <p>Emoji from AnimalService: {{animal.emoji}} (🐶)</p>
+ </#VIEW>
+ </app-child>
+ </#VIEW>
+</app-root>
-```
-"🐳">
- <#VIEW>
-
- <#VIEW
- @Provide(AnimalService="🐶")
- @Inject(AnimalService=>"🐶")>
-
- Emoji from AnimalService: {{animal.emoji}} (🐶)
- #VIEW>
-
- #VIEW>
-
-```
-
-Just as with the `FlowerService` example, the `AnimalService` is provided
-in the `` `@Component()` decorator. This means that since the
-injector first looks in the `ElementInjector` of the component, it finds the
-`AnimalService` value of 🐶 (puppy). It doesn't need to continue searching the
-`ElementInjector` tree, nor does it need to search the `ModuleInjector`.
-
-### `providers` vs. `viewProviders`
-
-To see the difference between using `providers` and `viewProviders`, add
-another component to the example and call it `InspectorComponent`.
-`InspectorComponent` will be a child of the `ChildComponent`. In
-`inspector.component.ts`, inject the `FlowerService` and `AnimalService` in
-the constructor:
+
+Just as with the `FlowerService` example, the `AnimalService` is provided in the `` `@Component()` decorator.
+This means that since the injector first looks in the `ElementInjector` of the component, it finds the `AnimalService` value of dog \(🐶
\).
+It doesn't need to continue searching the `ElementInjector` tree, nor does it need to search the `ModuleInjector`.
-
+### `providers` vs. `viewProviders`
-
+To see the difference between using `providers` and `viewProviders`, add another component to the example and call it `InspectorComponent`.
+`InspectorComponent` will be a child of the `ChildComponent`.
+In `inspector.component.ts`, inject the `FlowerService` and `AnimalService` in the constructor:
-You do not need a `providers` or `viewProviders` array. Next, in
-`inspector.component.html`, add the same markup from previous components:
+
-
+You do not need a `providers` or `viewProviders` array.
+Next, in `inspector.component.html`, add the same markup from previous components:
-
+
Remember to add the `InspectorComponent` to the `AppModule` `declarations` array.
-
-
-
-
+
Next, make sure your `child.component.html` contains the following:
-
-
-
+
-The first two lines, with the bindings, are there from previous steps. The
-new parts are `` and ``. `` allows
-you to project content, and `` inside the `ChildComponent`
- template makes the `InspectorComponent` a child component of
- `ChildComponent`.
+The first two lines, with the bindings, are there from previous steps.
+The new parts are `` and ``.
+`` allows you to project content, and `` inside the `ChildComponent` template makes the `InspectorComponent` a child component of `ChildComponent`.
Next, add the following to `app.component.html` to take advantage of content projection.
-
-
-
+
-The browser now renders the following, omitting the previous examples
-for brevity:
+The browser now renders the following, omitting the previous examples for brevity:
-```
+
-//...Omitting previous examples. The following applies to this section.
+//…Omitting previous examples. The following applies to this section.
Content projection: This is coming from content. Doesn't get to see
puppy because the puppy is declared inside the view only.
-Emoji from FlowerService: 🌻
-Emoji from AnimalService: 🐳
+Emoji from FlowerService: 🌻
+Emoji from AnimalService: 🐳
-Emoji from FlowerService: 🌻
-Emoji from AnimalService: 🐶
+Emoji from FlowerService: 🌻
+Emoji from AnimalService: 🐶
-```
+
-These four bindings demonstrate the difference between `providers`
-and `viewProviders`. Since the 🐶 (puppy) is declared inside the <#VIEW>,
-it isn't visible to the projected content. Instead, the projected
-content sees the 🐳 (whale).
+These four bindings demonstrate the difference between `providers` and `viewProviders`.
+Since the dog \(🐶
\) is declared inside the `<#VIEW>`, it isn't visible to the projected content.
+Instead, the projected content sees the whale \(🐳
\).
-The next section though, where `InspectorComponent` is a child component
-of `ChildComponent`, `InspectorComponent` is inside the `<#VIEW>`, so
-when it asks for the `AnimalService`, it sees the 🐶 (puppy).
+The next section though, where `InspectorComponent` is a child component of `ChildComponent`, `InspectorComponent` is inside the `<#VIEW>`, so when it asks for the `AnimalService`, it sees the dog \(🐶
\).
The `AnimalService` in the logical tree would look like this:
-```
-"🐳">
- <#VIEW>
-
- <#VIEW
- @Provide(AnimalService="🐶")
- @Inject(AnimalService=>"🐶")>
-
- Emoji from AnimalService: {{animal.emoji}} (🐶)
-
- Emoji from AnimalService: {{animal.emoji}} (🐶)
-
- #VIEW>
-
- <#VIEW>
- Emoji from AnimalService: {{animal.emoji}} (🐳)
- #VIEW>
-
-
- #VIEW>
-
-```
-
-The projected content of `` sees the 🐳 (whale), not
-the 🐶 (puppy), because the
-🐶 (puppy) is inside the `` `<#VIEW>`. The `` can
-only see the 🐶 (puppy)
-if it is also within the `<#VIEW>`.
-
-{@a modify-visibility}
+
+
+<app-root @NgModule(AppModule)
+ @Inject(AnimalService) animal=>"🐳">
+ <#VIEW>
+ <app-child>
+ <#VIEW @Provide(AnimalService="🐶")
+ @Inject(AnimalService=>"🐶")>
+ <!-- ^^using viewProviders means AnimalService is available in <#VIEW>-->
+ <p>Emoji from AnimalService: {{animal.emoji}} (🐶)</p>
+ <app-inspector>
+ <p>Emoji from AnimalService: {{animal.emoji}} (🐶)</p>
+ </app-inspector>
+ </#VIEW>
+ <app-inspector>
+ <#VIEW>
+ <p>Emoji from AnimalService: {{animal.emoji}} (🐳)</p>
+ </#VIEW>
+ </app-inspector>
+ </app-child>
+ </#VIEW>
+</app-root>
+
+
+
+The projected content of `` sees the whale \(🐳
\), not the dog \(🐶
\), because the dog \(🐶
\) is inside the `` `<#VIEW>`.
+The `` can only see the dog \(🐶
\) if it is also within the `<#VIEW>`.
+
+
## Modifying service visibility
-This section describes how to limit the scope of the beginning and
-ending `ElementInjector` using the visibility decorators `@Host()`,
-`@Self()`, and `@SkipSelf()`.
+This section describes how to limit the scope of the beginning and ending `ElementInjector` using the visibility decorators `@Host()`, `@Self()`, and `@SkipSelf()`.
### Visibility of provided tokens
-Visibility decorators influence where the search for the injection
-token begins and ends in the logic tree. To do this, place
-visibility decorators at the point of injection, that is, the
-`constructor()`, rather than at a point of declaration.
+Visibility decorators influence where the search for the injection token begins and ends in the logic tree.
+To do this, place visibility decorators at the point of injection, that is, the `constructor()`, rather than at a point of declaration.
+
+To alter where the injector starts looking for `FlowerService`, add `@SkipSelf()` to the `` `@Inject` declaration for the `FlowerService`.
+This declaration is in the `` constructor as shown in `child.component.ts`:
+
+
+
+constructor(@SkipSelf() public flower : FlowerService) { }
+
+
-To alter where the injector starts looking for `FlowerService`, add
-`@SkipSelf()` to the `` `@Inject` declaration for the
-`FlowerService`. This declaration is in the `` constructor
-as shown in `child.component.ts`:
+With `@SkipSelf()`, the `` injector doesn't look to itself for the `FlowerService`.
+Instead, the injector starts looking for the `FlowerService` at the ``'s `ElementInjector`, where it finds nothing.
+Then, it goes back to the `` `ModuleInjector` and finds the red hibiscus \(🌺
\) value, which is available because the `` `ModuleInjector` and the `` `ModuleInjector` are flattened into one `ModuleInjector`.
+Thus, the UI renders the following:
-```typescript=
- constructor(@SkipSelf() public flower : FlowerService) { }
-```
+
-With `@SkipSelf()`, the `` injector doesn't look to itself for
-the `FlowerService`. Instead, the injector starts looking for the
-`FlowerService` at the ``'s `ElementInjector`, where it finds
-nothing. Then, it goes back to the `` `ModuleInjector` and finds
-the 🌺 (red hibiscus) value, which is available because the ``
-`ModuleInjector` and the `` `ModuleInjector` are flattened into one
- `ModuleInjector`. Thus, the UI renders the following:
+Emoji from FlowerService: 🌺
-```
-Emoji from FlowerService: 🌺
-```
+
In a logical tree, this same idea might look like this:
-```
-"🌺">
- <#VIEW>
-
- <#VIEW @Inject(FlowerService, SkipSelf)=>"🌺">
-
- #VIEW>
-
- #VIEW>
-
-```
-
-Though `` provides the 🌻 (sunflower), the application renders
-the 🌺 (red hibiscus) because `@SkipSelf()` causes the current
-injector to skip
-itself and look to its parent.
-
-If you now add `@Host()` (in addition to the `@SkipSelf()`) to the
-`@Inject` of the `FlowerService`, the result will be `null`. This is
-because `@Host()` limits the upper bound of the search to the
-`<#VIEW>`. Here's the idea in the logical tree:
-
-```
-"🌺">
- <#VIEW>
-
- <#VIEW @Inject(FlowerService, @SkipSelf, @Host, @Optional)=>null>
- #VIEW>
-
- #VIEW>
-
-```
-
-Here, the services and their values are the same, but `@Host()`
-stops the injector from looking any further than the `<#VIEW>`
-for `FlowerService`, so it doesn't find it and returns `null`.
+
+
+<app-root @NgModule(AppModule)
+ @Inject(FlowerService) flower=>"🌺">
+ <#VIEW>
+ <app-child @Provide(FlowerService="🌻")>
+ <#VIEW @Inject(FlowerService, SkipSelf)=>"🌺">
+ <!-- With SkipSelf, the injector looks to the next injector up the tree -->
+ </#VIEW>
+ </app-child>
+ </#VIEW>
+</app-root>
+
+
+
+Though `` provides the sunflower \(🌻
\), the application renders the red hibiscus \(🌺
\) because `@SkipSelf()` causes the current injector to skip itself and look to its parent.
+
+If you now add `@Host()` \(in addition to the `@SkipSelf()`\) to the `@Inject` of the `FlowerService`, the result will be `null`.
+This is because `@Host()` limits the upper bound of the search to the `<#VIEW>`.
+Here's the idea in the logical tree:
+
+
+
+<app-root @NgModule(AppModule)
+ @Inject(FlowerService) flower=>"🌺">
+ <#VIEW> <!-- end search here with null-->
+ <app-child @Provide(FlowerService="🌻")> <!-- start search here -->
+ <#VIEW @Inject(FlowerService, @SkipSelf, @Host, @Optional)=>null>
+ </#VIEW>
+ </app-parent>
+ </#VIEW>
+</app-root>
+
+
+
+Here, the services and their values are the same, but `@Host()` stops the injector from looking any further than the `<#VIEW>` for `FlowerService`, so it doesn't find it and returns `null`.
-**Note:** The example application uses `@Optional()` so the application does
-not throw an error, but the principles are the same.
+**NOTE**:
+The example application uses `@Optional()` so the application does not throw an error, but the principles are the same.
### `@SkipSelf()` and `viewProviders`
-The `` currently provides the `AnimalService` in
-the `viewProviders` array with the value of 🐶 (puppy). Because
-the injector has only to look at the ``'s `ElementInjector`
-for the `AnimalService`, it never sees the 🐳 (whale).
+The `` currently provides the `AnimalService` in the `viewProviders` array with the value of dog \(🐶
\).
+Because the injector has only to look at the ``'s `ElementInjector` for the `AnimalService`, it never sees the whale \(🐳
\).
-As in the `FlowerService` example, if you add `@SkipSelf()`
-to the constructor for the `AnimalService`, the injector won't
-look in the current ``'s `ElementInjector` for the
-`AnimalService`.
+As in the `FlowerService` example, if you add `@SkipSelf()` to the constructor for the `AnimalService`, the injector won't look in the current ``'s `ElementInjector` for the `AnimalService`.
+
+
-```typescript=
export class ChildComponent {
-// add @SkipSelf()
- constructor(@SkipSelf() public animal : AnimalService) { }
+ // add @SkipSelf()
+ constructor(@SkipSelf() public animal : AnimalService) { }
}
-```
-Instead, the injector will begin at the ``
-`ElementInjector`. Remember that the `` class
-provides the `AnimalService` in the `viewProviders` array
-with a value of 🐶 (puppy):
+
+
+Instead, the injector will begin at the `` `ElementInjector`.
+Remember that the `` class provides the `AnimalService` in the `viewProviders` array with a value of dog \(🐶
\):
-```ts
-@Component({
+
+
+@Component({
selector: 'app-child',
- ...
+ …
viewProviders:
- [{ provide: AnimalService, useValue: { emoji: '🐶' } }]
+ [{ provide: AnimalService, useValue: { emoji: '🐶' } }]
})
-```
+
+
The logical tree looks like this with `@SkipSelf()` in ``:
-```
- "🐳")>
- <#VIEW>
-
- <#VIEW
- @Provide(AnimalService="🐶")
- @Inject(AnimalService, SkipSelf=>"🐳")>
-
- #VIEW>
-
- #VIEW>
-
-```
-
-With `@SkipSelf()` in the ``, the injector begins its
-search for the `AnimalService` in the `` `ElementInjector`
-and finds 🐳 (whale).
+
+
+<app-root @NgModule(AppModule)
+ @Inject(AnimalService=>"🐳")>
+ <#VIEW><!-- search begins here -->
+ <app-child>
+ <#VIEW @Provide(AnimalService="🐶")
+ @Inject(AnimalService, SkipSelf=>"🐳")>
+ <!--Add @SkipSelf -->
+ </#VIEW>
+ </app-child>
+ </#VIEW>
+</app-root>
+
+
+
+With `@SkipSelf()` in the ``, the injector begins its search for the `AnimalService` in the `` `ElementInjector` and finds whale \(🐳
\).
### `@Host()` and `viewProviders`
-If you add `@Host()` to the constructor for `AnimalService`, the
-result is 🐶 (puppy) because the injector finds the `AnimalService`
-in the `` `<#VIEW>`. Here is the `viewProviders` array
-in the `` class and `@Host()` in the constructor:
+If you add `@Host()` to the constructor for `AnimalService`, the result is dog \(🐶
\) because the injector finds the `AnimalService` in the `` `<#VIEW>`.
+Here is the `viewProviders` array in the `` class and `@Host()` in the constructor:
+
+
-```typescript=
-@Component({
+@Component({
selector: 'app-child',
- ...
+ …
viewProviders:
- [{ provide: AnimalService, useValue: { emoji: '🐶' } }]
+ [{ provide: AnimalService, useValue: { emoji: '🐶' } }]
})
export class ChildComponent {
- constructor(@Host() public animal : AnimalService) { }
+ constructor(@Host() public animal : AnimalService) { }
}
-```
+
+
`@Host()` causes the injector to look until it encounters the edge of the `<#VIEW>`.
-```
- "🐳")>
- <#VIEW>
-
- <#VIEW
- @Provide(AnimalService="🐶")
- @Inject(AnimalService, @Host=>"🐶")>
- #VIEW>
-
- #VIEW>
-
-```
-
-Add a `viewProviders` array with a third animal, 🦔 (hedgehog), to the
-`app.component.ts` `@Component()` metadata:
-
-```typescript
-@Component({
+
+
+<app-root @NgModule(AppModule)
+ @Inject(AnimalService=>"🐳")>
+ <#VIEW>
+ <app-child>
+ <#VIEW @Provide(AnimalService="🐶")
+ @Inject(AnimalService, @Host=>"🐶")> <!-- @Host stops search here -->
+ </#VIEW>
+ </app-child>
+ </#VIEW>
+</app-root>
+
+
+
+Add a `viewProviders` array with a third animal, hedgehog \(🦔
\), to the `app.component.ts` `@Component()` metadata:
+
+
+
+@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: [ './app.component.css' ],
- viewProviders: [{ provide: AnimalService, useValue: { emoji: '🦔' } }]
+ viewProviders: [{ provide: AnimalService, useValue: { emoji: '🦔' } }]
})
-```
-Next, add `@SkipSelf()` along with `@Host()` to the constructor for the
-`Animal Service` in `child.component.ts`. Here are `@Host()`
-and `@SkipSelf()` in the ``
-constructor :
+
+
+Next, add `@SkipSelf()` along with `@Host()` to the constructor for the `Animal Service` in `child.component.ts`.
+Here are `@Host()` and `@SkipSelf()` in the `` constructor:
+
+
-```ts
export class ChildComponent {
constructor(
- @Host() @SkipSelf() public animal : AnimalService) { }
+ @Host() @SkipSelf() public animal : AnimalService) { }
}
-```
-When `@Host()` and `SkipSelf()` were applied to the `FlowerService`,
-which is in the `providers` array, the result was `null` because
-`@SkipSelf()` starts its search in the `` injector, but
-`@Host()` stops searching at `<#VIEW>`—where there is no
-`FlowerService`. In the logical tree, you can see that the
-`FlowerService` is visible in ``, not its `<#VIEW>`.
+
+
+When `@Host()` and `SkipSelf()` were applied to the `FlowerService`, which is in the `providers` array, the result was `null` because `@SkipSelf()` starts its search in the `` injector, but `@Host()` stops searching at `<#VIEW>` —where there is no `FlowerService`
+In the logical tree, you can see that the `FlowerService` is visible in ``, not its `<#VIEW>`.
-However, the `AnimalService`, which is provided in the
-`AppComponent` `viewProviders` array, is visible.
+However, the `AnimalService`, which is provided in the `AppComponent` `viewProviders` array, is visible.
The logical tree representation shows why this is:
-```html
-"🐳")>
- <#VIEW @Provide(AnimalService="🦔")
- @Inject(AnimalService, @Optional)=>"🦔">
-
-
- <#VIEW @Provide(AnimalService="🐶")
- @Inject(AnimalService, @SkipSelf, @Host, @Optional)=>"🦔">
-
- #VIEW>
-
- #VIEW>
-
-```
-
-`@SkipSelf()`, causes the injector to start its search for
-the `AnimalService` at the ``, not the ``,
-where the request originates, and `@Host()` stops the search
-at the `` `<#VIEW>`. Since `AnimalService` is
-provided by way of the `viewProviders` array, the injector finds 🦔
-(hedgehog) in the `<#VIEW>`.
-
-
-{@a component-injectors}
+
+
+<app-root @NgModule(AppModule)
+ @Inject(AnimalService=>"🐳")>
+ <#VIEW @Provide(AnimalService="🦔")
+ @Inject(AnimalService, @Optional)=>"🦔">
+ <!-- ^^@SkipSelf() starts here, @Host() stops here^^ -->
+ <app-child>
+ <#VIEW @Provide(AnimalService="🐶")
+ @Inject(AnimalService, @SkipSelf, @Host, @Optional)=>"🦔">
+ <!-- Add @SkipSelf ^^-->
+ </#VIEW>
+ </app-child>
+ </#VIEW>
+</app-root>
+
+
+
+`@SkipSelf()`, causes the injector to start its search for the `AnimalService` at the ``, not the ``, where the request originates, and `@Host()` stops the search at the `` `<#VIEW>`.
+Since `AnimalService` is provided by way of the `viewProviders` array, the injector finds hedgehog \(🦔
\) in the `<#VIEW>`.
+
+
## `ElementInjector` use case examples
-The ability to configure one or more providers at different levels
-opens up useful possibilities.
+The ability to configure one or more providers at different levels opens up useful possibilities.
For a look at the following scenarios in a working app, see the heroes use case examples .
### Scenario: service isolation
@@ -1052,36 +877,22 @@ Architectural reasons may lead you to restrict access to a service to the applic
For example, the guide sample includes a `VillainsListComponent` that displays a list of villains.
It gets those villains from a `VillainsService`.
-If you provided `VillainsService` in the root `AppModule`
-(where you registered the `HeroesService`),
-that would make the `VillainsService` visible everywhere in the
-application, including the _Hero_ workflows. If you later
-modified the `VillainsService`, you could break something in a
-hero component somewhere.
+If you provided `VillainsService` in the root `AppModule` \(where you registered the `HeroesService`\), that would make the `VillainsService` visible everywhere in the application, including the *Hero* workflows.
+If you later modified the `VillainsService`, you could break something in a hero component somewhere.
Instead, you can provide the `VillainsService` in the `providers` metadata of the `VillainsListComponent` like this:
+
-
-
-
-
-By providing `VillainsService` in the `VillainsListComponent` metadata and nowhere else,
-the service becomes available only in the `VillainsListComponent` and its sub-component tree.
-
-`VillainService` is a singleton with respect to `VillainsListComponent`
-because that is where it is declared. As long as `VillainsListComponent`
-does not get destroyed it will be the same instance of `VillainService`
-but if there are multiple instances of `VillainsListComponent`, then each
-instance of `VillainsListComponent` will have its own instance of `VillainService`.
-
+By providing `VillainsService` in the `VillainsListComponent` metadata and nowhere else, the service becomes available only in the `VillainsListComponent` and its sub-component tree.
+`VillainService` is a singleton with respect to `VillainsListComponent` because that is where it is declared.
+As long as `VillainsListComponent` does not get destroyed it will be the same instance of `VillainService` but if there are multiple instances of `VillainsListComponent`, then each instance of `VillainsListComponent` will have its own instance of `VillainService`.
### Scenario: multiple edit sessions
Many applications allow users to work on several open tasks at the same time.
-For example, in a tax preparation application, the preparer could be working on several tax returns,
-switching from one to the other throughout the day.
+For example, in a tax preparation application, the preparer could be working on several tax returns, switching from one to the other throughout the day.
This guide demonstrates that scenario with an example in the Tour of Heroes theme.
Imagine an outer `HeroListComponent` that displays a list of super heroes.
@@ -1091,12 +902,14 @@ Each selected hero tax return opens in its own component and multiple returns ca
Each tax return component has the following characteristics:
-* Is its own tax return editing session.
-* Can change a tax return without affecting a return in another component.
-* Has the ability to save the changes to its tax return or cancel them.
+* Is its own tax return editing session
+* Can change a tax return without affecting a return in another component
+* Has the ability to save the changes to its tax return or cancel them
-
+
+
+
Suppose that the `HeroTaxReturnComponent` had logic to manage and restore changes.
@@ -1107,20 +920,13 @@ You could delegate that management to a helper service, as this example does.
The `HeroTaxReturnService` caches a single `HeroTaxReturn`, tracks changes to that return, and can save or restore it.
It also delegates to the application-wide singleton `HeroService`, which it gets by injection.
-
-
-
-
+
Here is the `HeroTaxReturnComponent` that makes use of `HeroTaxReturnService`.
+
-
-
-
-
-
-The _tax-return-to-edit_ arrives by way of the `@Input()` property, which is implemented with getters and setters.
+The *tax-return-to-edit* arrives by way of the `@Input()` property, which is implemented with getters and setters.
The setter initializes the component's own instance of the `HeroTaxReturnService` with the incoming return.
The getter always returns what that service says is the current state of the hero.
The component also asks the service to save and restore this tax return.
@@ -1130,16 +936,11 @@ Every component would share the same service instance, and each component would
To prevent this, configure the component-level injector of `HeroTaxReturnComponent` to provide the service, using the `providers` property in the component metadata.
-
-
-
-
-
+
The `HeroTaxReturnComponent` has its own provider of the `HeroTaxReturnService`.
-Recall that every component _instance_ has its own injector.
-Providing the service at the component level ensures that _every_ instance of the component gets its own, private instance of the service, and no tax return gets overwritten.
-
+Recall that every component *instance* has its own injector.
+Providing the service at the component level ensures that *every* instance of the component gets its own, private instance of the service, and no tax return gets overwritten.
@@ -1148,40 +949,43 @@ You can review it and download it from the .
-
-
### Scenario: specialized providers
-Another reason to re-provide a service at another level is to substitute a _more specialized_ implementation of that service, deeper in the component tree.
+Another reason to re-provide a service at another level is to substitute a *more specialized* implementation of that service, deeper in the component tree.
Consider a Car component that depends on several services.
-Suppose you configured the root injector (marked as A) with _generic_ providers for
-`CarService`, `EngineService` and `TiresService`.
-
-You create a car component (A) that displays a car constructed from these three generic services.
+Suppose you configured the root injector \(marked as A\) with *generic* providers for `CarService`, `EngineService` and `TiresService`.
-Then you create a child component (B) that defines its own, _specialized_ providers for `CarService` and `EngineService`
-that have special capabilities suitable for whatever is going on in component (B).
+You create a car component \(A\) that displays a car constructed from these three generic services.
-Component (B) is the parent of another component (C) that defines its own, even _more specialized_ provider for `CarService`.
+Then you create a child component \(B\) that defines its own, *specialized* providers for `CarService` and `EngineService` that have special capabilities suitable for whatever is going on in component \(B\).
+Component \(B\) is the parent of another component \(C\) that defines its own, even *more specialized* provider for `CarService`.
-
+
+
+
Behind the scenes, each component sets up its own injector with zero, one, or more providers defined for that component itself.
-When you resolve an instance of `Car` at the deepest component (C),
-its injector produces an instance of `Car` resolved by injector (C) with an `Engine` resolved by injector (B) and
-`Tires` resolved by the root injector (A).
-
+When you resolve an instance of `Car` at the deepest component \(C\), its injector produces an instance of `Car` resolved by injector \(C\) with an `Engine` resolved by injector \(B\) and `Tires` resolved by the root injector \(A\).
-
-
+
+
+
## More on dependency injection
For more information on Angular dependency injection, see the [DI Providers](guide/dependency-injection-providers) and [DI in Action](guide/dependency-injection-in-action) guides.
+
+
+
+
+
+
+
+@reviewed 2022-02-28
diff --git a/aio/content/guide/http.md b/aio/content/guide/http.md
index ce24f022f111f..616a15488d7d5 100644
--- a/aio/content/guide/http.md
+++ b/aio/content/guide/http.md
@@ -5,58 +5,47 @@ Angular provides a client HTTP API for Angular applications, the `HttpClient` se
The HTTP client service offers the following major features.
-* The ability to request [typed response objects](#typed-response).
-* Streamlined [error handling](#error-handling).
-* [Testability](#testing-requests) features.
-* Request and response [interception](#intercepting-requests-and-responses).
+* The ability to request [typed response objects](#typed-response)
+* Streamlined [error handling](#error-handling)
+* [Testability](#testing-requests) features
+* Request and response [interception](#intercepting-requests-and-responses)
-##### Prerequisites
+## Prerequisites
Before working with the `HttpClientModule`, you should have a basic understanding of the following:
-* TypeScript programming
-* Usage of the HTTP protocol
-* Angular app-design fundamentals, as described in [Angular Concepts](guide/architecture)
-* Observable techniques and operators. See the [Observables](guide/observables) guide.
+* TypeScript programming
+* Usage of the HTTP protocol
+* Angular app-design fundamentals, as described in [Angular Concepts](guide/architecture)
+* Observable techniques and operators.
+ See the [Observables](guide/observables) guide.
## Setup for server communication
Before you can use `HttpClient`, you need to import the Angular `HttpClientModule`.
Most apps do so in the root `AppModule`.
-
-
+
You can then inject the `HttpClient` service as a dependency of an application class, as shown in the following `ConfigService` example.
-
-
+
-The `HttpClient` service makes use of [observables](guide/glossary#observable "Observable definition") for all transactions. You must import the RxJS observable and operator symbols that appear in the example snippets. These `ConfigService` imports are typical.
+The `HttpClient` service makes use of [observables](guide/glossary#observable "Observable definition") for all transactions.
+You must import the RxJS observable and operator symbols that appear in the example snippets.
+These `ConfigService` imports are typical.
-
-
+
You can run the that accompanies this guide.
The sample app does not require a data server.
-It relies on the
-[Angular _in-memory-web-api_](https://github.com/angular/angular/tree/master/packages/misc/angular-in-memory-web-api),
-which replaces the _HttpClient_ module's `HttpBackend`.
+It relies on the [Angular *in-memory-web-api*](https://github.com/angular/angular/tree/master/packages/misc/angular-in-memory-web-api), which replaces the *HttpClient* module's `HttpBackend`.
The replacement service simulates the behavior of a REST-like backend.
-Look at the `AppModule` _imports_ to see how it is configured.
+Look at the `AppModule` *imports* to see how it is configured.
@@ -68,21 +57,23 @@ The return type varies based on the `observe` and `responseType` values that you
The `get()` method takes two arguments; the endpoint URL from which to fetch, and an *options* object that is used to configure the request.
-```
+
+
options: {
- headers?: HttpHeaders | {[header: string]: string | string[]},
- observe?: 'body' | 'events' | 'response',
- params?: HttpParams|{[param: string]: string | number | boolean | ReadonlyArray},
- reportProgress?: boolean,
- responseType?: 'arraybuffer'|'blob'|'json'|'text',
- withCredentials?: boolean,
- }
-```
+ headers?: HttpHeaders | {[header: string]: string | string[]},
+ observe?: 'body' | 'events' | 'response',
+ params?: HttpParams|{[param: string]: string | number | boolean | ReadonlyArray<string | number | boolean>},
+ reportProgress?: boolean,
+ responseType?: 'arraybuffer'|'blob'|'json'|'text',
+ withCredentials?: boolean,
+}
+
+
Important options include the *observe* and *responseType* properties.
-* The *observe* option specifies how much of the response to return.
-* The *responseType* option specifies the format in which to return data.
+* The *observe* option specifies how much of the response to return
+* The *responseType* option specifies the format in which to return data
@@ -94,46 +85,32 @@ Use the `params` property to configure a request with [HTTP URL parameters](#url
Applications often request JSON data from a server.
-In the `ConfigService` example, the app needs a configuration file on the server, `config.json`,
-that specifies resource URLs.
+In the `ConfigService` example, the app needs a configuration file on the server, `config.json`, that specifies resource URLs.
-
-
+
To fetch this kind of data, the `get()` call needs the following options: `{observe: 'body', responseType: 'json'}`.
These are the default values for those options, so the following examples do not pass the options object.
Later sections show some of the additional option possibilities.
-{@a config-service}
+
The example conforms to the best practices for creating scalable solutions by defining a re-usable [injectable service](guide/glossary#service "service definition") to perform the data-handling functionality.
In addition to fetching data, the service can post-process the data, add error handling, and add retry logic.
The `ConfigService` fetches this file using the `HttpClient.get()` method.
-
-
+
-The `ConfigComponent` injects the `ConfigService` and calls
-the `getConfig` service method.
+The `ConfigComponent` injects the `ConfigService` and calls the `getConfig` service method.
-Because the service method returns an `Observable` of configuration data,
-the component *subscribes* to the method's return value.
+Because the service method returns an `Observable` of configuration data, the component *subscribes* to the method's return value.
The subscription callback performs minimal post-processing.
It copies the data fields into the component's `config` object, which is data-bound in the component template for display.
-
-
+
-{@a typed-response}
+
### Requesting a typed response
@@ -143,70 +120,68 @@ Specifying the response type acts as a type assertion at compile time.
Specifying the response type is a declaration to TypeScript that it should treat your response as being of the given type.
-This is a build-time check and doesn't guarantee that the server actually responds with an object of this type. It is up to the server to ensure that the type specified by the server API is returned.
+This is a build-time check and doesn't guarantee that the server actually responds with an object of this type.
+It is up to the server to ensure that the type specified by the server API is returned.
To specify the response object type, first define an interface with the required properties.
Use an interface rather than a class, because the response is a plain object that cannot be automatically converted to an instance of a class.
-
-
+
Next, specify that interface as the `HttpClient.get()` call's type parameter in the service.
-
-
+
- When you pass an interface as a type parameter to the `HttpClient.get()` method, use the [RxJS `map` operator](guide/rx-library#operators) to transform the response data as needed by the UI. You can then pass the transformed data to the [async pipe](api/common/AsyncPipe).
+When you pass an interface as a type parameter to the `HttpClient.get()` method, use the [RxJS `map` operator](guide/rx-library#operators) to transform the response data as needed by the UI.
+You can then pass the transformed data to the [async pipe](api/common/AsyncPipe).
-The callback in the updated component method receives a typed data object, which is
-easier and safer to consume:
+The callback in the updated component method receives a typed data object, which is easier and safer to consume:
-
-
+
To access properties that are defined in an interface, you must explicitly convert the plain object you get from the JSON to the required response type.
For example, the following `subscribe` callback receives `data` as an Object, and then type-casts it in order to access the properties.
-
- .subscribe(data => this.config = {
- heroesUrl: (data as any).heroesUrl,
- textfile: (data as any).textfile,
- });
+
+
+.subscribe(data => this.config = {
+ heroesUrl: (data as any).heroesUrl,
+ textfile: (data as any).textfile,
+});
+
-{@a string-union-types}
+
-*observe* and *response* types
+
+observe
and response
types
The types of the `observe` and `response` options are *string unions*, rather than plain strings.
-```
+
+
options: {
- ...
- observe?: 'body' | 'events' | 'response',
- ...
- responseType?: 'arraybuffer'|'blob'|'json'|'text',
- ...
- }
-```
-This can cause confusion. For example:
-
-```typescript
+ …
+ observe?: 'body' | 'events' | 'response',
+ …
+ responseType?: 'arraybuffer'|'blob'|'json'|'text',
+ …
+}
+
+
+
+This can cause confusion.
+For example:
+
+
+
// this works
client.get('/foo', {responseType: 'text'})
@@ -215,52 +190,49 @@ const options = {
responseType: 'text',
};
client.get('/foo', options)
-```
+
+
In the second case, TypeScript infers the type of `options` to be `{responseType: string}`.
-The type is too wide to pass to `HttpClient.get` which is expecting the type of `responseType` to be one of the _specific_ strings.
+The type is too wide to pass to `HttpClient.get` which is expecting the type of `responseType` to be one of the *specific* strings.
`HttpClient` is typed explicitly this way so that the compiler can report the correct return type based on the options you provided.
Use `as const` to let TypeScript know that you really do mean to use a constant string type:
-```typescript
+
+
const options = {
responseType: 'text' as const,
};
client.get('/foo', options);
-```
+
+
### Reading the full response
-In the previous example, the call to `HttpClient.get()` did not specify any options. By default, it returned the JSON data contained in the response body.
+In the previous example, the call to `HttpClient.get()` did not specify any options.
+By default, it returned the JSON data contained in the response body.
-You might need more information about the transaction than is contained in the response body. Sometimes servers return special headers or status codes to indicate certain conditions that are important to the application workflow.
+You might need more information about the transaction than is contained in the response body.
+Sometimes servers return special headers or status codes to indicate certain conditions that are important to the application workflow.
Tell `HttpClient` that you want the full response with the `observe` option of the `get()` method:
-
-
+
Now `HttpClient.get()` returns an `Observable` of type `HttpResponse` rather than just the JSON data contained in the body.
The component's `showConfigResponse()` method displays the response headers as well as the configuration:
-
-
+
As you can see, the response object has a `body` property of the correct type.
### Making a JSONP request
-Apps can use the `HttpClient` to make [JSONP](https://en.wikipedia.org/wiki/JSONP) requests across domains when a server doesn't support [CORS protocol](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS).
+Apps can use the `HttpClient` to make [JSONP](https://en.wikipedia.org/wiki/JSONP) requests across domains when a server doesn't support [CORS protocol](https://developer.mozilla.org/docs/Web/HTTP/CORS).
Angular JSONP requests return an `Observable`.
Follow the pattern for subscribing to observables and use the RxJS `map` operator to transform the response before using the [async pipe](api/common/AsyncPipe) to manage the results.
@@ -268,17 +240,19 @@ Follow the pattern for subscribing to observables and use the RxJS `map` operato
In Angular, use JSONP by including `HttpClientJsonpModule` in the `NgModule` imports.
In the following example, the `searchHeroes()` method uses a JSONP request to query for heroes whose names contain the search term.
-```ts
+
+
/* GET heroes whose name contains search term */
searchHeroes(term: string): Observable {
term = term.trim();
- const heroesURL = `${this.heroesURL}?${term}`;
+ const heroesURL = `${this.heroesURL}?${term}`;
return this.http.jsonp(heroesUrl, 'callback').pipe(
catchError(this.handleError('searchHeroes', [])) // then handle the error
);
}
-```
+
+
This request passes the `heroesURL` as the first parameter and the callback function name as the second parameter.
The response is wrapped in the callback function, which takes the observables returned by the JSONP method and pipes them through to the error handler.
@@ -288,35 +262,29 @@ The response is wrapped in the callback function, which takes the observables re
Not all APIs return JSON data.
In this next example, a `DownloaderService` method reads a text file from the server and logs the file contents, before returning those contents to the caller as an `Observable`.
-
-
+
`HttpClient.get()` returns a string rather than the default JSON because of the `responseType` option.
-The RxJS `tap` operator (as in "wiretap") lets the code inspect both success and error values passing through the observable without disturbing them.
+The RxJS `tap` operator \(as in "wiretap"\) lets the code inspect both success and error values passing through the observable without disturbing them.
A `download()` method in the `DownloaderComponent` initiates the request by subscribing to the service method.
-
-
+
-{@a error-handling}
+
## Handling request errors
-If the request fails on the server, `HttpClient` returns an _error_ object instead of a successful response.
+If the request fails on the server, `HttpClient` returns an *error* object instead of a successful response.
The same service that performs your server transactions should also perform error inspection, interpretation, and resolution.
-When an error occurs, you can obtain details of what failed in order to inform your user. In some cases, you might also automatically [retry the request](#retry).
+When an error occurs, you can obtain details of what failed in order to inform your user.
+In some cases, you might also automatically [retry the request](#retry).
+
+
-{@a error-details}
### Getting error details
An app should give the user useful feedback when data access fails.
@@ -325,54 +293,44 @@ In addition to detecting that an error has occurred, you need to get error detai
Two types of errors can occur.
-* The server backend might reject the request, returning an HTTP response with a status code such as 404 or 500. These are error _responses_.
+* The server backend might reject the request, returning an HTTP response with a status code such as 404 or 500.
+ These are error *responses*.
-* Something could go wrong on the client-side such as a network error that prevents the request from completing successfully or an exception thrown in an RxJS operator. These errors have `status` set to `0` and the `error` property contains a `ProgressEvent` object, whose `type` might provide further information.
+* Something could go wrong on the client-side such as a network error that prevents the request from completing successfully or an exception thrown in an RxJS operator.
+ These errors have `status` set to `0` and the `error` property contains a `ProgressEvent` object, whose `type` might provide further information.
-`HttpClient` captures both kinds of errors in its `HttpErrorResponse`. Inspect that response to identify the error's cause.
+`HttpClient` captures both kinds of errors in its `HttpErrorResponse`.
+Inspect that response to identify the error's cause.
The following example defines an error handler in the previously defined [ConfigService](#config-service "ConfigService defined").
-
-
+
The handler returns an RxJS `ErrorObservable` with a user-friendly error message.
The following code updates the `getConfig()` method, using a [pipe](guide/pipes "Pipes guide") to send all observables returned by the `HttpClient.get()` call to the error handler.
-
-
+
+
+
-{@a retry}
### Retrying a failed request
Sometimes the error is transient and goes away automatically if you try again.
-For example, network interruptions are common in mobile scenarios, and trying again
-can produce a successful result.
+For example, network interruptions are common in mobile scenarios, and trying again can produce a successful result.
-The [RxJS library](guide/rx-library) offers several _retry_ operators.
-For example, the `retry()` operator automatically re-subscribes to a failed `Observable` a specified number of times. _Re-subscribing_ to the result of an `HttpClient` method call has the effect of reissuing the HTTP request.
+The [RxJS library](guide/rx-library) offers several *retry* operators.
+For example, the `retry()` operator automatically re-subscribes to a failed `Observable` a specified number of times.
+*Re-subscribing* to the result of an `HttpClient` method call has the effect of reissuing the HTTP request.
The following example shows how to pipe a failed request to the `retry()` operator before passing it to the error handler.
-
-
-
+
## Sending data to a server
In addition to fetching data from a server, `HttpClient` supports other HTTP methods such as PUT, POST, and DELETE, which you can use to modify the remote data.
-The sample app for this guide includes an abridged version of the "Tour of Heroes" example
-that fetches heroes and enables users to add, delete, and update them.
+The sample app for this guide includes an abridged version of the "Tour of Heroes" example that fetches heroes and enables users to add, delete, and update them.
The following sections show examples of the data-update methods from the sample's `HeroesService`.
### Making a POST request
@@ -380,98 +338,83 @@ The following sections show examples of the data-update methods from the sample'
Apps often send data to a server with a POST request when submitting a form.
In the following example, the `HeroesService` makes an HTTP POST request when adding a hero to the database.
-
-
+
-The `HttpClient.post()` method is similar to `get()` in that it has a type parameter, which you can use to specify that you expect the server to return data of a given type. The method takes a resource URL and two additional parameters:
+The `HttpClient.post()` method is similar to `get()` in that it has a type parameter, which you can use to specify that you expect the server to return data of a given type.
+The method takes a resource URL and two additional parameters:
-* *body* - The data to POST in the body of the request.
-* *options* - An object containing method options which, in this case, [specify required headers](#adding-headers).
+| Parameter | Details |
+|:--- |:--- |
+| body | The data to POST in the body of the request. |
+| options | An object containing method options which, in this case, [specify required headers](#adding-headers). |
The example catches errors as [described above](#error-details).
-The `HeroesComponent` initiates the actual POST operation by subscribing to
-the `Observable` returned by this service method.
+The `HeroesComponent` initiates the actual POST operation by subscribing to the `Observable` returned by this service method.
-
-
+
-When the server responds successfully with the newly added hero, the component adds
-that hero to the displayed `heroes` list.
+When the server responds successfully with the newly added hero, the component adds that hero to the displayed `heroes` list.
### Making a DELETE request
-This application deletes a hero with the `HttpClient.delete` method by passing the hero's ID
-in the request URL.
+This application deletes a hero with the `HttpClient.delete` method by passing the hero's ID in the request URL.
-
-
+
-The `HeroesComponent` initiates the actual DELETE operation by subscribing to
-the `Observable` returned by this service method.
+The `HeroesComponent` initiates the actual DELETE operation by subscribing to the `Observable` returned by this service method.
-
-
+
-The component isn't expecting a result from the delete operation, so it subscribes without a callback. Even though you are not using the result, you still have to subscribe. Calling the `subscribe()` method _executes_ the observable, which is what initiates the DELETE request.
+The component isn't expecting a result from the delete operation, so it subscribes without a callback.
+Even though you are not using the result, you still have to subscribe.
+Calling the `subscribe()` method *executes* the observable, which is what initiates the DELETE request.
-You must call _subscribe()_ or nothing happens. Just calling `HeroesService.deleteHero()` does not initiate the DELETE request.
+You must call `subscribe()` or nothing happens.
+Just calling `HeroesService.deleteHero()` does not initiate the DELETE request.
+
-
-
+
-{@a always-subscribe}
-**Always _subscribe_!**
+**Always *subscribe*.**
-An `HttpClient` method does not begin its HTTP request until you call `subscribe()` on the observable returned by that method. This is true for _all_ `HttpClient` _methods_.
+An `HttpClient` method does not begin its HTTP request until you call `subscribe()` on the observable returned by that method.
+This is true for *all* `HttpClient` *methods*.
-The [`AsyncPipe`](api/common/AsyncPipe) subscribes (and unsubscribes) for you automatically.
+The [`AsyncPipe`](api/common/AsyncPipe) subscribes \(and unsubscribes\) for you automatically.
-All observables returned from `HttpClient` methods are _cold_ by design.
-Execution of the HTTP request is _deferred_, letting you extend the
-observable with additional operations such as `tap` and `catchError` before anything actually happens.
+All observables returned from `HttpClient` methods are *cold* by design.
+Execution of the HTTP request is *deferred*, letting you extend the observable with additional operations such as `tap` and `catchError` before anything actually happens.
-Calling `subscribe(...)` triggers execution of the observable and causes
-`HttpClient` to compose and send the HTTP request to the server.
+Calling `subscribe(…)` triggers execution of the observable and causes `HttpClient` to compose and send the HTTP request to the server.
-Think of these observables as _blueprints_ for actual HTTP requests.
+Think of these observables as *blueprints* for actual HTTP requests.
In fact, each `subscribe()` initiates a separate, independent execution of the observable.
Subscribing twice results in two HTTP requests.
-```javascript
-const req = http.get('/api/heroes');
+
+
+const req = http.get<Heroes>('/api/heroes');
// 0 requests made - .subscribe() not called.
req.subscribe();
// 1 request made.
req.subscribe();
// 2 requests made.
-```
+
+
+
### Making a PUT request
@@ -479,11 +422,7 @@ req.subscribe();
An app can send PUT requests using the HTTP client service.
The following `HeroesService` example, like the POST example, replaces a resource with updated data.
-
-
+
As for any of the HTTP methods that return an observable, the caller, `HeroesComponent.update()` [must `subscribe()`](#always-subscribe "Why you must always subscribe.") to the observable returned from the `HttpClient.put()` in order to initiate the request.
@@ -494,14 +433,9 @@ For example, a server might require an authorization token, or "Content-Type" he
##### Adding headers
-The `HeroesService` defines such headers in an `httpOptions` object that are passed
-to every `HttpClient` save method.
+The `HeroesService` defines such headers in an `httpOptions` object that are passed to every `HttpClient` save method.
-
-
+
##### Updating headers
@@ -511,12 +445,9 @@ Use the `set()` method instead, to return a clone of the current instance with t
The following example shows how, when an old token expires, you can update the authorization header before making the next request.
-
-
+
-{@a url-params}
+
## Configuring HTTP URL parameters
@@ -527,72 +458,72 @@ The following example, the `searchHeroes()` method queries for heroes whose name
Start by importing `HttpParams` class.
-import {HttpParams} from "@angular/common/http";
-
-
+import {HttpParams} from "@angular/common/http";
+
+
+
If there is a search term, the code constructs an options object with an HTML URL-encoded search parameter.
If the term is "cat", for example, the GET request URL would be `api/heroes?name=cat`.
-The `HttpParams` object is immutable. If you need to update the options, save the returned value of the `.set()` method.
+The `HttpParams` object is immutable.
+If you need to update the options, save the returned value of the `.set()` method.
You can also create HTTP parameters directly from a query string by using the `fromString` variable:
+
const params = new HttpParams({fromString: 'name=foo'});
+
+
-{@a intercepting-requests-and-responses}
## Intercepting requests and responses
-With interception, you declare _interceptors_ that inspect and transform HTTP requests from your application to a server.
+With interception, you declare *interceptors* that inspect and transform HTTP requests from your application to a server.
The same interceptors can also inspect and transform a server's responses on their way back to the application.
-Multiple interceptors form a _forward-and-backward_ chain of request/response handlers.
+Multiple interceptors form a *forward-and-backward* chain of request/response handlers.
-Interceptors can perform a variety of _implicit_ tasks, from authentication to logging, in a routine, standard way, for every HTTP request/response.
+Interceptors can perform a variety of *implicit* tasks, from authentication to logging, in a routine, standard way, for every HTTP request/response.
-Without interception, developers would have to implement these tasks _explicitly_
-for each `HttpClient` method call.
+Without interception, developers would have to implement these tasks *explicitly* for each `HttpClient` method call.
### Write an interceptor
To implement an interceptor, declare a class that implements the `intercept()` method of the `HttpInterceptor` interface.
-Here is a do-nothing _noop_ interceptor that passes the request through without touching it:
+Here is a do-nothing `noop` interceptor that passes the request through without touching it:
-
-
+
The `intercept` method transforms a request into an `Observable` that eventually returns the HTTP response.
In this sense, each interceptor is fully capable of handling the request entirely by itself.
-Most interceptors inspect the request on the way in and forward the (perhaps altered) request to the `handle()` method of the `next` object which implements the [`HttpHandler`](api/common/http/HttpHandler) interface.
+Most interceptors inspect the request on the way in and forward the \(perhaps altered\) request to the `handle()` method of the `next` object which implements the [`HttpHandler`](api/common/http/HttpHandler) interface.
+
+
-```javascript
export abstract class HttpHandler {
- abstract handle(req: HttpRequest): Observable>;
+ abstract handle(req: HttpRequest<any>): Observable<HttpEvent<any>>;
}
-```
-Like `intercept()`, the `handle()` method transforms an HTTP request into an `Observable` of [`HttpEvents`](#interceptor-events) which ultimately include the server's response. The `intercept()` method could inspect that observable and alter it before returning it to the caller.
+
+
+Like `intercept()`, the `handle()` method transforms an HTTP request into an `Observable` of [`HttpEvents`](#interceptor-events) which ultimately include the server's response.
+The `intercept()` method could inspect that observable and alter it before returning it to the caller.
-This _no-op_ interceptor calls `next.handle()` with the original request and returns the observable without doing a thing.
+This `no-op` interceptor calls `next.handle()` with the original request and returns the observable without doing a thing.
-### The _next_ object
+### The `next` object
The `next` object represents the next interceptor in the chain of interceptors.
The final `next` in the chain is the `HttpClient` backend handler that sends the request to the server and receives the server's response.
-
Most interceptors call `next.handle()` so that the request flows through to the next interceptor and, eventually, the backend handler.
-An interceptor _could_ skip calling `next.handle()`, short-circuit the chain, and [return its own `Observable`](#caching) with an artificial server response.
+An interceptor *could* skip calling `next.handle()`, short-circuit the chain, and [return its own `Observable`](#caching) with an artificial server response.
This is a common middleware pattern found in frameworks such as Express.js.
@@ -601,49 +532,32 @@ This is a common middleware pattern found in frameworks such as Express.js.
The `NoopInterceptor` is a service managed by Angular's [dependency injection (DI)](guide/dependency-injection) system.
Like other services, you must provide the interceptor class before the app can use it.
-Because interceptors are (optional) dependencies of the `HttpClient` service,
-you must provide them in the same injector (or a parent of the injector) that provides `HttpClient`.
-Interceptors provided _after_ DI creates the `HttpClient` are ignored.
+Because interceptors are \(optional\) dependencies of the `HttpClient` service, you must provide them in the same injector \(or a parent of the injector\) that provides `HttpClient`.
+Interceptors provided *after* DI creates the `HttpClient` are ignored.
This app provides `HttpClient` in the app's root injector, as a side-effect of importing the `HttpClientModule` in `AppModule`.
You should provide interceptors in `AppModule` as well.
-After importing the `HTTP_INTERCEPTORS` injection token from `@angular/common/http`,
-write the `NoopInterceptor` provider like this:
+After importing the `HTTP_INTERCEPTORS` injection token from `@angular/common/http`, write the `NoopInterceptor` provider like this:
-
-
+
-Note the `multi: true` option.
-This required setting tells Angular that `HTTP_INTERCEPTORS` is a token for a _multiprovider_
-that injects an array of values, rather than a single value.
+Notice the `multi: true` option.
+This required setting tells Angular that `HTTP_INTERCEPTORS` is a token for a *multiprovider* that injects an array of values, rather than a single value.
-You _could_ add this provider directly to the providers array of the `AppModule`.
-However, it's rather verbose and there's a good chance that
-you'll create more interceptors and provide them in the same way.
-You must also pay [close attention to the order](#interceptor-order)
-in which you provide these interceptors.
+You *could* add this provider directly to the providers array of the `AppModule`.
+However, it's rather verbose and there's a good chance that you'll create more interceptors and provide them in the same way.
+You must also pay [close attention to the order](#interceptor-order) in which you provide these interceptors.
Consider creating a "barrel" file that gathers all the interceptor providers into an `httpInterceptorProviders` array, starting with this first one, the `NoopInterceptor`.
-
-
+
-Then import and add it to the `AppModule` _providers array_ like this:
+Then import and add it to the `AppModule` `providers array` like this:
-
-
+
-As you create new interceptors, add them to the `httpInterceptorProviders` array and
-you won't have to revisit the `AppModule`.
+As you create new interceptors, add them to the `httpInterceptorProviders` array and you won't have to revisit the `AppModule`.
@@ -654,25 +568,28 @@ There are many more interceptors in the complete sample code.
### Interceptor order
Angular applies interceptors in the order that you provide them.
-For example, consider a situation in which you want to handle the authentication of your HTTP requests and log them before sending them to a server. To accomplish this task, you could provide an `AuthInterceptor` service and then a `LoggingInterceptor` service.
+For example, consider a situation in which you want to handle the authentication of your HTTP requests and log them before sending them to a server.
+To accomplish this task, you could provide an `AuthInterceptor` service and then a `LoggingInterceptor` service.
Outgoing requests would flow from the `AuthInterceptor` to the `LoggingInterceptor`.
Responses from these requests would flow in the other direction, from `LoggingInterceptor` back to `AuthInterceptor`.
The following is a visual representation of the process:
-
+
+
+
- The last interceptor in the process is always the `HttpBackend` that handles communication with the server.
+The last interceptor in the process is always the `HttpBackend` that handles communication with the server.
You cannot change the order or remove interceptors later.
If you need to enable and disable an interceptor dynamically, you'll have to build that capability into the interceptor itself.
-{@a interceptor-events}
+
### Handling interceptor events
@@ -684,58 +601,53 @@ The methods `HttpInterceptor.intercept()` and `HttpHandler.handle()` return obse
Many interceptors are only concerned with the outgoing request and return the event stream from `next.handle()` without modifying it.
Some interceptors, however, need to examine and modify the response from `next.handle()`; these operations can see all of these events in the stream.
-{@a immutability}
+
-Although interceptors are capable of modifying requests and responses,
-the `HttpRequest` and `HttpResponse` instance properties are `readonly`,
-rendering them largely immutable.
-They are immutable for a good reason: an app might retry a request several times before it succeeds, which means that the interceptor chain can re-process the same request multiple times.
-If an interceptor could modify the original request object, the re-tried operation would start from the modified request rather than the original. Immutability ensures that interceptors see the same request for each try.
+Although interceptors are capable of modifying requests and responses, the `HttpRequest` and `HttpResponse` instance properties are `readonly`, rendering them largely immutable.
+They are immutable for a good reason:
+An app might retry a request several times before it succeeds, which means that the interceptor chain can re-process the same request multiple times.
+If an interceptor could modify the original request object, the re-tried operation would start from the modified request rather than the original.
+Immutability ensures that interceptors see the same request for each try.
- Your interceptor should return every event without modification unless it has a compelling reason to do otherwise.
+Your interceptor should return every event without modification unless it has a compelling reason to do otherwise.
TypeScript prevents you from setting `HttpRequest` read-only properties.
-```javascript
- // Typescript disallows the following assignment because req.url is readonly
- req.url = req.url.replace('http://', 'https://');
-```
+
+
+// Typescript disallows the following assignment because req.url is readonly
+req.url = req.url.replace('http://', 'https://');
+
+
If you must alter a request, clone it first and modify the clone before passing it to `next.handle()`.
You can clone and modify the request in a single step, as shown in the following example.
-
-
+
The `clone()` method's hash argument lets you mutate specific properties of the request while copying the others.
#### Modifying a request body
-The `readonly` assignment guard can't prevent deep updates and, in particular,
-it can't prevent you from modifying a property of a request body object.
+The `readonly` assignment guard can't prevent deep updates and, in particular, it can't prevent you from modifying a property of a request body object.
+
+
-```javascript
- req.body.name = req.body.name.trim(); // bad idea!
-```
+req.body.name = req.body.name.trim(); // bad idea!
+
+
If you must modify the request body, follow these steps.
-1. Copy the body and make your change in the copy.
-2. Clone the request object, using its `clone()` method.
-3. Replace the clone's body with the modified copy.
+1. Copy the body and make your change in the copy.
+1. Clone the request object, using its `clone()` method.
+1. Replace the clone's body with the modified copy.
-
-
+
#### Clearing the request body in a clone
@@ -744,15 +656,18 @@ To do this, set the cloned request body to `null`.
-**Tip**: If you set the cloned request body to `undefined`, Angular assumes you intend to leave the body as is.
+**TIP**:
+If you set the cloned request body to `undefined`, Angular assumes you intend to leave the body as is.
-```javascript
- newReq = req.clone({ ... }); // body not mentioned => preserve original body
- newReq = req.clone({ body: undefined }); // preserve original body
- newReq = req.clone({ body: null }); // clear the body
-```
+
+
+newReq = req.clone({ … }); // body not mentioned => preserve original body
+newReq = req.clone({ body: undefined }); // preserve original body
+newReq = req.clone({ body: null }); // clear the body
+
+
## Http interceptor use-cases
@@ -763,83 +678,58 @@ Following are a number of common uses for interceptors.
Apps often use an interceptor to set default headers on outgoing requests.
The sample app has an `AuthService` that produces an authorization token.
-Here is its `AuthInterceptor` that injects that service to get the token and
-adds an authorization header with that token to every outgoing request:
+Here is its `AuthInterceptor` that injects that service to get the token and adds an authorization header with that token to every outgoing request:
-
-
+
-The practice of cloning a request to set new headers is so common that
-there's a `setHeaders` shortcut for it:
+The practice of cloning a request to set new headers is so common that there's a `setHeaders` shortcut for it:
-
-
+
An interceptor that alters headers can be used for a number of different operations, including:
-* Authentication/authorization
-* Caching behavior; for example, `If-Modified-Since`
-* XSRF protection
+* Authentication/authorization
+* Caching behavior; for example, `If-Modified-Since`
+* XSRF protection
### Logging request and response pairs
-Because interceptors can process the request and response _together_, they can perform tasks such as timing and logging an entire HTTP operation.
+Because interceptors can process the request and response *together*, they can perform tasks such as timing and logging an entire HTTP operation.
Consider the following `LoggingInterceptor`, which captures the time of the request,
the time of the response, and logs the outcome with the elapsed time
with the injected `MessageService`.
-
-
+
The RxJS `tap` operator captures whether the request succeeded or failed.
-The RxJS `finalize` operator is called when the response observable either errors or completes (which it must),
-and reports the outcome to the `MessageService`.
+The RxJS `finalize` operator is called when the response observable either errors or completes \(which it must\), and reports the outcome to the `MessageService`.
Neither `tap` nor `finalize` touch the values of the observable stream returned to the caller.
-{@a custom-json-parser}
+
### Custom JSON parsing
Interceptors can be used to replace the built-in JSON parsing with a custom implementation.
The `CustomJsonInterceptor` in the following example demonstrates how to achieve this.
-If the intercepted request expects a `'json'` response, the `responseType` is changed to `'text'`
-to disable the built-in JSON parsing. Then the response is parsed via the injected `JsonParser`.
+If the intercepted request expects a `'json'` response, the `responseType` is changed to `'text'` to disable the built-in JSON parsing.
+Then the response is parsed via the injected `JsonParser`.
-
-
+
You can then implement your own custom `JsonParser`.
Here is a custom JsonParser that has a special date reviver.
-
-
+
You provide the `CustomParser` along with the `CustomJsonInterceptor`.
-
-
+
+
-{@a caching}
### Caching requests
Interceptors can handle requests by themselves, without forwarding to `next.handle()`.
@@ -849,79 +739,57 @@ You can delegate caching to an interceptor without disturbing your existing data
The `CachingInterceptor` in the following example demonstrates this approach.
-
-
+
-* The `isCacheable()` function determines if the request is cacheable.
-In this sample, only GET requests to the package search API are cacheable.
+* The `isCacheable()` function determines if the request is cacheable.
+ In this sample, only GET requests to the package search API are cacheable.
-* If the request is not cacheable, the interceptor forwards the request
-to the next handler in the chain.
+* If the request is not cacheable, the interceptor forwards the request to the next handler in the chain
+* If a cacheable request is found in the cache, the interceptor returns an `of()` *observable* with the cached response, by-passing the `next` handler \(and all other interceptors downstream\)
+* If a cacheable request is not in cache, the code calls `sendRequest()`.
+ This function forwards the request to `next.handle()` which ultimately calls the server and returns the server's response.
-* If a cacheable request is found in the cache, the interceptor returns an `of()` _observable_ with
-the cached response, by-passing the `next` handler (and all other interceptors downstream).
+
-* If a cacheable request is not in cache, the code calls `sendRequest()`.
-This function forwards the request to `next.handle()` which ultimately calls the server and returns the server's response.
+
-{@a send-request}
-
-
+
-Note how `sendRequest()` intercepts the response on its way back to the application.
+Notice how `sendRequest()` intercepts the response on its way back to the application.
This method pipes the response through the `tap()` operator, whose callback adds the response to the cache.
-The original response continues untouched back up through the chain of interceptors
-to the application caller.
+The original response continues untouched back up through the chain of interceptors to the application caller.
-Data services, such as `PackageSearchService`, are unaware that
-some of their `HttpClient` requests actually return cached responses.
+Data services, such as `PackageSearchService`, are unaware that some of their `HttpClient` requests actually return cached responses.
+
+
-{@a cache-refresh}
### Using interceptors to request multiple values
The `HttpClient.get()` method normally returns an observable that emits a single value, either the data or an error.
An interceptor can change this to an observable that emits [multiple values](guide/observables).
-The following revised version of the `CachingInterceptor` optionally returns an observable that
-immediately emits the cached response, sends the request on to the package search API,
-and emits again later with the updated search results.
+The following revised version of the `CachingInterceptor` optionally returns an observable that immediately emits the cached response, sends the request on to the package search API, and emits again later with the updated search results.
-
-
+
-The _cache-then-refresh_ option is triggered by the presence of a custom `x-refresh` header.
+The *cache-then-refresh* option is triggered by the presence of a custom `x-refresh` header.
-A checkbox on the `PackageSearchComponent` toggles a `withRefresh` flag,
-which is one of the arguments to `PackageSearchService.search()`.
-That `search()` method creates the custom `x-refresh` header
-and adds it to the request before calling `HttpClient.get()`.
+A checkbox on the `PackageSearchComponent` toggles a `withRefresh` flag, which is one of the arguments to `PackageSearchService.search()`.
+That `search()` method creates the custom `x-refresh` header and adds it to the request before calling `HttpClient.get()`.
-The revised `CachingInterceptor` sets up a server request
-whether there's a cached value or not,
-using the same `sendRequest()` method described [above](#send-request).
+The revised `CachingInterceptor` sets up a server request whether there's a cached value or not, using the same `sendRequest()` method described [above](#send-request).
The `results$` observable makes the request when subscribed.
-* If there's no cached value, the interceptor returns `results$`.
+* If there's no cached value, the interceptor returns `results$`.
+* If there is a cached value, the code *pipes* the cached response onto `results$`, producing a recomposed observable that emits twice, the cached response first \(and immediately\), followed later by the response from the server.
+ Subscribers see a sequence of two responses.
-* If there is a cached value, the code _pipes_ the cached response onto
-`results$`, producing a recomposed observable that emits twice,
-the cached response first (and immediately), followed later
-by the response from the server.
-Subscribers see a sequence of two responses.
-
-{@a report-progress}
+
## Tracking and showing request progress
@@ -929,47 +797,31 @@ Sometimes applications transfer large amounts of data and those transfers can ta
File uploads are a typical example.
You can give the users a better experience by providing feedback on the progress of such transfers.
-To make a request with progress events enabled, create an instance of `HttpRequest`
-with the `reportProgress` option set true to enable tracking of progress events.
+To make a request with progress events enabled, create an instance of `HttpRequest` with the `reportProgress` option set true to enable tracking of progress events.
-
-
+
-**Tip**: Every progress event triggers change detection, so only turn them on if you need to report progress in the UI.
+**TIP**:
+Every progress event triggers change detection, so only turn them on if you need to report progress in the UI.
-When using [`HttpClient.request()`](api/common/http/HttpClient#request) with an HTTP method, configure the method with
-[`observe: 'events'`](api/common/http/HttpClient#request) to see all events, including the progress of transfers.
+When using [`HttpClient.request()`](api/common/http/HttpClient#request) with an HTTP method, configure the method with [`observe: 'events'`](api/common/http/HttpClient#request) to see all events, including the progress of transfers.
-Next, pass this request object to the `HttpClient.request()` method, which
-returns an `Observable` of `HttpEvents` (the same events processed by [interceptors](#interceptor-events)).
+Next, pass this request object to the `HttpClient.request()` method, which returns an `Observable` of `HttpEvents` \(the same events processed by [interceptors](#interceptor-events)\).
-
-
+
The `getEventMessage` method interprets each type of `HttpEvent` in the event stream.
-
-
+
The sample app for this guide doesn't have a server that accepts uploaded files.
-The `UploadInterceptor` in `app/http-interceptors/upload-interceptor.ts`
-intercepts and short-circuits upload requests
-by returning an observable of simulated events.
+The `UploadInterceptor` in `app/http-interceptors/upload-interceptor.ts` intercepts and short-circuits upload requests by returning an observable of simulated events.
@@ -980,14 +832,9 @@ It's better to wait until the user stops typing and then send a request.
This technique is known as debouncing.
Consider the following template, which lets a user enter a search term to find a package by name.
-When the user enters a name in a search-box, the `PackageSearchComponent` sends
-a search request for a package with that name to the package search API.
+When the user enters a name in a search-box, the `PackageSearchComponent` sends a search request for a package with that name to the package search API.
-
-
+
Here, the `keyup` event binding sends every keystroke to the component's `search()` method.
@@ -1002,29 +849,21 @@ In the `getValue()` method, the target is cast to an `HTMLInputElement` to let t
The following snippet implements debouncing for this input using RxJS operators.
-
-
+
The `searchText$` is the sequence of search-box values coming from the user.
-It's defined as an RxJS `Subject`, which means it is a multicasting `Observable`
-that can also emit values for itself by calling `next(value)`,
-as happens in the `search()` method.
+It's defined as an RxJS `Subject`, which means it is a multicasting `Observable` that can also emit values for itself by calling `next(value)`, as happens in the `search()` method.
-Rather than forward every `searchText` value directly to the injected `PackageSearchService`,
-the code in `ngOnInit()` pipes search values through three operators, so that a search value reaches the service only if it's a new value and the user stopped typing.
+Rather than forward every `searchText` value directly to the injected `PackageSearchService`, the code in `ngOnInit()` pipes search values through three operators, so that a search value reaches the service only if it's a new value and the user stopped typing.
-* `debounceTime(500)`—Wait for the user to stop typing (1/2 second in this case).
-
-* `distinctUntilChanged()`—Wait until the search text changes.
-
-* `switchMap()`—Send the search request to the service.
+| RxJS operators | Details |
+|:--- |:--- |
+| `debounceTime(500)` | Wait for the user to stop typing \(1/2 second in this case\). |
+| `distinctUntilChanged()` | Wait until the search text changes. |
+| `switchMap()` | Send the search request to the service. |
The code sets `packages$` to this re-composed `Observable` of search results.
-The template subscribes to `packages$` with the [AsyncPipe](api/common/AsyncPipe)
-and displays search results as they arrive.
+The template subscribes to `packages$` with the [AsyncPipe](api/common/AsyncPipe) and displays search results as they arrive.
@@ -1032,25 +871,25 @@ See [Using interceptors to request multiple values](#cache-refresh) for more abo
-### Using the *switchMap()* operator
+### Using the `switchMap()` operator
The `switchMap()` operator takes a function argument that returns an `Observable`.
In the example, `PackageSearchService.search` returns an `Observable`, as other data service methods do.
-If a previous search request is still in-flight (as when the network connection is poor),
-the operator cancels that request and sends a new one.
+If a previous search request is still in-flight \(as when the network connection is poor\), the operator cancels that request and sends a new one.
-Note that `switchMap()` returns service responses in their original request order, even if the
-server returns them out of order.
+
+**NOTE**:
+`switchMap()` returns service responses in their original request order, even if the server returns them out of order.
+
+
-If you think you'll reuse this debouncing logic,
-consider moving it to a utility function or into the `PackageSearchService` itself.
+If you think you'll reuse this debouncing logic, consider moving it to a utility function or into the `PackageSearchService` itself.
-
## Security: XSRF protection
[Cross-Site Request Forgery (XSRF or CSRF)](https://en.wikipedia.org/wiki/Cross-site_request_forgery) is an attack technique by which the attacker can trick an authenticated user into unknowingly executing actions on your website.
@@ -1058,7 +897,7 @@ consider moving it to a utility function or into the `PackageSearchService` itse
When performing HTTP requests, an interceptor reads a token from a cookie, by default `XSRF-TOKEN`, and sets it as an HTTP header, `X-XSRF-TOKEN`.
Because only code that runs on your domain could read the cookie, the backend can be certain that the HTTP request came from your client application and not an attacker.
-By default, an interceptor sends this header on all mutating requests (such as POST)
+By default, an interceptor sends this header on all mutating requests \(such as POST\)
to relative URLs, but not on GET/HEAD requests or on requests with an absolute URL.
To take advantage of this, your server needs to set a token in a JavaScript readable session cookie called `XSRF-TOKEN` on either the page load or the first GET request.
@@ -1071,113 +910,78 @@ To prevent collisions in environments where multiple Angular apps share the same
*`HttpClient` supports only the client half of the XSRF protection scheme.*
-Your backend service must be configured to set the cookie for your page, and to verify that
-the header is present on all eligible requests.
+Your backend service must be configured to set the cookie for your page, and to verify that the header is present on all eligible requests.
Failing to do so renders Angular's default protection ineffective.
### Configuring custom cookie/header names
-If your backend service uses different names for the XSRF token cookie or header,
-use `HttpClientXsrfModule.withOptions()` to override the defaults.
+If your backend service uses different names for the XSRF token cookie or header, use `HttpClientXsrfModule.withOptions()` to override the defaults.
-
-
+
+
+
-{@a testing-requests}
## Testing HTTP requests
As for any external dependency, you must mock the HTTP backend so your tests can simulate interaction with a remote server.
The `@angular/common/http/testing` library makes it straightforward to set up such mocking.
Angular's HTTP testing library is designed for a pattern of testing in which the app executes code and makes requests first.
-The test then expects that certain requests have or have not been made,
-performs assertions against those requests,
-and finally provides responses by "flushing" each expected request.
+The test then expects that certain requests have or have not been made, performs assertions against those requests, and finally provides responses by "flushing" each expected request.
At the end, tests can verify that the app made no unexpected requests.
-You can run these sample tests
-in a live coding environment.
+You can run these sample tests in a live coding environment.
The tests described in this guide are in `src/testing/http-client.spec.ts`.
-There are also tests of an application data service that call `HttpClient` in
-`src/app/heroes/heroes.service.spec.ts`.
+There are also tests of an application data service that call `HttpClient` in `src/app/heroes/heroes.service.spec.ts`.
### Setup for testing
-To begin testing calls to `HttpClient`,
-import the `HttpClientTestingModule` and the mocking controller, `HttpTestingController`,
-along with the other symbols your tests require.
+To begin testing calls to `HttpClient`, import the `HttpClientTestingModule` and the mocking controller, `HttpTestingController`, along with the other symbols your tests require.
-
-
+
-Then add the `HttpClientTestingModule` to the `TestBed` and continue with
-the setup of the _service-under-test_.
+Then add the `HttpClientTestingModule` to the `TestBed` and continue with the setup of the *service-under-test*.
-
-
+
Now requests made in the course of your tests hit the testing backend instead of the normal backend.
-This setup also calls `TestBed.inject()` to inject the `HttpClient` service and the mocking controller
-so they can be referenced during the tests.
+This setup also calls `TestBed.inject()` to inject the `HttpClient` service and the mocking controller so they can be referenced during the tests.
### Expecting and answering requests
Now you can write a test that expects a GET Request to occur and provides a mock response.
-
-
+
The last step, verifying that no requests remain outstanding, is common enough for you to move it into an `afterEach()` step:
-
-
+
#### Custom request expectations
If matching by URL isn't sufficient, it's possible to implement your own matching function.
For example, you could look for an outgoing request that has an authorization header:
-
-
+
-As with the previous `expectOne()`,
-the test fails if 0 or 2+ requests satisfy this predicate.
+As with the previous `expectOne()`, the test fails if 0 or 2+ requests satisfy this predicate.
#### Handling more than one request
If you need to respond to duplicate requests in your test, use the `match()` API instead of `expectOne()`.
It takes the same arguments but returns an array of matching requests.
-Once returned, these requests are removed from future matching and
-you are responsible for flushing and verifying them.
+Once returned, these requests are removed from future matching and you are responsible for flushing and verifying them.
-
-
+
### Testing for errors
@@ -1185,25 +989,19 @@ You should test the app's defenses against HTTP requests that fail.
Call `request.flush()` with an error message, as seen in the following example.
-
-
+
Alternatively, call `request.error()` with a `ProgressEvent`.
-
-
-
+
## Passing metadata to interceptors
-Many interceptors require or benefit from configuration. Consider an interceptor that retries failed requests.
+Many interceptors require or benefit from configuration.
+Consider an interceptor that retries failed requests.
By default, the interceptor might retry a request three times, but you might want to override this retry count for particularly error-prone or sensitive requests.
-`HttpClient` requests contain a _context_ that can carry metadata about the request.
+`HttpClient` requests contain a *context* that can carry metadata about the request.
This context is available for interceptors to read or modify, though it is not transmitted to the backend server when the request is sent.
This lets applications or other interceptors tag requests with configuration parameters, such as how many times to retry a request.
@@ -1212,29 +1010,30 @@ This lets applications or other interceptors tag requests with configuration par
Angular stores and retrieves a value in the context using an `HttpContextToken`.
You can create a context token using the `new` operator, as in the following example:
-
+
The lambda function `() => 3` passed during the creation of the `HttpContextToken` serves two purposes:
-1. It lets TypeScript infer the type of this token: `HttpContextToken
`.
- The request context is type-safe—reading a token from a request's context returns a value of the appropriate type.
+1. It lets TypeScript infer the type of this token:
+ `HttpContextToken`
+ The request context is type-safe —reading a token from a request's context returns a value of the appropriate type.
-1. It sets the default value for the token.
- This is the value that the request context returns if no other value was set for this token.
- Using a default value avoids the need to check if a particular value is set.
+1. It sets the default value for the token.
+ This is the value that the request context returns if no other value was set for this token.
+ Using a default value avoids the need to check if a particular value is set.
### Setting context values when making a request
When making a request, you can provide an `HttpContext` instance, in which you have already set the context values.
-
+
### Reading context values in an interceptor
Within an interceptor, you can read the value of a token in a given request's context with `HttpContext.get()`.
If you have not explicitly set a value for the token, Angular returns the default value specified in the token.
-
+
### Contexts are mutable
@@ -1242,4 +1041,12 @@ Unlike most other aspects of `HttpRequest` instances, the request context is mut
This lets interceptors coordinate operations through the context.
For instance, the `RetryInterceptor` example could use a second context token to track how many errors occur during the execution of a given request:
-
+
+
+
+
+
+
+
+
+@reviewed 2022-02-28
diff --git a/aio/content/guide/i18n-common-add-package.md b/aio/content/guide/i18n-common-add-package.md
index c19c76eabfc70..29402631bb3d1 100644
--- a/aio/content/guide/i18n-common-add-package.md
+++ b/aio/content/guide/i18n-common-add-package.md
@@ -4,7 +4,7 @@ To take advantage of the localization features of Angular, use the [Angular CLI]
To add the `@angular/localize` package, use the following command to update the `package.json` and `polyfills.ts` files in your project.
-
+
diff --git a/aio/content/guide/i18n-common-deploy.md b/aio/content/guide/i18n-common-deploy.md
index 8b3e6b334e764..1dfe7fa58bd44 100644
--- a/aio/content/guide/i18n-common-deploy.md
+++ b/aio/content/guide/i18n-common-deploy.md
@@ -1,6 +1,7 @@
# Deploy multiple locales
-If `myapp` is the directory that contains the distributable files of your project, you typically make different versions available for different locales in locale directories. For example, your French version is located in the `myapp/fr` directory and the Spanish version is located in the `myapp/es` directory.
+If `myapp` is the directory that contains the distributable files of your project, you typically make different versions available for different locales in locale directories.
+For example, your French version is located in the `myapp/fr` directory and the Spanish version is located in the `myapp/es` directory.
The HTML `base` tag with the `href` attribute specifies the base URI, or URL, for relative links.
If you set the `"localize"` option in [`angular.json`][AioGuideWorkspaceConfig] workspace build configuration file to `true` or to an array of locale IDs, the CLI adjusts the base `href` for each version of the application.
@@ -8,7 +9,7 @@ To adjust the base `href` for each version of the application, the CLI adds the
Specify the `"baseHref"` for each locale in your [`angular.json`][AioGuideWorkspaceConfig] workspace build configuration file.
The following example displays `"baseHref"` set to an empty string.
-
+
Also, to declare the base `href` at compile time, use the CLI `--baseHref` option with [`ng build`][AioCliBuild].
@@ -50,4 +51,4 @@ The following example displays an Apache configuration.
-@reviewed 2021-10-07
+@reviewed 2022-02-28
diff --git a/aio/content/guide/i18n-common-format-data-locale.md b/aio/content/guide/i18n-common-format-data-locale.md
index 764e47d660f2c..a5a1ae8561165 100644
--- a/aio/content/guide/i18n-common-format-data-locale.md
+++ b/aio/content/guide/i18n-common-format-data-locale.md
@@ -1,13 +1,14 @@
# Format data based on locale
-Angular provides the following built-in data transformation [pipes][AioGuideGlossaryPipe]. The data transformation pipes use the [`LOCALE_ID`][AioApiCoreLocaleId] token to format data based on rules of each locale.
+Angular provides the following built-in data transformation [pipes][AioGuideGlossaryPipe].
+The data transformation pipes use the [`LOCALE_ID`][AioApiCoreLocaleId] token to format data based on rules of each locale.
-| Data transformation pipe | Details |
-|:--- |:--- |
-| [`DatePipe`][AioApiCommonDatepipe] | Formats a date value. |
-| [`CurrencyPipe`][AioApiCommonCurrencypipe] | Transforms a number into a currency string. |
-| [`DecimalPipe`][AioApiCommonDecimalpipe] | Transforms a number into a decimal number string. |
-| [`PercentPipe`][AioApiCommonPercentpipe] | Transforms a number into a percentage string. |
+| Data transformation pipe | Details |
+|:--- |:--- |
+| [`DatePipe`][AioApiCommonDatepipe] | Formats a date value. |
+| [`CurrencyPipe`][AioApiCommonCurrencypipe] | Transforms a number into a currency string. |
+| [`DecimalPipe`][AioApiCommonDecimalpipe] | Transforms a number into a decimal number string. |
+| [`PercentPipe`][AioApiCommonPercentpipe] | Transforms a number into a percentage string. |
## Use DatePipe to display the current date
@@ -17,7 +18,7 @@ To display the current date in the format for the current locale, use the follow
-{{ today | date }}
+{{ today | date }}
@@ -25,19 +26,20 @@ To display the current date in the format for the current locale, use the follow
Add the `locale` parameter to the pipe to override the current value of `LOCALE_ID` token.
-To force the currency to use American English (`en-US`), use the following format for the `CurrencyPipe`
+To force the currency to use American English \(`en-US`\), use the following format for the `CurrencyPipe`
-{{ amount | currency : 'en-US' }}
+{{ amount | currency : 'en-US' }}
-**NOTE**: The locale specified for the `CurrencyPipe` overrides the global `LOCALE_ID` token of your application.
+**NOTE**:
+The locale specified for the `CurrencyPipe` overrides the global `LOCALE_ID` token of your application.
@@ -61,4 +63,4 @@ To force the currency to use American English (`en-US`), use the following forma
-@reviewed 2021-10-28
+@reviewed 2022-02-28
diff --git a/aio/content/guide/i18n-common-locale-id.md b/aio/content/guide/i18n-common-locale-id.md
index b7c552109c11a..02f0f736b1288 100644
--- a/aio/content/guide/i18n-common-locale-id.md
+++ b/aio/content/guide/i18n-common-locale-id.md
@@ -1,18 +1,20 @@
# Refer to locales by ID
-Angular uses the Unicode *locale identifier* (Unicode locale ID) to find the correct locale data for internationalization of text strings.
+Angular uses the Unicode *locale identifier* \(Unicode locale ID\) to find the correct locale data for internationalization of text strings.
-* A locale ID conforms to the [Unicode Common Locale Data Repository (CLDR) core specification][UnicodeCldrDevelopmentCoreSpecification]. For more information about locale IDs, see [Unicode Language and Locale Identifiers][UnicodeCldrDevelopmentCoreSpecificationHVgyyng33o798].
-* CLDR and Angular use [BCP 47 tags][RfcEditorInfoBcp47] as the base for the locale ID.
+* A locale ID conforms to the [Unicode Common Locale Data Repository (CLDR) core specification][UnicodeCldrDevelopmentCoreSpecification].
+ For more information about locale IDs, see [Unicode Language and Locale Identifiers][UnicodeCldrDevelopmentCoreSpecificationHVgyyng33o798].
+
+* CLDR and Angular use [BCP 47 tags][RfcEditorInfoBcp47] as the base for the locale ID
A locale ID specifies the language, country, and an optional code for further variants or subdivisions.
-A locale ID consists of the language identifier, a dash (`-`) character, and the locale extension.
+A locale ID consists of the language identifier, a hyphen \(`-`\) character, and the locale extension.
@@ -44,8 +46,6 @@ The [Angular repository][GithubAngularAngularTreeMasterPackagesCommonLocales] in
For a list of language codes, see [ISO 639-2][LocStandardsIso6392].
-
-
## Set the source locale ID
@@ -56,8 +56,8 @@ By default, Angular uses `en-US` as the source locale of your project.
To change the source locale of your project for the build, complete the following actions.
-1. Open the [`angular.json`][AioGuideWorkspaceConfig] workspace build configuration file
-1. Change the source locale in the `sourceLocale` field
+1. Open the [`angular.json`][AioGuideWorkspaceConfig] workspace build configuration file.
+1. Change the source locale in the `sourceLocale` field.
## What's next
diff --git a/aio/content/guide/i18n-common-merge.md b/aio/content/guide/i18n-common-merge.md
index c761983351c0f..4be824a8d8fdb 100644
--- a/aio/content/guide/i18n-common-merge.md
+++ b/aio/content/guide/i18n-common-merge.md
@@ -43,16 +43,16 @@ Use the `i18n` project option in the [`angular.json`][AioGuideWorkspaceConfig] w
The following sub-options identify the source language and tell the compiler where to find supported translations for the project.
-| Suboption | Details |
-|:--- |:--- |
-| `sourceLocale` | The locale you use within the application source code (`en-US` by default) |
-| `locales` | A map of locale identifiers to translation files |
+| Suboption | Details |
+|:--- |:--- |
+| `sourceLocale` | The locale you use within the application source code \(`en-US` by default\) |
+| `locales` | A map of locale identifiers to translation files |
### `angular.json` for `en-US` and `fr` example
-For example, the following excerpt of an [`angular.json`][AioGuideWorkspaceConfig] workspace build configuration file sets the source locale to `en-US` and provides the path to the French (`fr`) locale translation file.
+For example, the following excerpt of an [`angular.json`][AioGuideWorkspaceConfig] workspace build configuration file sets the source locale to `en-US` and provides the path to the French \(`fr`\) locale translation file.
-
+
## Generate application variants for each locale
@@ -64,7 +64,8 @@ To use your locale definition in the build configuration, use the `"localize"` o
-**NOTE**: [Ahead-of-time (AOT) compilation][AioGuideGlossaryAheadOfTimeAotCompilation] is required to localize component templates.
+**NOTE**:
+[Ahead-of-time (AOT) compilation][AioGuideGlossaryAheadOfTimeAotCompilation] is required to localize component templates.
If you changed this setting, set `"aot"` to `true` in order to use AOT.
@@ -75,7 +76,7 @@ If you changed this setting, set `"aot"` to `true` in order to use AOT.
Due to the deployment complexities of i18n and the need to minimize rebuild time, the development server only supports localizing a single locale at a time.
If you set the `"localize"` option to `true`, define more than one locale, and use `ng serve`; then an error occurs.
If you want to develop against a specific locale, set the `"localize"` option to a specific locale.
-For example, for French (`fr`), specify `"localize": ["fr"]`.
+For example, for French \(`fr`\), specify `"localize": ["fr"]`.
@@ -90,7 +91,7 @@ Also, set the property to override other configurations.
The following example displays the `"localize"` option set to `true` in the [`angular.json`][AioGuideWorkspaceConfig] workspace build configuration file, so that all locales defined in the build configuration are built.
-
+
## Build from the command line
@@ -104,7 +105,7 @@ For more information about how to set the locales, see [Generate application var
-
+
## Apply specific build options for just one locale
@@ -112,7 +113,7 @@ To apply specific build options to only one locale, specify a single locale to c
-Use the [Angular CLI][AioCliMain] development server (`ng serve`) with only a single locale.
+Use the [Angular CLI][AioCliMain] development server \(`ng serve`\) with only a single locale.
@@ -120,29 +121,29 @@ Use the [Angular CLI][AioCliMain] development server (`ng serve`) with only a si
The following example displays a custom locale-specific configuration using a single locale.
-
+
Pass this configuration to the `ng serve` or `ng build` commands.
The following code example displays how to serve the French language file.
-
+
For production builds, use configuration composition to run both configurations.
-
+
-
+
## Report missing translations
When a translation is missing, the build succeeds but generates a warning such as `Missing translation for message "{translation_text}"`.
To configure the level of warning that is generated by the Angular compiler, specify one of the following levels.
-| Warning level | Details | Output |
-|:--- |:--- |:--- |
-| `error` | Throw an error and the build fails | n/a |
-| `ignore` | Do nothing | n/a |
-| `warning` | Displays the default warning in the console or shell | `Missing translation for message "{translation_text}"` |
+| Warning level | Details | Output |
+|:--- |:--- |:--- |
+| `error` | Throw an error and the build fails | n/a |
+| `ignore` | Do nothing | n/a |
+| `warning` | Displays the default warning in the console or shell | `Missing translation for message "{translation_text}"` |
Specify the warning level in the `options` section for the `build` target of your [`angular.json`][AioGuideWorkspaceConfig] workspace build configuration file.
@@ -150,7 +151,7 @@ Specify the warning level in the `options` section for the `build` target of you
The following example displays how to set the warning level to `error`.
-
+
@@ -158,7 +159,7 @@ When you compile your Angular project into an Angular application, the instances
This means that your Angular application is translated after compilation.
This also means that you can create localized versions of your Angular application without re-compiling your entire Angular project for each locale.
-When you translate your Angular application, the *translation transformation* replaces and reorders the parts (static strings and expressions) of the template literal string with strings from a collection of translations.
+When you translate your Angular application, the *translation transformation* replaces and reorders the parts \(static strings and expressions\) of the template literal string with strings from a collection of translations.
For more information, see [`$localize`][AioApiLocalizeInitLocalize].
@@ -203,4 +204,4 @@ Compile once, then translate for each locale.
-@reviewed 2021-10-13
+@reviewed 2022-02-28
diff --git a/aio/content/guide/i18n-common-prepare.md b/aio/content/guide/i18n-common-prepare.md
index 55dd68fa4bb7b..22bc7b29e50c0 100644
--- a/aio/content/guide/i18n-common-prepare.md
+++ b/aio/content/guide/i18n-common-prepare.md
@@ -29,11 +29,11 @@ The `i18n` attribute is a custom attribute that the Angular tools and compilers
The following `