diff --git a/aio/content/examples/component-communication/.gitignore b/aio/content/examples/component-interaction/.gitignore similarity index 100% rename from aio/content/examples/component-communication/.gitignore rename to aio/content/examples/component-interaction/.gitignore diff --git a/aio/content/examples/component-communication/e2e-spec.ts b/aio/content/examples/component-interaction/e2e-spec.ts similarity index 100% rename from aio/content/examples/component-communication/e2e-spec.ts rename to aio/content/examples/component-interaction/e2e-spec.ts diff --git a/aio/content/examples/component-communication/example-config.json b/aio/content/examples/component-interaction/example-config.json similarity index 100% rename from aio/content/examples/component-communication/example-config.json rename to aio/content/examples/component-interaction/example-config.json diff --git a/aio/content/examples/component-communication/plnkr.json b/aio/content/examples/component-interaction/plnkr.json similarity index 100% rename from aio/content/examples/component-communication/plnkr.json rename to aio/content/examples/component-interaction/plnkr.json diff --git a/aio/content/examples/component-communication/src/app/app.component.html b/aio/content/examples/component-interaction/src/app/app.component.html similarity index 100% rename from aio/content/examples/component-communication/src/app/app.component.html rename to aio/content/examples/component-interaction/src/app/app.component.html diff --git a/aio/content/examples/component-communication/src/app/app.component.ts b/aio/content/examples/component-interaction/src/app/app.component.ts similarity index 100% rename from aio/content/examples/component-communication/src/app/app.component.ts rename to aio/content/examples/component-interaction/src/app/app.component.ts diff --git a/aio/content/examples/component-communication/src/app/app.module.ts b/aio/content/examples/component-interaction/src/app/app.module.ts similarity index 100% rename from aio/content/examples/component-communication/src/app/app.module.ts rename to aio/content/examples/component-interaction/src/app/app.module.ts diff --git a/aio/content/examples/component-communication/src/app/astronaut.component.ts b/aio/content/examples/component-interaction/src/app/astronaut.component.ts similarity index 100% rename from aio/content/examples/component-communication/src/app/astronaut.component.ts rename to aio/content/examples/component-interaction/src/app/astronaut.component.ts diff --git a/aio/content/examples/component-communication/src/app/countdown-parent.component.ts b/aio/content/examples/component-interaction/src/app/countdown-parent.component.ts similarity index 100% rename from aio/content/examples/component-communication/src/app/countdown-parent.component.ts rename to aio/content/examples/component-interaction/src/app/countdown-parent.component.ts diff --git a/aio/content/examples/component-communication/src/app/countdown-timer.component.ts b/aio/content/examples/component-interaction/src/app/countdown-timer.component.ts similarity index 100% rename from aio/content/examples/component-communication/src/app/countdown-timer.component.ts rename to aio/content/examples/component-interaction/src/app/countdown-timer.component.ts diff --git a/aio/content/examples/component-communication/src/app/hero-child.component.ts b/aio/content/examples/component-interaction/src/app/hero-child.component.ts similarity index 100% rename from aio/content/examples/component-communication/src/app/hero-child.component.ts rename to aio/content/examples/component-interaction/src/app/hero-child.component.ts diff --git a/aio/content/examples/component-communication/src/app/hero-parent.component.ts b/aio/content/examples/component-interaction/src/app/hero-parent.component.ts similarity index 100% rename from aio/content/examples/component-communication/src/app/hero-parent.component.ts rename to aio/content/examples/component-interaction/src/app/hero-parent.component.ts diff --git a/aio/content/examples/component-communication/src/app/hero.ts b/aio/content/examples/component-interaction/src/app/hero.ts similarity index 100% rename from aio/content/examples/component-communication/src/app/hero.ts rename to aio/content/examples/component-interaction/src/app/hero.ts diff --git a/aio/content/examples/component-communication/src/app/mission.service.ts b/aio/content/examples/component-interaction/src/app/mission.service.ts similarity index 100% rename from aio/content/examples/component-communication/src/app/mission.service.ts rename to aio/content/examples/component-interaction/src/app/mission.service.ts diff --git a/aio/content/examples/component-communication/src/app/missioncontrol.component.ts b/aio/content/examples/component-interaction/src/app/missioncontrol.component.ts similarity index 100% rename from aio/content/examples/component-communication/src/app/missioncontrol.component.ts rename to aio/content/examples/component-interaction/src/app/missioncontrol.component.ts diff --git a/aio/content/examples/component-communication/src/app/name-child.component.ts b/aio/content/examples/component-interaction/src/app/name-child.component.ts similarity index 100% rename from aio/content/examples/component-communication/src/app/name-child.component.ts rename to aio/content/examples/component-interaction/src/app/name-child.component.ts diff --git a/aio/content/examples/component-communication/src/app/name-parent.component.ts b/aio/content/examples/component-interaction/src/app/name-parent.component.ts similarity index 100% rename from aio/content/examples/component-communication/src/app/name-parent.component.ts rename to aio/content/examples/component-interaction/src/app/name-parent.component.ts diff --git a/aio/content/examples/component-communication/src/app/version-child.component.ts b/aio/content/examples/component-interaction/src/app/version-child.component.ts similarity index 100% rename from aio/content/examples/component-communication/src/app/version-child.component.ts rename to aio/content/examples/component-interaction/src/app/version-child.component.ts diff --git a/aio/content/examples/component-communication/src/app/version-parent.component.ts b/aio/content/examples/component-interaction/src/app/version-parent.component.ts similarity index 100% rename from aio/content/examples/component-communication/src/app/version-parent.component.ts rename to aio/content/examples/component-interaction/src/app/version-parent.component.ts diff --git a/aio/content/examples/component-communication/src/app/voter.component.ts b/aio/content/examples/component-interaction/src/app/voter.component.ts similarity index 100% rename from aio/content/examples/component-communication/src/app/voter.component.ts rename to aio/content/examples/component-interaction/src/app/voter.component.ts diff --git a/aio/content/examples/component-communication/src/app/votetaker.component.ts b/aio/content/examples/component-interaction/src/app/votetaker.component.ts similarity index 100% rename from aio/content/examples/component-communication/src/app/votetaker.component.ts rename to aio/content/examples/component-interaction/src/app/votetaker.component.ts diff --git a/aio/content/examples/component-communication/src/demo.css b/aio/content/examples/component-interaction/src/demo.css similarity index 100% rename from aio/content/examples/component-communication/src/demo.css rename to aio/content/examples/component-interaction/src/demo.css diff --git a/aio/content/examples/component-communication/src/index.html b/aio/content/examples/component-interaction/src/index.html similarity index 100% rename from aio/content/examples/component-communication/src/index.html rename to aio/content/examples/component-interaction/src/index.html diff --git a/aio/content/examples/component-communication/src/main.ts b/aio/content/examples/component-interaction/src/main.ts similarity index 100% rename from aio/content/examples/component-communication/src/main.ts rename to aio/content/examples/component-interaction/src/main.ts diff --git a/aio/content/guide/component-communication.md b/aio/content/guide/component-interaction.md similarity index 67% rename from aio/content/guide/component-communication.md rename to aio/content/guide/component-interaction.md index 38af8444c4..c5b4bbd07a 100644 --- a/aio/content/guide/component-communication.md +++ b/aio/content/guide/component-interaction.md @@ -15,15 +15,15 @@ in which two or more components share information. # Contents -* [Pass data from parent to child with input binding](guide/component-communication#parent-to-child) -* [Intercept input property changes with a setter](guide/component-communication#parent-to-child-setter) -* [Intercept input property changes with `ngOnChanges()`](guide/component-communication#parent-to-child-on-changes) -* [Parent calls an `@ViewChild()`](guide/component-communication#parent-to-view-child) -* [Parent and children communicate via a service](guide/component-communication#bidirectional-service) +* [Pass data from parent to child with input binding](guide/component-interaction#parent-to-child) +* [Intercept input property changes with a setter](guide/component-interaction#parent-to-child-setter) +* [Intercept input property changes with `ngOnChanges()`](guide/component-interaction#parent-to-child-on-changes) +* [Parent calls an `@ViewChild()`](guide/component-interaction#parent-to-view-child) +* [Parent and children communicate via a service](guide/component-interaction#bidirectional-service) --> -**See the **. +**See the **. {@a parent-to-child} @@ -33,7 +33,7 @@ in which two or more components share information. typically adorned with [@Input decorations](guide/template-syntax#inputs-outputs). - + @@ -46,7 +46,7 @@ binding its `master` string property to the child's `master` alias, and each iteration's `hero` instance to the child's `hero` property. - + @@ -56,23 +56,23 @@ The running application displays three heroes:
- Parent-to-child + Parent-to-child
-### Test it +

Test it

E2E test that all children were instantiated and displayed as expected: - + -[Back to top](guide/component-communication#top) +[Back to top](guide/component-interaction#top) {@a parent-to-child-setter} @@ -84,7 +84,7 @@ 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. - + @@ -93,30 +93,30 @@ 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: - +
- Parent-to-child-setter + Parent-to-child-setter
-### Test it +

Test it

E2E tests of input property setter with empty and non-empty names: - + -[Back to top](guide/component-communication#top) +[Back to top](guide/component-interaction#top) {@a parent-to-child-on-changes} @@ -139,7 +139,7 @@ Learn about `ngOnChanges()` in the [LifeCycle Hooks](guide/lifecycle-hooks) chap This `VersionChildComponent` detects changes to the `major` and `minor` input properties and composes a log message reporting these changes: - + @@ -148,7 +148,7 @@ This `VersionChildComponent` detects changes to the `major` and `minor` input pr The `VersionParentComponent` supplies the `minor` and `major` values and binds buttons to methods that change them. - + @@ -158,24 +158,24 @@ Here's the output of a button-pushing sequence:
- Parent-to-child-onchanges + Parent-to-child-onchanges
-### Test it +

Test it

Test that ***both*** input properties are set initially and that button clicks trigger the expected `ngOnChanges` calls and values: - + -[Back to top](guide/component-communication#top) +[Back to top](guide/component-interaction#top) {@a child-to-parent} @@ -189,7 +189,7 @@ The child's `EventEmitter` property is an ***output property***, as seen in this `VoterComponent`: - + @@ -201,7 +201,7 @@ The parent `VoteTakerComponent` binds an event handler called `onVoted()` that r payload `$event` and updates a counter. - + @@ -212,23 +212,23 @@ and the method processes it:
- Child-to-parent + Child-to-parent
-### Test it +

Test it

Test that clicking the *Agree* and *Disagree* buttons update the appropriate counters: - + -[Back to top](guide/component-communication#top) +[Back to top](guide/component-interaction#top) @@ -245,7 +245,7 @@ The following is a child `CountdownTimerComponent` that repeatedly counts down t It has `start` and `stop` methods that control the clock and it displays a countdown status message in its own template. - + @@ -254,7 +254,7 @@ countdown status message in its own template. The `CountdownLocalVarParentComponent` that hosts the timer component is as follows: - + @@ -274,7 +274,7 @@ Here we see the parent and child working together.
- countdown timer + countdown timer
@@ -282,20 +282,20 @@ Here we see the parent and child working together. {@a countdown-tests} -### Test it +

Test it

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-communication#top) +[Back to top](guide/component-interaction#top) {@a parent-to-view-child} @@ -312,9 +312,9 @@ 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-communication#countdown-timer-example) example. +[Countdown Timer](guide/component-interaction#countdown-timer-example) example. Neither its appearance nor its behavior will change. -The child [CountdownTimerComponent](guide/component-communication#countdown-timer-example) is the same as well. +The child [CountdownTimerComponent](guide/component-interaction#countdown-timer-example) is the same as well.
@@ -329,7 +329,7 @@ is solely for the purpose of demonstration. Here is the parent, `CountdownViewChildParentComponent`: - + @@ -360,10 +360,10 @@ in the same cycle. The app has to *wait one turn* before it can display the seco Use `setTimeout()` to wait one tick and then revise the `seconds()` method so that it takes future values from the timer component. -### Test it -Use [the same countdown timer tests](guide/component-communication#countdown-tests) as before. +

Test it

+Use [the same countdown timer tests](guide/component-interaction#countdown-tests) as before. -[Back to top](guide/component-communication#top) +[Back to top](guide/component-interaction#top) {@a bidirectional-service} @@ -378,7 +378,7 @@ Components outside this component subtree have no access to the service or their This `MissionService` connects the `MissionControlComponent` to multiple `AstronautComponent` children. - + @@ -388,7 +388,7 @@ The `MissionControlComponent` both provides the instance of the service that it (through the `providers` metadata array) and injects that instance into itself through its constructor: - + @@ -398,7 +398,7 @@ 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: - + @@ -426,21 +426,21 @@ facilitated by the service:
- bidirectional-service + bidirectional-service
-### Test it +

Test it

Tests click buttons of both the parent `MissionControlComponent` and the `AstronautComponent` children and verify that the history meets expectations: - + -[Back to top](guide/component-communication#top) +[Back to top](guide/component-interaction#top) diff --git a/aio/content/guide/component-styles.md b/aio/content/guide/component-styles.md index 5633703d4c..c618630b1f 100644 --- a/aio/content/guide/component-styles.md +++ b/aio/content/guide/component-styles.md @@ -1,12 +1,4 @@ -@title -Component Styles - -@intro -Learn how to apply CSS styles to components. - -@description - - +# 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 @@ -142,29 +134,20 @@ through this component to all of its child elements in the DOM. - - The `/deep/` selector also has the alias `>>>`. You can use either interchangeably.
- - Use the `/deep/` and `>>>` selectors only with *emulated* view encapsulation. Emulated is the default and most commonly used view encapsulation. For more information, see the [Controlling view encapsulation](guide/component-styles#view-encapsulation) section. -
- - {@a loading-styles} - - -## Loading styles into components +## Loading component styles There are several ways to add styles to a component: @@ -279,7 +262,7 @@ In this case, the URL is relative to the CSS file into which you're importing. -## Controlling view encapsulation: native, emulated, and none +## View encapsulation As discussed earlier, component CSS styles are encapsulated into the component's view and don't affect the rest of the application. @@ -323,7 +306,7 @@ in most cases. -## Appendix 1: Inspecting the CSS generated in emulated view encapsulation +## Appendix: Inspecting generated CSS When using emulated view encapsulation, Angular preprocesses all component styles so that they approximate the standard shadow CSS scoping rules. @@ -381,7 +364,7 @@ These extra selectors enable the scoping rules described in this page. -## Appendix 2: Loading styles with relative URLs +## Appendix: Loading with relative URLs It's common practice to split a component's code, HTML, and CSS into three separate files in the same directory: diff --git a/aio/content/guide/dynamic-component-loader.md b/aio/content/guide/dynamic-component-loader.md index 5d6cec220e..924853bf0d 100644 --- a/aio/content/guide/dynamic-component-loader.md +++ b/aio/content/guide/dynamic-component-loader.md @@ -1,34 +1,9 @@ -@title -Dynamic Component Loader - -@intro -Load components dynamically. - -@description - +# Dynamic Component Loader Component templates are not always fixed. An application may need to load new components at runtime. This cookbook shows you how to use `ComponentFactoryResolver` to add components dynamically. -{@a toc} - - - See the of the code in this cookbook. @@ -51,7 +26,7 @@ Angular comes with its own API for loading components dynamically. {@a directive} -## The directive +## The anchor directive Before you can add components you have to define an anchor point to tell Angular where to insert components. @@ -100,7 +75,7 @@ because it doesn't render any additional output. {@a resolving-components} -### Resolving components +## Resolving components Take a closer look at the methods in `ad-banner.component.ts`. @@ -184,7 +159,7 @@ add dynamically loaded components to the `NgModule`'s `entryComponents` array: {@a common-interface} -### A common _AdComponent_ interface +## The _AdComponent_ interface In the ad banner, all components implement a common `AdComponent` interface to standardize the API for passing data to the components. @@ -213,7 +188,7 @@ Here are two sample components and the `AdComponent` interface for reference: {@a final-ad-baner} -### Final ad banner +## Final ad banner The final ad banner looks like this:
diff --git a/aio/content/guide/ngmodule.md b/aio/content/guide/ngmodule.md index 2e1f0b2cb2..f2bb2ccf8b 100644 --- a/aio/content/guide/ngmodule.md +++ b/aio/content/guide/ngmodule.md @@ -1,5 +1,4 @@ -

NgModules

- +# NgModules **NgModules** help organize an application into cohesive blocks of functionality. -### Live examples +#### Live examples This page explains NgModules through a progression of improvements to a sample with a "Tour of Heroes" theme. Here's an index to live examples at key moments in the evolution of the sample: @@ -48,7 +47,7 @@ Here's an index to live examples at key moments in the evolution of the sample: * Just before adding SharedModule * The final version -### Frequently asked questions (FAQs) +#### Frequently asked questions (FAQs) This page covers NgModule concepts in a tutorial fashion. @@ -108,7 +107,7 @@ Later in this page, you'll read about this process. For now, you'll start with t -## _AppModule_: the application root module +## The root _AppModule_ Every Angular app has a *root module* class. By convention, the *root module* class is called `AppModule` and it exists in a file named `app.module.ts`. @@ -156,7 +155,7 @@ You launch the application by bootstrapping the `AppModule` in the `main.ts` fil Angular offers a variety of bootstrapping options targeting multiple platforms. This page describes two options, both targeting the browser. -### Dynamic bootstrapping with the just-in-time (JIT) compiler +### Compile just-in-time (JIT) In the first, _dynamic_ option, the [Angular compiler](guide/ngmodule-faq#q-angular-compiler "About the Angular Compiler") compiles the application in the browser and then launches the app. @@ -172,7 +171,7 @@ The samples in this page demonstrate the dynamic bootstrapping approach. Try the live example. -### Static bootstrapping with the ahead-of-time (AOT) compiler +### Compile ahead-of-time (AOT) Consider the static alternative which can produce a much smaller application that launches faster, especially on mobile devices and high latency networks. @@ -245,10 +244,6 @@ Import the `HighlightDirective` class and add it to the module's `declarations` - - -### Add a component - Refactor the title into its own `TitleComponent`. The component's template binds to the component's `title` and `subtitle` properties like this: @@ -388,7 +383,7 @@ You must import those modules before you can use their directives. To illustrate this point, you'll extend the sample app with `ContactComponent`, a form component that imports form support from the Angular `FormsModule`. -### Add the _ContactComponent_ +

Add the _ContactComponent_

[Angular forms](guide/forms) are a great way to manage user data entry. @@ -400,7 +395,7 @@ implemented with Angular forms in the [template-driven form](guide/forms#templat -### Angular form styles +

Angular form styles

You can write Angular form components in template-driven or @@ -476,7 +471,7 @@ Even if Angular somehow recognized `ngModel`, `ContactComponent` wouldn't behave like an Angular form because form features such as validation aren't yet available. -### Import the FormsModule +

Import the FormsModule

Add the `FormsModule` to the `AppModule` metadata's `imports` list. @@ -510,7 +505,7 @@ Components, directives, and pipes belong to _one module only_. {@a declare-pipe} -### Declare the contact component, directive, and pipe +

Declare the contact component, directive, and pipe

The application won't compile until you declare the contact component, directive, and pipe. Update the `declarations` in the `AppModule` accordingly: @@ -547,7 +542,7 @@ You'll learn more about that issue later in this page, in [Resolve directive con -### Provide the _ContactService_ +

Provide the _ContactService_

The `ContactComponent` displays contacts retrieved by the `ContactService`, which Angular injects into its constructor. @@ -574,7 +569,7 @@ Now you can inject `ContactService` (like `UserService`) into any component in t -### Application-scoped providers +

Application-scoped providers

The `ContactService` provider is _application_-scoped because Angular registers a module's `providers` with the application's *root injector*. @@ -602,7 +597,7 @@ Now you can inject `ContactService` (like `UserService`) into any component in t -### Run the app +

Run the app

Everything is in place to run the application with its contact editor. The app file structure looks like this: @@ -1322,7 +1317,7 @@ whether that component is eagerly or lazily loaded. -### Why bother? +

Why bother?

This scenario is clearly contrived. The app is too small to worry about a single service file and a tiny, one-time component. @@ -1530,12 +1525,12 @@ Angular creates a lazy-loaded module with its own injector, a _child_ of the roo Of course it finds the instance imported by the root `AppModule`. Now `parentModule` exists and the constructor throws the error. -### Conclusion +## Conclusion You made it! You can examine and download the complete source for this final version from the live example. -### Frequently asked questions +## Frequently asked questions Now that you understand NgModules, you may be interested in the companion [NgModule FAQs](guide/ngmodule-faq "NgModule FAQs") page diff --git a/aio/content/guide/pipes.md b/aio/content/guide/pipes.md index b4e1e5f74e..12f03a655a 100644 --- a/aio/content/guide/pipes.md +++ b/aio/content/guide/pipes.md @@ -1,12 +1,4 @@ -@title -Pipes - -@intro -Pipes transform displayed values within a template. - -@description - - +# Pipes Every application starts out with what seems like a simple task: get data, transform them, and show them to users. Getting data could be as simple as creating a local variable or as complex as streaming data over a WebSocket. @@ -27,7 +19,6 @@ Introducing Angular pipes, a way to write display-value transformations that you You can run the in Plunker and download the code from there. - ## Using pipes A pipe takes in data as input and transforms it to a desired output. @@ -217,25 +208,19 @@ Your pipe has one such parameter: the `exponent`. -### The *PipeTransform* interface +## The *PipeTransform* interface The `transform` method is essential to a pipe. The `PipeTransform` *interface* defines that method and guides both tooling and the compiler. Technically, it's optional; Angular looks for and executes the `transform` method regardless. -
- - Now you need a component to demonstrate the pipe. - - -
Power Booster
@@ -250,14 +235,11 @@ Note the following:
- -
Remember the declarations array
- You must manually register custom pipes. If you don't, Angular reports an error. In the previous example, you didn't list the `DatePipe` because all @@ -302,7 +284,7 @@ Angular strives to lower the cost whenever possible and appropriate. Angular picks a simpler, faster change detection algorithm when you use a pipe. -### No pipe +

No pipe

In the next example, the component uses the default, aggressive change detection strategy to monitor and update its display of every hero in the `heroes` array. Here's the template: @@ -326,7 +308,7 @@ You can add heroes and Angular updates the display when you do. If you click the `reset` button, Angular replaces `heroes` with a new array of the original heroes and updates the display. If you added the ability to remove or change a hero, Angular would detect those changes and update the display as well. -### Flying-heroes pipe +

FlyingHeroesPipe

Add a `FlyingHeroesPipe` to the `*ngFor` repeater that filters the list of heroes to just those heroes who can fly. @@ -410,7 +392,7 @@ impure like this: Before doing that, understand the difference between pure and impure, starting with a pure pipe. -### Pure pipes +

Pure pipes

Angular executes a *pure pipe* only when it detects a *pure change* to the input value. A pure change is either a change to a primitive input value (`String`, `Number`, `Boolean`, `Symbol`) @@ -441,7 +423,7 @@ a point that's discussed later in this page. -### Impure pipes +

Impure pipes

Angular executes an *impure pipe* during every component change detection cycle. An impure pipe is called often, as often as every keystroke or mouse-move. @@ -453,7 +435,7 @@ An expensive, long-running pipe could destroy the user experience. {@a impure-flying-heroes} -### An impure *FlyingHeroesPipe* +

An impure FlyingHeroesPipe

A flip of the switch turns the `FlyingHeroesPipe` into a `FlyingHeroesImpurePipe`. The complete implementation is as follows: @@ -498,10 +480,8 @@ You can confirm in the that the _flying heroes_ display updates as you add heroes, even when you mutate the `heroes` array. -

- The impure AsyncPipe -

- +{@a async-pipe} +

The impure AsyncPipe

The Angular `AsyncPipe` is an interesting example of an impure pipe. @@ -528,7 +508,7 @@ extract the resolved values and expose them for binding, and have to unsubscribe when it's destroyed (a potent source of memory leaks). -### An impure caching pipe +

An impure caching pipe

Write one more impure pipe, a pipe that makes an HTTP request. @@ -570,7 +550,7 @@ A breakpoint on the pipe's request for data shows the following: * Each pipe instance caches its own URL and data. * Each pipe instance only calls the server once. -### *JsonPipe* +

JsonPipe

In the previous code sample, the second `fetch` pipe binding demonstrates more pipe chaining. It displays the same hero data in JSON format by chaining through to the built-in `JsonPipe`. @@ -598,7 +578,7 @@ inspect an object for future binding. {@a pure-pipe-pure-fn} -### Pure pipes and pure functions +

Pure pipes and pure functions

A pure pipe uses pure functions. Pure functions process inputs and return values without detectable side effects. diff --git a/aio/content/guide/template-syntax.md b/aio/content/guide/template-syntax.md index d088637d3b..7bc2b2f69a 100644 --- a/aio/content/guide/template-syntax.md +++ b/aio/content/guide/template-syntax.md @@ -1,82 +1,18 @@ -@title -Template Syntax - -@intro -Learn how to write templates that display data and consume user events with the help of data binding. - -@description - - +# Template Syntax - - The Angular application manages what the user sees and can do, achieving this through the interaction of a component class instance (the *component*) and its user-facing template. You may be familiar with the component/template duality from your experience with model-view-controller (MVC) or model-view-viewmodel (MVVM). In Angular, the component plays the part of the controller/viewmodel, and the template represents the view. - -{@a toc} - - - {@a html} - - ## HTML in templates HTML is the language of the Angular template. @@ -98,31 +34,20 @@ Begin with the first form of data binding—interpolation—to see how m
- - {@a interpolation} - ## Interpolation ( {{...}} ) You met the double-curly braces of interpolation, `{{` and `}}`, early in your Angular education. - - - - You use interpolation to weave calculated strings into the text between HTML element tags and within attribute assignments. - - - - The text between the braces is often the name of a component property. Angular replaces that name with the string value of the corresponding component property. In the example above, Angular evaluates the `title` and `heroImageUrl` properties and "fills in the blanks", first displaying a bold application title and then a heroic image. @@ -130,22 +55,14 @@ and "fills in the blanks", first displaying a bold application title and then a More generally, the text between the braces is a **template expression** that Angular first **evaluates** and then **converts to a string**. The following interpolation illustrates the point by adding the two numbers: - - - - The expression can invoke methods of the host component such as `getVal()`, seen here: - - - - Angular evaluates all expressions in double curly braces, converts the expression results to strings, and links them with neighboring literal strings. Finally, it assigns this composite interpolated result to an **element or directive property**. @@ -156,15 +73,13 @@ Though this is not exactly true. Interpolation is a special syntax that Angular [property binding](guide/template-syntax#property-binding), as is explained [below](guide/template-syntax#property-binding-or-interpolation). But first, let's take a closer look at template expressions and statements. + back to top
- - {@a template-expressions} - ## Template expressions A template **expression** produces a value. @@ -186,40 +101,29 @@ including: * chaining expressions with ; or , * increment and decrement operators (`++` and `--`) - Other notable differences from JavaScript syntax include: * no support for the bitwise operators `|` and `&` * new [template expression operators](guide/template-syntax#expression-operators), such as `|` and `?.` - {@a expression-context} - ### Expression context The *expression context* is typically the _component_ instance. In the following snippets, the `title` within double-curly braces and the `isUnchanged` in quotes refer to properties of the `AppComponent`. - - - - An expression may also refer to properties of the _template's_ context such as a [template input variable](guide/template-syntax#template-input-variable) (`let hero`) or a [template reference variable](guide/template-syntax#ref-vars) (`#heroInput`). - - - - The context for terms in an expression is a blend of the _template variables_, the directive's _context_ object (if it has one), and the component's _members_. If you reference a name that belongs to more than one of these namespaces, @@ -235,14 +139,13 @@ Template expressions cannot refer to anything in the global namespace. They can't refer to `window` or `document`. They can't call `console.log` or `Math.max`. They are restricted to referencing members of the expression context. + back to top {@a no-side-effects} - {@a expression-guidelines} - ### Expression guidelines Template expressions can make or break an application. @@ -298,11 +201,8 @@ it returns the same object *reference* when called twice in a row.
- - {@a template-statements} - ## Template statements A template **statement** responds to an **event** raised by a binding target @@ -310,13 +210,9 @@ such as an element, component, or directive. You'll see template statements in the [event binding](guide/template-syntax#event-binding) section, appearing in quotes to the right of the `=` symbol as in `(event)="statement"`. - - - - A template statement *has a side effect*. That's the whole point of an event. It's how you update application state from user action. @@ -345,26 +241,18 @@ such as an event handling method of the component instance. The *statement context* is typically the component instance. The *deleteHero* in `(click)="deleteHero()"` is a method of the data-bound component. - - - - The statement context may also refer to properties of the template's own context. In the following examples, the template `$event` object, a [template input variable](guide/template-syntax#template-input-variable) (`let hero`), and a [template reference variable](guide/template-syntax#ref-vars) (`#heroForm`) are passed to an event handling method of the component. - - - - Template context names take precedence over component context names. In `deleteHero(hero)` above, the `hero` is the template input variable, not the component's `hero` property. @@ -380,15 +268,13 @@ A method call or simple property assignment should be the norm. Now that you have a feel for template expressions and statements, you're ready to learn about the varieties of data binding syntax beyond interpolation. + back to top
- - {@a binding-syntax} - ## Binding syntax: An overview Data binding is a mechanism for coordinating what users see, with application data values. @@ -402,49 +288,33 @@ This guide covers most of them, after a high-level view of Angular data binding Binding types can be grouped into three categories distinguished by the direction of data flow: from the _source-to-view_, from _view-to-source_, and in the two-way sequence: _view-to-source-to-view_: - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Data direction Syntax Type
One-way
from data source
to view target
@@ -454,7 +324,6 @@ from the _source-to-view_, from _view-to-source_, and in the two-way sequence: _ Interpolation
Property
@@ -462,55 +331,37 @@ from the _source-to-view_, from _view-to-source_, and in the two-way sequence: _ Class
Style
One-way
from view target
to data source
- (target)="statement" on-target="statement" - Event
Two-way - [(target)]="expression" bindon-target="expression" - Two-way
- - Binding types other than interpolation have a **target name** to the left of the equal sign, either surrounded by punctuation (`[]`, `()`) or preceded by a prefix (`bind-`, `on-`, `bindon-`). @@ -529,36 +380,24 @@ It requires a new mental model. In the normal course of HTML development, you create a visual structure with HTML elements, and you modify those elements by setting element attributes with string constants. - - - - You still create a structure and initialize attribute values this way in Angular templates. Then you learn to create new elements with components that encapsulate HTML and drop them into templates as if they were native HTML elements. - - - - That's HTML Plus. Then you learn about data binding. The first binding you meet might look like this: - - - - You'll get to that peculiar bracket notation in a moment. Looking beyond it, your intuition suggests that you're binding to the button's `disabled` attribute and setting it to the current value of the component's `isUnchanged` property. @@ -567,11 +406,8 @@ Your intuition is incorrect! Your everyday HTML mental model is misleading. In fact, once you start data binding, you are no longer working with HTML *attributes*. You aren't setting attributes. You are setting the *properties* of DOM elements, components, and directives. -
- - ### HTML attribute vs. DOM property The distinction between an HTML attribute and a DOM property is crucial to understanding how Angular binding works. @@ -613,34 +449,23 @@ The value of the *property* matters. **The HTML attribute and the DOM property are not the same thing, even when they have the same name.** -
- - This fact bears repeating: **Template binding works with *properties* and *events*, not *attributes*.** -
- -
A world without attributes
- - In the world of Angular, the only role of attributes is to initialize element and directive state. When you write a data binding, you're dealing exclusively with properties and events of the target object. HTML attributes effectively disappear. -
- - With this model firmly in mind, read on to learn about binding targets. ### Binding targets @@ -651,182 +476,114 @@ Depending on the binding type, the target can be an (element | component | directive) event, or (rarely) an attribute name. The following table summarizes: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Type Target Examples
Property Element property
Component property
Directive property
- - -
Event Element event
Component event
Directive event
- - -
Two-way Event and property - - -
Attribute Attribute (the exception) - - -
Class class property - - -
Style style property - - -
- - With this broad view in mind, you're ready to look at binding types in detail. back to top
- - {@a property-binding} - ## Property binding ( [property] ) Write a template **property binding** to set a property of a view element. @@ -835,41 +592,25 @@ The binding sets the property to the value of a [template expression](guide/temp The most common property binding sets an element property to a component property value. An example is binding the `src` property of an image element to a component's `heroImageUrl` property: - - - - Another example is disabling a button when the component says that it `isUnchanged`: - - - - Another is setting a property of a directive: - - - - Yet another is setting the model property of a custom component (a great way for parent and child components to communicate): - - - - ### One-way *in* People often describe property binding as *one-way data binding* because it flows a value in one direction, @@ -878,11 +619,8 @@ from a component's data property into a target element property. You cannot use property binding to pull values *out* of the target element. You can't bind to a property of the target element to _read_ it. You can only _set_ it. -
- - Similarly, you cannot use property binding to *call* a method on the target element. If the element raises events, you can listen to them with an [event binding](guide/template-syntax#event-binding). @@ -893,32 +631,21 @@ See the API reference for [ViewChild](api/core/ViewChild) and [ContentChild](api/core/ContentChild). -
- - ### Binding target An element property between enclosing square brackets identifies the target property. The target property in the following code is the image element's `src` property. - - - - Some people prefer the `bind-` prefix alternative, known as the *canonical form*: - - - - The target name is always the name of a property, even when it appears to be the name of something else. You see `src` and may think it's the name of an attribute. No. It's the name of an image element property. @@ -926,26 +653,17 @@ Element properties may be the more common targets, but Angular looks first to see if the name is a property of a known directive, as it is in the following example: - - - -
- - Technically, Angular is matching the name to a directive [input](guide/template-syntax#inputs-outputs), one of the property names listed in the directive's `inputs` array or a property decorated with `@Input()`. Such inputs map to the directive's own properties. -
- - If the name fails to match a property of a known directive or element, Angular reports an “unknown directive” error. ### Avoid side effects @@ -971,13 +689,9 @@ Return an object if the target property expects an object. The `hero` property of the `HeroDetail` component expects a `Hero` object, which is exactly what you're sending in the property binding: - - - - ### Remember the brackets The brackets tell Angular to evaluate the template expression. @@ -987,16 +701,11 @@ It does *not* evaluate the string! Don't make the following mistake: - - - - {@a one-time-initialization} - ### One-time string initialization You *should* omit the brackets when all of the following are true: @@ -1010,13 +719,9 @@ just as well for directive and component property initialization. The following example initializes the `prefix` property of the `HeroDetailComponent` to a fixed string, not a template expression. Angular sets it and forgets about it. - - - - The `[hero]` binding, on the other hand, remains a live binding to the component's `currentHero` property. {@a property-binding-or-interpolation} @@ -1026,13 +731,9 @@ The `[hero]` binding, on the other hand, remains a live binding to the component You often have a choice between interpolation and property binding. The following binding pairs do the same thing: - - - - _Interpolation_ is a convenient alternative to _property binding_ in many cases. When rendering data values as strings, there is no technical reason to prefer one form to the other. @@ -1042,53 +743,34 @@ both conforms to the rules and feels most natural for the task at hand. When setting an element property to a non-string data value, you must use _property binding_. - #### Content security Imagine the following *malicious content*. - - - - Fortunately, Angular data binding is on alert for dangerous HTML. It [*sanitizes*](guide/security#sanitization-and-security-contexts) the values before displaying them. It **will not** allow HTML with script tags to leak into the browser, neither with interpolation nor property binding. - - - - Interpolation handles the script tags differently than property binding but both approaches render the content harmlessly. -
evil title made safe
- - -

- back to top -

- - +back to top
- - {@a other-bindings} - ## Attribute, class, and style bindings The template syntax provides specialized one-way bindings for scenarios less well suited to property binding. @@ -1097,19 +779,13 @@ The template syntax provides specialized one-way bindings for scenarios less wel You can set the value of an attribute directly with an **attribute binding**. -
- - This is the only exception to the rule that a binding sets a target property. This is the only binding that creates and sets an attribute. -
- - This guide stresses repeatedly that setting an element property with a property binding is always preferred to setting the attribute with a string. Why does Angular offer attribute binding? @@ -1123,25 +799,17 @@ There are no property targets to bind to. This fact becomes painfully obvious when you write something like this. - <tr><td colspan="{{1 + 1}}">Three-Four</td></tr> - - - And you get this error: - Template parse errors: Can't bind to 'colspan' since it isn't a known native property - - - As the message says, the `` element does not have a `colspan` property. It has the "colspan" *attribute*, but interpolation and property binding can set only *properties*, not attributes. @@ -1155,13 +823,9 @@ You then set the attribute value, using an expression that resolves to a string. Bind `[attr.colspan]` to a calculated value: - - - - Here's how the table renders: @@ -1172,17 +836,13 @@ Here's how the table renders: One of the primary use cases for attribute binding is to set ARIA attributes, as in this example: - - back to top
- - ### Class binding You can add and remove CSS class names from an element's `class` attribute with @@ -1195,49 +855,32 @@ optionally followed by a dot (`.`) and the name of a CSS class: `[class.class-na The following examples show how to add and remove the application's "special" class with class bindings. Here's how to set the attribute without binding: - - - - You can replace that with a binding to a string of the desired class names; this is an all-or-nothing, replacement binding. - - - - Finally, you can bind to a specific class name. Angular adds the class when the template expression evaluates to truthy. It removes the class when the expression is falsy. - - - -
- - While this is a fine way to toggle a single class name, the [NgClass directive](guide/template-syntax#ngClass) is usually preferred when managing multiple class names at the same time. -
back to top
- - ### Style binding You can set inline styles with a **style binding**. @@ -1246,55 +889,36 @@ Style binding syntax resembles property binding. Instead of an element property between brackets, start with the prefix `style`, followed by a dot (`.`) and the name of a CSS style property: `[style.style-property]`. - - - - Some style binding styles have a unit extension. The following example conditionally sets the font size in “em” and “%” units . - - - -
- - While this is a fine way to set a single style, the [NgStyle directive](guide/template-syntax#ngStyle) is generally preferred when setting several inline styles at the same time. -
- -
- - Note that a _style property_ name can be written in either [dash-case](guide/glossary#dash-case), as shown above, or [camelCase](guide/glossary#camelcase), such as `fontSize`. -
back to top
- - {@a event-binding} - ## Event binding ( (event) ) The bindings directives you've met so far flow data in one direction: **from a component to an element**. @@ -1313,56 +937,35 @@ within parentheses on the left of an equal sign, and a quoted The following event binding listens for the button's click events, calling the component's `onSave()` method whenever a click occurs: - - - - ### Target event A **name between parentheses** — for example, `(click)` — identifies the target event. In the following example, the target is the button's click event. - - - - Some people prefer the `on-` prefix alternative, known as the **canonical form**: - - - - Element events may be the more common targets, but Angular looks first to see if the name matches an event property of a known directive, as it does in the following example: - - - -
- - The `myClick` directive is further described in the section on [aliasing input/output properties](guide/template-syntax#aliasing-io). -
- - If the name fails to match an element event or an output property of a known directive, Angular reports an “unknown directive” error. @@ -1385,13 +988,9 @@ with properties such as `target` and `target.value`. Consider this example: - - - - This code sets the input box `value` property by binding to the `name` property. To listen for changes to the value, the code binds to the input box's `input` event. When the user makes changes, the `input` event is raised, and the binding executes @@ -1402,13 +1001,10 @@ To update the `name` property, the changed text is retrieved by following the pa If the event belongs to a directive (recall that components are directives), `$event` has whatever shape the directive decides to produce. - {@a eventemitter} - {@a custom-event} - ### Custom events with EventEmitter Directives typically raise custom events with an Angular [EventEmitter](api/core/EventEmitter). @@ -1422,32 +1018,21 @@ The best it can do is raise an event reporting the user's delete request. Here are the pertinent excerpts from that `HeroDetailComponent`: - - - - - - - The component defines a `deleteRequest` property that returns an `EventEmitter`. When the user clicks *delete*, the component invokes the `delete()` method, telling the `EventEmitter` to emit a `Hero` object. Now imagine a hosting parent component that binds to the `HeroDetailComponent`'s `deleteRequest` event. - - - - When the `deleteRequest` event fires, Angular calls the parent component's `deleteHero` method, passing the *hero-to-delete* (emitted by `HeroDetail`) in the `$event` variable. @@ -1459,15 +1044,13 @@ Template statement side effects are not just OK, but expected. Deleting the hero updates the model, perhaps triggering other changes including queries and saves to a remote server. These changes percolate through the system and are ultimately displayed in this and other views. + back to top
- - {@a two-way} - ## Two-way binding ( [(...)] ) You often want to both display a data property and update that property when the user makes changes. @@ -1479,49 +1062,33 @@ Angular offers a special _two-way data binding_ syntax for this purpose, **`[(x) The `[(x)]` syntax combines the brackets of _property binding_, `[x]`, with the parentheses of _event binding_, `(x)`. -
- -
[( )] = banana in a box
- - Visualize a *banana in a box* to remember that the parentheses go _inside_ the brackets. -
- - The `[(x)]` syntax is easy to demonstrate when the element has a settable property called `x` and a corresponding event named `xChange`. Here's a `SizerComponent` that fits the pattern. It has a `size` value property and a companion `sizeChange` event: - - - - The initial `size` is an input value from a property binding. Clicking the buttons increases or decreases the `size`, within min/max values constraints, and then raises (_emits_) the `sizeChange` event with the adjusted size. Here's an example in which the `AppComponent.fontSizePx` is two-way bound to the `SizerComponent`: - - - - The `AppComponent.fontSizePx` establishes the initial `SizerComponent.size` value. Clicking the buttons updates the `AppComponent.fontSizePx` via the two-way binding. The revised `AppComponent.fontSizePx` value flows through to the _style_ binding, @@ -1530,13 +1097,9 @@ making the displayed text bigger or smaller. The two-way binding syntax is really just syntactic sugar for a _property_ binding and an _event_ binding. Angular _desugars_ the `SizerComponent` binding into this: - - - - The `$event` variable contains the payload of the `SizerComponent.sizeChange` event. Angular assigns the `$event` value to the `AppComponent.fontSizePx` when the user clicks the buttons. @@ -1546,15 +1109,13 @@ It would be convenient to use two-way binding with HTML form elements like `back to top
- - {@a directives} - ## Built-in directives Earlier versions of Angular included over seventy built-in directives. @@ -1565,13 +1126,9 @@ You don't need many of those directives in Angular. You can often achieve the same results with the more capable and expressive Angular binding system. Why create a directive to handle a click when you can write a simple binding such as this? - - - - You still benefit from directives that simplify complex tasks. Angular still ships with built-in directives; just not as many. You'll write your own directives, just not as many. @@ -1579,14 +1136,10 @@ You'll write your own directives, just not as many. This segment reviews some of the most frequently used built-in directives, classified as either [_attribute_ directives](guide/template-syntax#attribute-directives) or [_structural_ directives](guide/template-syntax#structural-directives). -
- - {@a attribute-directives} - ## Built-in _attribute_ directives Attribute directives listen to and modify the behavior of @@ -1605,11 +1158,8 @@ This section is an introduction to the most commonly used attribute directives:
- - {@a ngClass} - ### NgClass You typically control how elements appear @@ -1618,58 +1168,39 @@ You can bind to the `ngClass` to add or remove several classes simultaneously. A [class binding](guide/template-syntax#class-binding) is a good way to add or remove a *single* class. - - - - To add or remove *many* CSS classes at the same time, the `NgClass` directive may be the better choice. Try binding `ngClass` to a key:value control object. Each key of the object is a CSS class name; its value is `true` if the class should be added, `false` if it should be removed. - Consider a `setCurrentClasses` component method that sets a component property, `currentClasses` with an object that adds or removes three classes based on the `true`/`false` state of three other component properties: - - - - Adding an `ngClass` property binding to `currentClasses` sets the element's classes accordingly: - - - -
- - It's up to you to call `setCurrentClassess()`, both initially and when the dependent properties change. -
back to top
- - {@a ngStyle} - ### NgStyle You can set inline styles dynamically, based on the state of the component. @@ -1677,13 +1208,9 @@ With `NgStyle` you can set many inline styles simultaneously. A [style binding](guide/template-syntax#style-binding) is an easy way to set a *single* style value. - - - - To set *many* inline styles at the same time, the `NgStyle` directive may be the better choice. Try binding `ngStyle` to a key:value control object. @@ -1692,40 +1219,26 @@ Each key of the object is a style name; its value is whatever is appropriate for Consider a `setCurrentStyles` component method that sets a component property, `currentStyles` with an object that defines three styles, based on the state of three other component propertes: - - - - Adding an `ngStyle` property binding to `currentStyles` sets the element's styles accordingly: - - - -
- - It's up to you to call `setCurrentStyles()`, both initially and when the dependent properties change. -
back to top
- - {@a ngModel} - ### NgModel - Two-way binding to form elements with [(ngModel)] When developing data entry forms, you often both display a data property and @@ -1733,13 +1246,9 @@ update that property when the user makes changes. Two-way data binding with the `NgModel` directive makes that easy. Here's an example: - - - - #### _FormsModule_ is required to use _ngModel_ Before using the `ngModel` directive in a two-way data binding, @@ -1749,43 +1258,29 @@ Learn more about the `FormsModule` and `ngModel` in the Here's how to import the `FormsModule` to make `[(ngModel)]` available. - - - - #### Inside [(ngModel)] Looking back at the `name` binding, note that you could have achieved the same result with separate bindings to the `` element's `value` property and `input` event. - - - - That's cumbersome. Who can remember which element property to set and which element event emits user changes? How do you extract the currently displayed text from the input box so you can update the data property? Who wants to look that up each time? That `ngModel` directive hides these onerous details behind its own `ngModel` input and `ngModelChange` output properties. - - - -
- - The `ngModel` data property sets the element's value property and the `ngModelChange` event property listens for changes to the element's value. @@ -1805,24 +1300,17 @@ can name the value and event properties to suit Angular's basic [two-way binding syntax](guide/template-syntax#two-way) and skip `NgModel` altogether. The [`sizer` shown above](guide/template-syntax#two-way) is an example of this technique. -
- - Separate `ngModel` bindings is an improvement over binding to the element's native properties. You can do better. You shouldn't have to mention the data property twice. Angular should be able to capture the component's data property and set it with a single declaration, which it can with the `[(ngModel)]` syntax: - - - - Is `[(ngModel)]` all you need? Is there ever a reason to fall back to its expanded form? The `[(ngModel)]` syntax can only _set_ a data-bound property. @@ -1830,35 +1318,21 @@ If you need to do something more or something different, you can write the expan The following contrived example forces the input value to uppercase: - - - - Here are all variations in action, including the uppercase version: -
NgModel variations
- - -

- back to top -

- - +back to top
- - {@a structural-directives} - ## Built-in _structural_ directives Structural directives are responsible for HTML layout. @@ -1882,38 +1356,25 @@ _This_ section is an introduction to the common structural directives: * [`NgFor`](guide/template-syntax#ngFor) - repeat a template for each item in a list * [`NgSwitch`](guide/template-syntax#ngSwitch) - a set of directives that switch among alternative views -
- - {@a ngIf} - ### NgIf You can add or remove an element from the DOM by applying an `NgIf` directive to that element (called the _host elment_). Bind the directive to a condition expression like `isActive` in this example. - - - -
- - Don't forget the asterisk (`*`) in front of `ngIf`. -
- - When the `isActive` expression returns a truthy value, `NgIf` adds the `HeroDetailComponent` to the DOM. When the expression is falsy, `NgIf` removes the `HeroDetailComponent` from the DOM, destroying that component and all of its sub-components. @@ -1923,13 +1384,9 @@ from the DOM, destroying that component and all of its sub-components. You can control the visibility of an element with a [class](guide/template-syntax#class-binding) or [style](guide/template-syntax#style-binding) binding: - - - - Hiding an element is quite different from removing an element with `NgIf`. When you hide an element, that element and all of its descendents remain in the DOM. @@ -1955,33 +1412,23 @@ Here we see `NgIf` guarding two `
`s. The `currentHero` name will appear only when there is a `currentHero`. The `nullHero` will never be displayed. - - - -
- - See also the [_safe navigation operator_](guide/template-syntax#safe-navigation-operator "Safe naviation operator (?.)") described below. -
back to top
- - {@a ngFor} - ### NgFor `NgFor` is a _repeater_ directive — a way to present a list of items. @@ -1990,39 +1437,24 @@ You tell Angular to use that block as a template for rendering each item in the Here is an example of `NgFor` applied to a simple `
`: - - - - You can also apply an `NgFor` to a component element, as in this example: - - - -
- - Don't forget the asterisk (`*`) in front of `ngFor`. -
- - The text assigned to `*ngFor` is the instruction that guides the repeater process. - {@a microsyntax} - #### *ngFor microsyntax The string assigned to `*ngFor` is not a [template expression](guide/template-syntax#template-expressions). @@ -2038,13 +1470,10 @@ in the list. Learn about the _microsyntax_ in the [_Structural Directives_](guide/structural-directives#microsyntax) guide. - {@a template-input-variable} - {@a template-input-variables} - ### Template input variables The `let` keyword before `hero` creates a _template input variable_ called `hero`. @@ -2056,13 +1485,9 @@ You reference the `hero` input variable within the `ngFor` host element Here it is referenced first in an interpolation and then passed in a binding to the `hero` property of the `` component. - - - - Learn more about _template input variables_ in the [_Structural Directives_](guide/structural-directives#template-input-variable) guide. @@ -2073,28 +1498,18 @@ You can capture the `index` in a template input variable and use it in the templ The next example captures the `index` in a variable named `i` and displays it with the hero name like this. - - - -
- - Learn about the other `NgFor` context values such as `last`, `even`, and `odd` in the [NgFor API reference](api/common/NgFor). -
- - {@a trackBy} - #### *ngFor with _trackBy_ The `NgFor` directive may perform poorly, especially with large lists. @@ -2111,22 +1526,14 @@ Angular can avoid this churn with `trackBy`. Add a method to the component that returns the value `NgFor` _should_ track. In this case, that value is the hero's `id`. - - - - In the microsyntax expression, set `trackBy` to this method. - - - - Here is an illustration of the _trackBy_ effect. "Reset heroes" creates new heroes with the same `hero.id`s. "Change ids" creates new heroes with new `hero.id`s. @@ -2134,26 +1541,16 @@ Here is an illustration of the _trackBy_ effect. * With no `trackBy`, both buttons trigger complete DOM element replacement. * With `trackBy`, only changing the `id` triggers element replacement. -
trackBy
- - -

- back to top -

- - +back to top
- - {@a ngSwitch} - ### The _NgSwitch_ directives *NgSwitch* is like the JavaScript `switch` statement. @@ -2163,19 +1560,13 @@ Angular puts only the *selected* element into the DOM. *NgSwitch* is actually a set of three, cooperating directives: `NgSwitch`, `NgSwitchCase`, and `NgSwitchDefault` as seen in this example. - - - -
trackBy
- - `NgSwitch` is the controller directive. Bind it to an expression that returns the *switch value*. The `emotion` value in this example is a string, but the switch value can be of any type. @@ -2199,29 +1590,21 @@ which is bound to the `currentHero` of the parent component. Switch directives work as well with native elements and web components too. For example, you could replace the `` switch case with the following. - - back to top
- - {@a template-reference-variable} - {@a ref-vars} - {@a ref-var} - ## Template reference variables ( #var ) - A **template reference variable** is often a reference to a DOM element within a template. It can also be a reference to an Angular component or directive or a web component. @@ -2229,25 +1612,17 @@ It can also be a reference to an Angular component or directive or a Use the hash symbol (#) to declare a reference variable. The `#phone` declares a `phone` variable on an `` element. - - - - You can refer to a template reference variable _anywhere_ in the template. The `phone` variable declared on this `` is consumed in a `