docs(aio): move cookbooks into guide

Also update all docs with migrated versions from latest angular.io

Fixes #14941
This commit is contained in:
Peter Bacon Darwin 2017-03-11 13:44:25 +00:00 committed by Chuck Jazdzewski
parent 6497633529
commit 1847550ad1
36 changed files with 1207 additions and 907 deletions

View File

@ -896,7 +896,7 @@ For more information on pipes, see [Pipes](../guide/pipes.html).
</code-example>
Displays the collection in the order specified by the expression.
In this example, the movie title orders the movieList.
In this example, the movie title orders the `movieList`.
</td>

View File

@ -2,7 +2,7 @@
Ahead-of-Time Compilation
@intro
Learn how to use Ahead-of-time compilation
Learn how to use Ahead-of-time compilation.
@description
This cookbook describes how to radically improve performance by compiling _Ahead of Time_ (AOT)

View File

@ -2,7 +2,7 @@
Architecture Overview
@intro
The basic building blocks of Angular applications
The basic building blocks of Angular applications.
@description
You write Angular applications by composing HTML *templates* with Angularized markup,

View File

@ -9,7 +9,6 @@ An **Attribute** directive changes the appearance or behavior of a DOM element.
# Contents
* [Directives overview](#directive-overview)
* [Build a simple attribute directive](#write-directive)
* [Apply the attribute directive to an element in a template](#apply-directive)
@ -19,9 +18,6 @@ An **Attribute** directive changes the appearance or behavior of a DOM element.
Try the <live-example title="Attribute Directive example"></live-example>.
{@a directive-overview}
## Directives overview
There are three kinds of directives in Angular:
@ -38,13 +34,12 @@ Two examples are [NgFor](template-syntax.html#ngFor) and [NgIf](template-syntax.
Learn about them in the [Structural Directives](structural-directives.html) guide.
*Attribute directives* are used as attributes of elements.
The built-in [NgStyle](template-syntax.html#ngStyle) directive in the [Template Syntax](template-syntax.html) guide, for example,
The built-in [NgStyle](template-syntax.html#ngStyle) directive in the
[Template Syntax](template-syntax.html) guide, for example,
can change several element styles at the same time.
{@a write-directive}
## Build a simple attribute directive
An attribute directive minimally requires building a controller class annotated with
`@Directive`, which specifies the selector that identifies
the attribute.
@ -53,35 +48,45 @@ The controller class implements the desired directive behavior.
This page demonstrates building a simple _myHighlight_ attribute
directive to set an element's background color
when the user hovers over that element. You can apply it like this:
{@example 'attribute-directives/ts/src/app/app.component.1.html' region='applied'}
### Write the directive code
Follow the [setup](setup.html) instructions for creating a new local project
named <span ngio-ex>attribute-directives</span>.
Create the following source file in `src/app` with the following code:
Create the following source file in the indicated folder:
{@example 'attribute-directives/ts/src/app/highlight.directive.1.ts'}
The `import` statement specifies symbols from the Angular `core`:
1. `Directive` provides the functionality of the `@Directive` decorator.
1. `ElementRef` [injects](dependency-injection.html) into the directive's constructor
so the code can access the DOM element.
1. `Input` allows data to flow from the binding expression into the directive.
Next, the `@Directive` decorator function contains the directive metadata in a configuration object
as an argument.
`@Directive` requires a CSS selector to identify
the HTML in the template that is associated with the directive.
The [CSS selector for an attribute](https://developer.mozilla.org/en-US/docs/Web/CSS/Attribute_selectors)
is the attribute name in square brackets.
Here, the directive's selector is `[myHighlight]`.
Angular locates all elements in the template that have an attribute named `myHighlight`.
### Why not call it "highlight"?
Though *highlight* is a more concise name than *myHighlight* and would work,
a best practice is to prefix selector names to ensure
they don't conflict with standard HTML attributes.
they don't conflict with standard HTML attributes.
This also reduces the risk of colliding with third-party directive names.
Make sure you do **not** prefix the `highlight` directive name with **`ng`** because
that prefix is reserved for Angular and using it could cause bugs that are difficult to diagnose. For a simple demo, the short prefix, `my`, helps distinguish your custom directive.
<p>
After the <code> @Directive </code> metadata comes the directive's controller class, called <code> HighlightDirective </code> , which contains the logic for the directive.
</p>
that prefix is reserved for Angular and using it could cause bugs that are difficult to diagnose.
For a simple demo, the short prefix, `my`, helps distinguish your custom directive.
After the `@Directive` metadata comes the directive's controller class,
called `HighlightDirective`, which contains the logic for the directive.
<span if-docs="ts">Exporting `HighlightDirective` makes it accessible to other components.</span>
Angular creates a new instance of the directive's controller class for
each matching element, injecting an Angular `ElementRef`
@ -89,29 +94,28 @@ into the constructor.
`ElementRef` is a service that grants direct access to the DOM element
through its `nativeElement` property.
{@a apply-directive}
## Apply the attribute directive
To use the new `HighlightDirective`, create a template that
applies the directive as an attribute to a paragraph (`<p>`) element.
In Angular terms, the `<p>` element is the attribute **host**.
<p>
Put the template in its own <code> </code> file that looks like this:
</p>
Put the template in its own <span ngio-ex>app.component.html</span>
file that looks like this:
{@example 'attribute-directives/ts/src/app/app.component.1.html'}
Now reference this template in the `AppComponent`:
{@example 'attribute-directives/ts/src/app/app.component.ts'}
Next, add an `import` statement to fetch the `Highlight` directive and
add that class to the `declarations` NgModule metadata. This way Angular
recognizes the directive when it encounters `myHighlight` in the template.
{@example 'attribute-directives/ts/src/app/app.module.ts'}
Now when the app runs, the `myHighlight` directive highlights the paragraph text.
@ -123,8 +127,10 @@ Now when the app runs, the `myHighlight` directive highlights the paragraph text
### Your directive isn't working?
Did you remember to add the directive to the `declarations` attribute of `@NgModule`? It is easy to forget!
Did you remember to add the directive to the `declarations` attribute of `@NgModule`?
It is easy to forget!
Open the console in the browser tools and look for an error like this:
<code-example format="nocode">
EXCEPTION: Template parse errors:
Can't bind to 'myHighlight' since it isn't a known property of 'p'.
@ -140,9 +146,6 @@ It created an instance of the `HighlightDirective` class and
injected a reference to the `<p>` element into the directive's constructor
which sets the `<p>` element's background style to yellow.
{@a respond-to-user}
## Respond to user-initiated events
Currently, `myHighlight` simply sets an element color.
@ -152,14 +155,10 @@ and respond by setting or clearing the highlight color.
Begin by adding `HostListener` to the list of imported symbols;
add the `Input` symbol as well because you'll need it soon.
{@example 'attribute-directives/ts/src/app/highlight.directive.ts' region='imports'}
Then add two eventhandlers that respond when the mouse enters or leaves, each adorned by the `HostListener` !{_decorator}.
{@example 'attribute-directives/ts/src/app/highlight.directive.2.ts' region='mouse-methods'}
The `@HostListener` !{_decorator} lets you subscribe to events of the DOM element that hosts an attribute directive, the `<p>` in this case.
Then add two eventhandlers that respond when the mouse enters or leaves,
each adorned by the `HostListener` !{_decorator}.
The `@HostListener` !{_decorator} lets you subscribe to events of the DOM
element that hosts an attribute directive, the `<p>` in this case.
Of course you could reach into the DOM with standard JavaScript and and attach event listeners manually.
There are at least three problems with _that_ approach:
@ -169,24 +168,19 @@ There are at least three problems with _that_ approach:
1. Talking to DOM API directly isn't a best practice.
The handlers delegate to a helper method that sets the color on the DOM element, `#{_priv}el`,
which you declare and initialize in the constructor.
{@example 'attribute-directives/ts/src/app/highlight.directive.2.ts' region='ctor'}
Here's the updated directive in full:
{@example 'attribute-directives/ts/src/app/highlight.directive.2.ts'}
Run the app and confirm that the background color appears when the mouse hovers over the `p` and
disappears as it moves out.
Run the app and confirm that the background color appears when
the mouse hovers over the `p` and disappears as it moves out.
<figure class='image-display'>
<img src="assets/images/devguide/attribute-directives/highlight-directive-anim.gif" alt="Second Highlight"> </img>
</figure>
{@a bindings}
## Pass values into the directive with an _@Input_ data binding
Currently the highlight color is hard-coded _within_ the directive. That's inflexible.
@ -194,9 +188,6 @@ In this section, you give the developer the power to set the highlight color whi
Start by adding a `highlightColor` property to the directive class like this:
{@example 'attribute-directives/ts/src/app/highlight.directive.2.ts' region='color'}
{@a input}
### Binding to an _@Input_ property
@ -207,30 +198,15 @@ It's called an *input* property because data flows from the binding expression _
Without that input metadata, Angular rejects the binding; see [below](#why-input "Why add @Input?") for more about that.
Try it by adding the following directive binding variations to the `AppComponent` template:
{@example 'attribute-directives/ts/src/app/app.component.1.html' region='color-1'}
Add a `color` property to the `AppComponent`.
{@example 'attribute-directives/ts/src/app/app.component.1.ts' region='class'}
Let it control the highlight color with a property binding.
{@example 'attribute-directives/ts/src/app/app.component.1.html' region='color-2'}
That's good, but it would be nice to _simultaneously_ apply the directive and set the color _in the same attribute_ like this.
{@example 'attribute-directives/ts/src/app/app.component.html' region='color'}
The `[myHighlight]` attribute binding both applies the highlighting directive to the `<p>` element
and sets the directive's highlight color with a property binding.
You're re-using the directive's attribute selector (`[myHighlight]`) to do both jobs.
That's a crisp, compact syntax.
You'll have to rename the directive's `highlightColor` property to `myHighlight` because that's now the color property binding name.
{@example 'attribute-directives/ts/src/app/highlight.directive.2.ts' region='color-2'}
This is disagreeable. The word, `myHighlight`, is a terrible property name and it doesn't convey the property's intent.
@ -244,60 +220,54 @@ _Inside_ the directive the property is known as `highlightColor`.
_Outside_ the directive, where you bind to it, it's known as `myHighlight`.
You get the best of both worlds: the property name you want and the binding syntax you want:
{@example 'attribute-directives/ts/src/app/app.component.html' region='color'}
Now that you're binding to `highlightColor`, modify the `onMouseEnter()` method to use it.
If someone neglects to bind to `highlightColor`, highlight in "red" by default.
If someone neglects to bind to `highlightColor`, highlight in red:
Here's the latest version of the directive class.
## Write a harness to try it
{@example 'attribute-directives/ts/src/app/highlight.directive.3.ts' region='mouse-enter'}
Here's the latest version of the directive class.## Write a harness to try itIt may be difficult to imagine how this directive actually works.
It may be difficult to imagine how this directive actually works.
In this section, you'll turn `AppComponent` into a harness that
lets you pick the highlight color with a radio button and bind your color choice to the directive.
Update `app.component.html` as follows:
Revise the `AppComponent.color` so that it has no initial value.Here is the harness and directive in action.
Update <span ngio-ex>app.component.html</span> as follows:
Revise the `AppComponent.color` so that it has no initial value.
Here are the harness and directive in action.
<figure class='image-display'>
<img src="assets/images/devguide/attribute-directives/highlight-directive-v2-anim.gif" alt="Highlight v.2"> </img>
</figure>
{@a second-property}
## Bind to a second property
This highlight directive has a single customizable property. In a real app, it may need more.
At the moment, the default color&mdash;the color that prevails until
the user picks a highlight color&mdash;is hard-coded as "red".
At the moment, the default color&mdash;the color that prevails until
the user picks a highlight color&mdash;is hard-coded as "red".
Let the template developer set the default color.
Add a second **input** property to `HighlightDirective` called `defaultColor`:Revise the directive's `onMouseEnter` so that it first tries to highlight with the `highlightColor`,
Add a second **input** property to `HighlightDirective` called `defaultColor`:
Revise the directive's `onMouseEnter` so that it first tries to highlight with the `highlightColor`,
then with the `defaultColor`, and falls back to "red" if both properties are undefined.
{@example 'attribute-directives/ts/src/app/highlight.directive.ts' region='mouse-enter'}
How do you bind to a second property when you're already binding to the `myHighlight` attribute name?
As with components, you can add as many directive property bindings as you need by stringing them along in the template.
The developer should be able to write the following template HTML to both bind to the `AppComponent.color`
and fall back to "violet" as the default color.
{@example 'attribute-directives/ts/src/app/app.component.html' region='defaultColor'}
Angular knows that the `defaultColor` binding belongs to the `HighlightDirective`
because you made it _public_ with the `@Input` !{_decorator}.
Here's how the harness should work when you're done coding.
<figure class='image-display'>
<img src="assets/images/devguide/attribute-directives/highlight-directive-final-anim.gif" alt="Final Highlight"> </img>
</figure>
## Summary
This page covered how to:
- [Build an **attribute directive**](#write-directive) that modifies the behavior of an element.
- [Apply the directive](#apply-directive) to an element in a template.
- [Respond to **events**](#respond-to-user) that change the directive's behavior.
@ -341,20 +311,11 @@ The final source code follows:
You can also experience and download the <live-example title="Attribute Directive example"></live-example>.
{@a why-input}
### Appendix: Why add _@Input_?
In this demo, the `hightlightColor` property is an ***input*** property of
the `HighlightDirective`. You've seen it applied without an alias:
{@example 'attribute-directives/ts/src/app/highlight.directive.2.ts' region='color'}
You've seen it with an alias:
{@example 'attribute-directives/ts/src/app/highlight.directive.ts' region='color'}
Either way, the `@Input` !{_decorator} tells Angular that this property is
_public_ and available for binding by a parent component.
Without `@Input`, Angular refuses to bind to the property.
@ -377,20 +338,17 @@ Only then can it be bound by some other component or directive.
You can tell if `@Input` is needed by the position of the property name in a binding.
* When it appears in the template expression to the ***right*** of the equals (=),
it belongs to the template's component and does not require the `@Input` !{_decorator}.
it belongs to the template's component and does not require the `@Input` !{_decorator}.
* When it appears in **square brackets** ([ ]) to the **left** of the equals (=),
the property belongs to some _other_ component or directive;
that property must be adorned with the `@Input` !{_decorator}.
the property belongs to some _other_ component or directive;
that property must be adorned with the `@Input` !{_decorator}.
Now apply that reasoning to the following example:
{@example 'attribute-directives/ts/src/app/app.component.html' region='color'}
* The `color` property in the expression on the right belongs to the template's component.
The template and its component trust each other.
The `color` property doesn't require the `@Input` !{_decorator}.
The template and its component trust each other.
The `color` property doesn't require the `@Input` !{_decorator}.
* The `myHighlight` property on the left refers to an _aliased_ property of the `MyHighlightDirective`,
not a property of the template's component. There are trust issues.
Therefore, the directive property must carry the `@Input` !{_decorator}.
* The `myHighlight` property on the left refers to an _aliased_ property of the `HighlightDirective`,
not a property of the template's component. There are trust issues.
Therefore, the directive property must carry the `@Input` !{_decorator}.

View File

@ -244,7 +244,7 @@ using <a href="https://saucelabs.com/" target="_blank">SauceLabs</a> and
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") on the host web page (`index.html`)
You can compensate by loading polyfill scripts ("polyfills") on the host web page (`index.html`)
that implement missing features in JavaScript.
{@example 'quickstart/ts/src/index.html' region='polyfills'}
@ -252,12 +252,12 @@ that implement missing features in JavaScript.
A particular browser may require at least one polyfill to run _any_ Angular application.
You may need additional polyfills for specific features.
The tables below will help you determine which polyfills to load, depending on the browsers you target and the features you use.
The tables below can help you determine which polyfills to load, depending on the browsers you target and the features you use.
~~~ {.alert.is-important}
The suggested polyfills are the ones we know will run full Angular applications.
The suggested polyfills are the ones that run full Angular applications.
You may 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.
@ -457,7 +457,7 @@ Below are the polyfills which are used to test the framework itself. They are a
<th>
Licence
License
</th>
@ -517,7 +517,7 @@ Below are the polyfills which are used to test the framework itself. They are a
<td>
MIT / Unicode licence
MIT / Unicode license
</td>
@ -611,4 +611,5 @@ Below are the polyfills which are used to test the framework itself. They are a
</table>
\* Figures are for minified and gzipped code, computed with the <a href="http://closure-compiler.appspot.com/home" target="_blank">closure compiler</a>
\* Figures are for minified and gzipped code,
computed with the <a href="http://closure-compiler.appspot.com/home" target="_blank">closure compiler</a>.

View File

@ -2,7 +2,7 @@
Dependency Injection
@intro
Techniques for Dependency Injection
Techniques for Dependency Injection.
@description
Dependency Injection is a powerful pattern for managing code dependencies.
@ -136,7 +136,7 @@ Technically, the `@Injectable()`decorator is only _required_ for a service class
The `LoggerService` doesn't depend on anything. The logger would work if we omitted `@Injectable()`
and the generated code would be slightly smaller.
But the service would break the moment we gave it a dependency and we'd have to go back and
But the service would break the moment we gave it a dependency and we'd have to go back
and add `@Injectable()` to fix it. We add `@Injectable()` from the start for the sake of consistency and to avoid future pain.
@ -362,7 +362,7 @@ Here's a typical example:
{@example 'cb-dependency-injection/ts/src/app/hero-bios.component.ts' region='ctor'}
Angular asks the injector for the service associated with the `LoggerService` and
Angular asks the injector for the service associated with the `LoggerService`
and assigns the returned value to the `logger` parameter.
Where did the injector get that value?

View File

@ -2,7 +2,7 @@
Cookbook
@intro
A collection of recipes for common Angular application scenarios
A collection of recipes for common Angular application scenarios.
@description
The *Cookbook* offers answers to common implementation questions.

View File

@ -19,12 +19,12 @@ Discusses `<ng-container>`.
Revised samples are more clear and cover all topics discussed.
## NEW: Samples re-structured with `src/` folder (2017-02-02)
All documentation samples have been realigned with the default folder structure of the angular-cli.
That's a step along the road to basing our sample in the angular-cli.
All documentation samples have been realigned with the default folder structure of the Angular CLI.
That's a step along the road to basing the sample in the Angular CLI.
But it's also good in its own right.
It helps clearly separate app code from setup and configuration files.
We've updated all samples with an `src/` folder at the project root.
All samples now have a `src/` folder at the project root.
The former `app/` folder moves under `src/`.
Read about moving your existing project to this structure in
<a href="https://github.com/angular/quickstart#updating-to-a-newer-version-of-the-quickstart-repo" target="_blank" target="Migrating samples/quickstart app to the src folder">
@ -50,24 +50,24 @@ The new [Deployment](deployment.html) guide describes techniques for putting you
It includes important advice on optimizing for production.
## Hierarchical Dependency Injection: refreshed (2017-01-13)
[Hierarchical Dependency Injection](hierarchical-dependency-injection.html) guide significantly revised.
Closes issue #3086
Revised samples are more clear and cover all topics discussed.
[Hierarchical Dependency Injection](hierarchical-dependency-injection.html) guide is significantly revised.
Closes issue #3086.
Revised samples are clearer and cover all topics discussed.
## Miscellaneous (2017-01-05)
* [Setup](setup.html) guide:
added (optional) instructions on how to remove _non-essential_ files.
* No longer consolidate RxJS operator imports in `rxjs-extensions` file; each file should import what it needs.
* All samples prepend template/style URLS URLs w/ `./` ... and so should you.
* All samples prepend template/style URLs with `./` as a best practice.
* [Style Guide](style-guide.html): copy edits and revised rules.
## Router: more detail (2016-12-21)
Added more information to the [Router](router.html) guide
including sections named outlets, wildcard routes, and preload strategies.
## Http: how to set default request headers (and other request options) (2016-12-14)
## HTTP: how to set default request headers (and other request options) (2016-12-14)
Added section on how to set default request headers (and other request options) to
[Http](server-communication.html#override-default-request-options) guide.
[HTTP](server-communication.html#override-default-request-options) guide.
## Testing: added component test plunkers (2016-12-02)
Added two plunkers that each test _one simple component_ so you can write a component test plunker of your own: <live-example name="setup" plnkr="quickstart-specs">one</live-example> for the QuickStart seed's `AppComponent` and <live-example name="testing" plnkr="banner-specs">another</live-example> for the Testing guide's `BannerComponent`.
@ -79,9 +79,9 @@ translation of alternative texts with `select`.
The sample demonstrates these features too.
## Testing: karma file updates (2016-11-30)
* karma.config + karma-test-shim can handle multiple spec source paths;
see quickstart issue: [angular/quickstart#294](https://github.com/angular/quickstart/issues/294)
* Displays Jasmine Runner output in the karma-launched browser
* `karma.config` + `karma-test-shim` can handle multiple spec source paths;
see quickstart issue: [angular/quickstart#294](https://github.com/angular/quickstart/issues/294).
* Displays Jasmine Runner output in the karma-launched browser.
## QuickStart Rewrite (2016-11-18)
The QuickStart is completely rewritten so that it actually is quick.
@ -91,7 +91,7 @@ by downloading (or cloning) the QuickStart github repository.
You are no longer asked to copy-and-paste code into setup files that were not explained anyway.
## Sync with Angular v.2.2.0 (2016-11-14)
Docs and code samples updated and tested with Angular v.2.2.0
Docs and code samples updated and tested with Angular v.2.2.0.
## UPDATE: NgUpgrade Guide for the AOT friendly _upgrade/static_ module (2016-11-14)
The updated [NgUpgrade Guide](upgrade.html) guide covers the
@ -101,20 +101,20 @@ facility for migrating from AngularJS to Angular.
The documentation for the version prior to v.2.2.0 has been removed.
## ES6 described in "TypeScript to JavaScript" (2016-11-14)
The updated "[TypeScript to JavaScript](../cookbook/ts-to-js.html)" cookbook
The updated [TypeScript to JavaScript](../cookbook/ts-to-js.html) cookbook
now explains how to write apps in ES6/7
by translating the common idioms in the TypeScript documentation examples
(and elsewhere on the web) to ES6/7 and ES5.
## Sync with Angular v.2.1.1 (2016-10-21)
Docs and code samples updated and tested with Angular v.2.1.0
Docs and code samples updated and tested with Angular v.2.1.1.
## npm _@types_ packages replace _typings_ (2016-10-20)
Documentation samples now get TypeScript type information for 3rd party libraries
from npm `@types` packages rather than with the _typings_ tooling.
The `typings.json` file is gone.
The "[AngularJS Upgrade](upgrade.html)" guide reflects this change.
The [AngularJS Upgrade](upgrade.html) guide reflects this change.
The `package.json` installs `@types/angular` and several `@types/angular-...`
packages in support of upgrade; these are not needed for pure Angular development.
@ -135,7 +135,7 @@ _before_ the user navigates to them for improved perceived performance.
New `:enter` and `:leave` aliases make animation more natural.
## Sync with Angular v.2.1.0 (2016-10-12)
Docs and code samples updated and tested with Angular v.2.1.0
Docs and code samples updated and tested with Angular v.2.1.0.
## NEW "Ahead of time (AOT) Compilation" cookbook (2016-10-11)
The NEW [Ahead of time (AOT) Compilation](../cookbook/aot-compiler.html) cookbook
@ -144,7 +144,7 @@ It demonstrates the basics with a QuickStart app
followed by the more advanced considerations of compiling and bundling the Tour of Heroes.
## Sync with Angular v.2.0.2 (2016-10-6)
Docs and code samples updated and tested with Angular v.2.0.2
Docs and code samples updated and tested with Angular v.2.0.2.
## "Routing and Navigation" guide with the _Router Module_ (2016-10-5)
The [Routing and Navigation](router.html) guide now locates route configuration
@ -171,16 +171,16 @@ The new "angular-in-memory-web-api" has new features.
## "Style Guide" with _NgModules_ (2016-09-27)
[StyleGuide](style-guide.html) explains our recommended conventions for Angular modules (NgModule).
[StyleGuide](style-guide.html) explains recommended conventions for Angular modules (NgModule).
Barrels now are far less useful and have been removed from the style guide;
they remain valuable but are not a matter of Angular style.
We also relaxed the rule that discouraged use of the `@Component.host` property.
Also relaxed the rule that discouraged use of the `@Component.host` property.
## _moduleId: module.id_ everywhere (2016-09-25)
Sample components that get their templates or styles with `templateUrl` or `styleUrls`
have been converted to _module-relative_ URLs.
We added the `moduleId: module.id` property-and-value to their `@Component` metadata.
Added the `moduleId: module.id` property-and-value to their `@Component` metadata.
This change is a requirement for compilation with AOT compiler when the app loads
modules with SystemJS as the samples currently do.

View File

@ -2,7 +2,7 @@
Component Interaction
@intro
Share information between different directives and components
Share information between different directives and components.
@description
<a id="top"></a>This cookbook contains recipes for common component communication scenarios
@ -118,7 +118,7 @@ the expected `ngOnChanges` calls and values:
<a id="child-to-parent"></a>## Parent listens for child event
The child component exposes an `EventEmitter` property with which it `emits`events when something happens.
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***,

View File

@ -100,7 +100,7 @@ For more information, see the [Template Syntax](./template-syntax.html#ngFor) pa
Notice the `hero` in the `ngFor` double-quoted instruction;
it is an example of a template input variable. Read
more about template input variables in the [microsyntax](./template-syntax.html#ngForMicrosyntax) section of
more about template input variables in the [microsyntax](./template-syntax.html#microsyntax) section of
the [Template Syntax](./template-syntax.html) page.
Angular duplicates the `<li>` for each item in the list, setting the `hero` variable

View File

@ -2,7 +2,7 @@
Dynamic Component Loader
@intro
Load components dynamically
Load components dynamically.
@description
Component templates are not always fixed. An application may need to load new components at runtime.

View File

@ -2,7 +2,7 @@
Dynamic Forms
@intro
Render dynamic forms with FormGroup
Render dynamic forms with FormGroup.
@description
We can't always justify the cost and time to build handcrafted forms,
@ -129,7 +129,7 @@ The `ngSwitch` determines which type of question to display.
In both components we're relying on Angular's **formGroup** to connect the template HTML to the
underlying control objects, populated from the question model with display and validation rules.
`formControlName` and `formGroup` are directives defined in `ReactiveFormsModule`. Our templates can can access these directives directly since we imported `ReactiveFormsModule` from `AppModule`.
`formControlName` and `formGroup` are directives defined in `ReactiveFormsModule`. Our templates can access these directives directly since we imported `ReactiveFormsModule` from `AppModule`.
<a id="questionnaire-metadata"></a>## Questionnaire data`DynamicFormComponent` expects the list of questions in the form of an array bound to `@Input() questions`.
The set of questions we have defined for the job application is returned from the `QuestionService`.

View File

@ -2,7 +2,7 @@
Form Validation
@intro
Validate user's form entries
Validate user's form entries.
@description
@ -258,7 +258,7 @@ At runtime, Angular interprets the template and derives its _form control model_
**Reactive Forms** takes a different approach.
You create the form control model in code. You write the template with form elements
and`form...` directives from the Angular `ReactiveFormsModule`.
and `form...` directives from the Angular `ReactiveFormsModule`.
At runtime, Angular binds the template elements to your control model based on your instructions.
This approach requires a bit more effort. *You have to write the control model and manage it*.
@ -365,7 +365,7 @@ Angular has stock validators that correspond to the standard HTML validation att
The `forbiddenNames` validator on the `"name"` control is a custom validator,
discussed in a separate [section below](#custom-validation).
Learn more about `FormBuilder` in a _forthcoming_ chapter on reactive forms.
Learn more about `FormBuilder` in the [Introduction to FormBuilder](../guide/reactive-forms.html#formbuilder) section of Reactive Forms guide.
#### Committing hero value changes
In two-way data binding, the user's changes flow automatically from the controls back to the data model properties.

View File

@ -2,5 +2,5 @@
Glossary
@intro
Brief definitions of the most important words in the Angular vocabulary
Brief definitions of the most important words in the Angular vocabulary.

View File

@ -41,7 +41,7 @@ open simultaneously.
<img src="assets/images/devguide/dependency-injection/component-hierarchy.png" alt="injector tree" width="600"> </img>
</figure>
### Injector bubbling
### Injector bubbling
When a component requests a dependency, Angular tries to satisfy that dependency with a provider registered in that component's own injector.
If the component's injector lacks the provider, it passes the request up to its parent component's injector.
@ -51,22 +51,24 @@ If it runs out of ancestors, Angular throws an error.
You can cap the bubbling. An intermediate component can declare that it is the "host" component.
The hunt for providers will climb no higher than the injector for that host component.
This a topic for another day.
This is a topic for another day.
### Re-providing a service at different levels
You can re-register a provider for a particular dependency token at multiple levels of the injector tree.
You don't *have* to re-register providers. You shouldn't do so unless you have a good reason.
You don't *have* to re-register providers. You shouldn't do so unless you have a good reason.
But you *can*.
As the resolution logic works upwards, the first provider encountered wins.
Thus, a provider in an intermediate injector intercepts a request for a service from something lower in the tree.
It effectively "reconfigures" and "shadows" a provider at a higher level in the tree.
If you only specify providers at the top level (typically the root `AppModule`), the tree of injectors appears to be flat.
If you only specify providers at the top level (typically the root `AppModule`), the tree of injectors appears to be flat.
All requests bubble up to the root <span if-docs="ts"><code>NgModule</code></span> injector that you configured with the `!{_bootstrapModule}` method.
## Component injectors
The ability to configure one or more providers at different levels opens up interesting and useful possibilities.
### Scenario: service isolation
Architectural reasons may lead you to restrict access to a service to the application domain where it belongs.
@ -74,57 +76,55 @@ Architectural reasons may lead you to restrict access to a service to the applic
The guide sample includes a `VillainsListComponent` that displays a list of villains.
It gets those villains from a `VillainsService`.
While you could provide `VillainsService` in the root `AppModule` (that's where you'll find the `HeroesService`),
While you _could_ provide `VillainsService` in the root `AppModule` (that's where you'll find the `HeroesService`),
that would make the `VillainsService` available everywhere in the application, including the _Hero_ workflows.
If you later modify the `VillainsService`, you could break something in a hero component somewhere.
That's not supposed to happen but the way you've provided the service creates that risk.
If you later modified the `VillainsService`, you could break something in a hero component somewhere.
That's not supposed to happen but providing the service in the root `AppModule` creates that risk.
Instead, provide the `VillainsService` in the `providers` metadata of the `VillainsListComponent` like this:
{@example 'hierarchical-dependency-injection/ts/src/app/villains-list.component.ts' region='metadata'}
By providing `VillainsService` in the `VillainsListComponent` metadata &mdash; and nowhere else &mdash;,
By providing `VillainsService` in the `VillainsListComponent` metadata and nowhere else,
the service becomes available only in the `VillainsListComponent` and its sub-component tree.
It's still a singleton, but it's a singleton that exist solely in the _villain_ domain.
You are confident that a hero component can't access it. You've reduced your exposure to error.
Now you know that a hero component can't access it. You've reduced your exposure to error.
### 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 several tax returns,
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.
To open a hero's tax return, the preparer clicks on a hero name, which opens a component for editing that return.
To open a hero's tax return, the preparer clicks on a hero name, which opens a component for editing that return.
Each selected hero tax return opens in its own component and multiple returns can be open at the same time.
Each tax return component
* 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.
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.
<figure class='image-display'>
<img src="assets/images/devguide/dependency-injection/hid-heroes-anim.gif" width="400" alt="Heroes in action"> </img>
</figure>
One might suppose that the `TaxReturnComponent` has logic to manage and restore changes.
That would be a pretty easy task for a simple hero tax return.
One might suppose that the `HeroTaxReturnComponent` has logic to manage and restore changes.
That would be a pretty easy task for a simple hero tax return.
In the real world, with a rich tax return data model, the change management would be tricky.
You might delegate that management to a helper service, as this example does.
Here is the `HeroTaxReturnService`.
Here is the `HeroTaxReturnService`.
It 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.
It also delegates to the application-wide singleton `HeroService`, which it gets by injection.
{@example 'hierarchical-dependency-injection/ts/src/app/hero-tax-return.service.ts'}
Here is the `HeroTaxReturnComponent` that makes use of it.
{@example 'hierarchical-dependency-injection/ts/src/app/hero-tax-return.component.ts'}
The _tax-return-to-edit_ arrives via the input property which is implemented with getters and setters.
@ -133,29 +133,25 @@ The getter always returns what that service says is the current state of the her
The component also asks the service to save and restore this tax return.
There'd be big trouble if _this_ service were an application-wide singleton.
Every component would share the same service instance.
Every component would share the same service instance.
Each component would overwrite the tax return that belonged to another hero.
What a mess!
Look closely at the metadata for the `HeroTaxReturnComponent`. Notice the `providers` property.
{@example 'hierarchical-dependency-injection/ts/src/app/hero-tax-return.component.ts' region='providers'}
The `HeroTaxReturnComponent` has its own provider of the `HeroTaxReturnService`.
Recall that every component _instance_ has its own injector.
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.
No tax return overwriting. No mess.
The rest of the scenario code relies on other Angular features and techniques that you can learn about elsewhere in the documentation.
You can review it and download it from the <live-example></live-example>
You can review it and download it from the <live-example></live-example>.
### Scenario: specialized providers
Another reason to re-provide a service is to substitute a _more specialized_ implementation of that service,
deeper in the component tree.
Consider again the Car example from the [Dependency Injection](./dependency-injection.html) guide.
Suppose you configured the root injector (marked as A) with _generic_ providers for
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.
@ -181,4 +177,4 @@ its injector produces an instance of `Car` resolved by injector (C) with an `Eng
The code for this _cars_ scenario is in the `car.components.ts` and `car.services.ts` files of the sample
which you can review and download from the <live-example></live-example>
which you can review and download from the <live-example></live-example>.

View File

@ -2,7 +2,7 @@
Documentation Overview
@intro
How to read and use this documentation
How to read and use this documentation.
@description
This page describes the Angular documentation at a high level.

View File

@ -2,7 +2,7 @@
Learning Angular
@intro
A suggested path through the documentation for Angular newcomers
A suggested path through the documentation for Angular newcomers.
@description

View File

@ -2,12 +2,12 @@
Npm Packages
@intro
Recommended npm packages, and how to specify package dependencies
Recommended npm packages, and how to specify package dependencies.
@description
Angular applications and Angular itself depend upon features and functionality provided by a variety of third-party packages.
These packages are maintained and installed with the Node Package Manager (<a href="https://docs.npmjs.com/" target="_blank">npm</a>).
Node.js and npm are essential to Angular development.
Node.js and npm are essential to Angular development.
<a href="https://docs.npmjs.com/getting-started/installing-node" target="_blank" title="Installing Node.js and updating npm">
Get them now</a> if they're not already installed on your machine.
@ -16,23 +16,28 @@ Get them now</a> if they're not already installed on your machine.
by running the commands `node -v` and `npm -v` in a terminal/console window.
Older versions produce errors.
We recommend [nvm](https://github.com/creationix/nvm) for managing multiple versions of node and npm. You may need [nvm](https://github.com/creationix/nvm) if you already have projects running on your machine that use other versions of node and npm.
We recommend a comprehensive starter-set of packages as specified in the `dependencies` and `devDependencies`
sections of the <a href="https://docs.npmjs.com/files/package.json" target="_blank">package.json</a> file
installed as described during [Setup](setup.html).You can use other packages but we recommend *this particular set* to start with because (a) they work well together and
(b) they include everything you'll need to build and run the sample applications in this series.
Note: A cookbook or guide page may require an additional library such as *jQuery*.You'll install more than you need for QuickStart.
No worries!
Consider using [nvm](https://github.com/creationix/nvm) for managing multiple
versions of node and npm. You may need [nvm](https://github.com/creationix/nvm) if
you already have projects running on your machine that use other versions of node and npm.
During [Setup](setup.html), a <a href="https://docs.npmjs.com/files/package.json" target="_blank">package.json</a>
file is installed with a comprehensive starter set of
packages as specified in the `dependencies` and `devDependencies` sections.
You can use other packages but the packages in _this particular set_ work well together and include
everything you need to build and run the sample applications in this series.
Note: A cookbook or guide page may require an additional library such as *jQuery*.You'll install more than you need for the QuickStart guide.
No worries!
You only serve to the client those packages that the application actually requests.
This page explains what each package does. You can make substitutions later to suit your tastes and experience.
## *dependencies* and *devDependencies*
The `package.json` includes two sets of packages,
The `package.json` includes two sets of packages,
[dependencies](#dependencies) and [devDependencies](#dev-dependencies).
The *dependencies* are essential to *running* the application.
The *devDependencies* are only necessary to *develop* the application.
The *dependencies* are essential to *running* the application.
The *devDependencies* are only necessary to *develop* the application.
You can exclude them from production installations by adding `--production` to the install command, as follows:
<code-example format="." language="bash">
npm install my-application --production
@ -46,37 +51,40 @@ You can exclude them from production installations by adding `--production` to t
## *dependencies*
The `dependencies` section of `package.json` contains:
* ***Features*** - Feature packages give the application framework and utility capabilities.
* ***Features***: Feature packages give the application framework and utility capabilities.
* ***Polyfills*** - Polyfills plug gaps in the browser's JavaScript implementation.
* ***Polyfills***: Polyfills plug gaps in the browser's JavaScript implementation.
* ***Other*** - Other libraries that support the application such as `bootstrap` for HTML widgets and styling.
* ***Other***: Other libraries that support the application such as `bootstrap` for HTML widgets and styling.
### Feature Packages
***@angular/core*** - Critical runtime parts of the framework needed by every application.
***@angular/core***: Critical runtime parts of the framework needed by every application.
Includes all metadata decorators, `Component`, `Directive`, dependency injection, and the component lifecycle hooks.
***@angular/common*** - The commonly needed services, pipes, and directives provided by the Angular team.
***@angular/common***: The commonly needed services, pipes, and directives provided by the Angular team.
***@angular/compiler*** - Angular's *Template Compiler*.
It understands templates and can convert them to code that makes the application run and render.
***@angular/compiler***: Angular's *Template Compiler*.
It understands templates and can convert them to code that makes the application run and render.
Typically you dont interact with the compiler directly; rather, you use it indirectly via `platform-browser-dynamic` or the offline template compiler.
***@angular/platform-browser*** - Everything DOM and browser related, especially the pieces that help render into DOM.
This package also includes the bootstrapStatic method for bootstrapping applications for production builds that pre-compile templates offline.
***@angular/platform-browser***: Everything DOM and browser related, especially
the pieces that help render into the DOM.
This package also includes the `bootstrapStatic()` method
for bootstrapping applications for production builds that pre-compile templates offline.
***@angular/platform-browser-dynamic*** - Includes [Providers](../api/core/index/Provider-type-alias.html) and a [bootstrap](ngmodule.html#bootstrap) method for applications that
***@angular/platform-browser-dynamic***: Includes [Providers](../api/core/index/Provider-type-alias.html)
and a [bootstrap](ngmodule.html#bootstrap) method for applications that
compile templates on the client. Dont use offline compilation.
Use this package for bootstrapping during development and for bootstrapping plunker samples.
***@angular/http*** - Angular's http client.
***@angular/http***: Angular's HTTP client.
***@angular/router*** - Component router.
***@angular/router***: Component router.
***@angular/upgrade*** - Set of utilities for upgrading AngularJS applications to Angular.
***@angular/upgrade***: Set of utilities for upgrading AngularJS applications to Angular.
***[system.js](https://github.com/systemjs/systemjs)*** - A dynamic module loader compatible with the
***[system.js](https://github.com/systemjs/systemjs)***: A dynamic module loader compatible with the
[ES2015 module](http://www.2ality.com/2014/09/es6-modules-final.html) specification.
Other viable choices include the well-regarded [webpack](https://webpack.github.io/).
@ -94,18 +102,18 @@ Install these polyfills using the npm packages that Angular lists in the *peerDe
You must list these packages in the `dependencies` section of your own `package.json`.
For background on this requirement, see [Why peerDependencies?](#why-peer-dependencies).***core-js*** - Patches the global context (window) with essential features of ES2015 (ES6).
You may substitute an alternative polyfill that provides the same core APIs.
For background on this requirement, see [Why peerDependencies?](#why-peer-dependencies).***core-js***: Patches the global context (window) with essential features of ES2015 (ES6).
You may substitute an alternative polyfill that provides the same core APIs.
When these APIs are implemented by the major browsers, this dependency will become unnecessary.
***rxjs*** - A polyfill for the [Observables specification](https://github.com/zenparsing/es-observable) currently before the
***rxjs***: A polyfill for the [Observables specification](https://github.com/zenparsing/es-observable) currently before the
[TC39](http://www.ecma-international.org/memento/TC39.htm) committee that determines standards for the JavaScript language.
You can pick a preferred version of *rxjs* (within a compatible version range)
You can pick a preferred version of *rxjs* (within a compatible version range)
without waiting for Angular updates.
***zone.js*** - A polyfill for the [Zone specification](https://gist.github.com/mhevery/63fdcdf7c65886051d55) currently before the
***zone.js***: A polyfill for the [Zone specification](https://gist.github.com/mhevery/63fdcdf7c65886051d55) currently before the
[TC39](http://www.ecma-international.org/memento/TC39.htm) committee that determines standards for the JavaScript language.
You can pick a preferred version of *zone.js* to use (within a compatible version range)
You can pick a preferred version of *zone.js* to use (within a compatible version range)
without waiting for Angular updates.
@ -113,12 +121,12 @@ without waiting for Angular updates.
### Other helper libraries
***angular-in-memory-web-api*** - An Angular-supported library that simulates a remote server's web api
without requiring an actual server or real http calls.
Good for demos, samples, and early stage development (before we even have a server).
Read about it in the [Http Client](server-communication.html#appendix-tour-of-heroes-in-memory-server) page.
***angular-in-memory-web-api***: An Angular-supported library that simulates a remote server's web api
without requiring an actual server or real HTTP calls.
Good for demos, samples, and early stage development (before you even have a server).
Read about it in the [HTTP Client](server-communication.html#in-mem-web-api) page.
***bootstrap*** - [Bootstrap](http://getbootstrap.com/) is a popular HTML and CSS framework for designing responsive web apps.
***bootstrap***: [Bootstrap](http://getbootstrap.com/) is a popular HTML and CSS framework for designing responsive web apps.
Some of the samples improve their appearance with *bootstrap*.
@ -128,39 +136,38 @@ Some of the samples improve their appearance with *bootstrap*.
The packages listed in the *devDependencies* section of the `package.json` help you develop the application.
You don't have to deploy them with the production application although there is no harm in doing so.
***[concurrently](https://www.npmjs.com/package/concurrently)*** -
***[concurrently](https://www.npmjs.com/package/concurrently)***:
A utility to run multiple *npm* commands concurrently on OS/X, Windows, and Linux operating systems.
***[lite-server](https://www.npmjs.com/package/lite-server)*** -
A light-weight, static file server, by [John Papa](http://johnpapa.net/)
***[lite-server](https://www.npmjs.com/package/lite-server)***:
A light-weight, static file server, by [John Papa](http://johnpapa.net/)
with excellent support for Angular apps that use routing.
***[typescript](https://www.npmjs.com/package/typescript)*** -
***[typescript](https://www.npmjs.com/package/typescript)***:
the TypeScript language server, including the *tsc* TypeScript compiler.
***@types/\**** - TypeScript definition files.
Learn more about it in the [TypeScript Configuration](typescript-configuration.html#typings) chapter.
***@types/\****: TypeScript definition files.
Learn more about it in the [TypeScript Configuration](typescript-configuration.html#typings) guide.
{@a why-peer-dependencies}
## Why *peerDependencies*?
There isn't a *peerDependencies* section in the QuickStart `package.json`.
But Angular has a *peerDependencies* section in
*its* package.json, which has important consequences for your application.
There isn't a [*peerDependencies*](https://nodejs.org/en/blog/npm/peer-dependencies/) section in the QuickStart `package.json`.
But Angular has a *peerDependencies* section in
*its* `package.json`, which has important consequences for your application.
It explains why you load the [polyfill](#polyfills) *dependency* packages in the QuickStart `package.json`,
This section explains why you load the [polyfill](#polyfills) *dependency*
packages in the QuickStart application's `package.json`,
and why you'll need those packages in your own applications.
An explanation of [peer dependencies](https://nodejs.org/en/blog/npm/peer-dependencies/) follows.
Packages depend on other packages. For example, your application depends on the Angular package.
Two packages, "A" and "B", could depend on the same third package "C".
Two packages, "A" and "B", could depend on the same third package "C".
"A" and "B" might both list "C" among their *dependencies*.
What if "A" and "B" depend on different versions of "C" ("C1" and "C2"). The npm package system supports that.
What if "A" and "B" depend on different versions of "C" ("C1" and "C2"). The npm package system supports that.
It installs "C1" in the `node_modules` folder for "A" and "C2" in the `node_modules` folder for "B".
Now "A" and "B" have their own copies of "C" and they run without interferring with one another.
@ -174,11 +181,11 @@ The difference between a `dependency` and a `peerDependency` is roughly this:
>A **dependency** says, "I need this thing directly available to *me*."
>
>A **peerDependency** says, "If you want to use me, you need this thing available to *you*."
The Angular `package.json` specifies several *peer dependency* packages,
The Angular `package.json` specifies several *peer dependency* packages,
each pinned to a particular version of a third-party package.
### We must install Angular's *peerDependencies* ourselves.
### You must install Angular's *peerDependencies* yourself.
When *npm* installs packages listed in *your* `dependencies` section,
it also installs the packages listed within *their* packages `dependencies` sections.
@ -191,7 +198,7 @@ the packages listed in Angular's *peerDependencies* section**.
Fortunately, *npm* issues a warning (a) When any *peer dependencies* are missing, or (b)
When the application or any of its other dependencies
installs a different version of a *peer dependency*.
installs a different version of a *peer dependency*.
These warnings guard against accidental failures due to version mismatches.
They leave you in control of package and version resolution.
@ -202,5 +209,5 @@ It is your responsibility to list all *peer dependency* packages **among your ow
The Angular polyfill dependencies are hard requirements. Currently, there is no way to make them optional.
However, there is an npm feature request for "optional peerDependencies," which would allow you to model this relationship better.
However, there is an npm feature request for "optional peerDependencies," which would allow you to model this relationship better.
When this feature request is implemented, Angular will switch from *peerDependencies* to *optionalPeerDependencies* for all polyfills.

File diff suppressed because it is too large Load Diff

View File

@ -2,7 +2,7 @@
Security
@intro
Developing for content security in Angular applications
Developing for content security in Angular applications.
@description
This page describes Angular's built-in

View File

@ -13,27 +13,50 @@ it isn't covered in this page.Modern browsers support two HTTP-based APIs:
[Fetch](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API).
The !{_Angular_http_library} simplifies application programming with the **XHR** and **JSONP** APIs.
This page covers:
- [The Tour of Heroes *HTTP* client demo](#http-client).
- [Fetch data with http.get](#fetch-data).
<li if-docs="ts"> [RxJS library](#rxjs).</li>
<li if-docs="ts"> [Enable RxJS operators](#enable-rxjs-operators).</li>
- [Process the response object](#extract-data).
- [Always handle errors](#error-handling).
- [Send data to the server](#update).
<li if-docs="ts"> [Fall back to promises](#promises).</li>
- [Cross-Origin Requests: Wikipedia example](#cors).
<ul if-docs="ts">
<li> [Search parameters](#search-parameters).</li>
<li> [More fun with observables](#more-observables).</li>
# Contents
* [Demos](#demos)
* [Providing HTTP Services](#http-providers)
* [The Tour of Heroes *HTTP* client demo](#http-client)
- [The `HeroListComponent` class](#HeroListComponent)
* [Fetch data with `http.get()`](#fetch-data)
<li if-docs="ts"> [RxJS library](#rxjs-library)
<ul>
<li> [Enable RxJS operators](#enable-rxjs-operators)</li>
</ul>
- [Guarding against Cross-Site Request Forgery](#xsrf).
- [Override default request headers (and other request options)](#override-default-request-options).
- [Appendix: Tour of Heroes _in-memory web api_](#in-mem-web-api).
</li>
* [Process the response object](#extract-data)
- [Parse to `JSON`](#parse-to-json)
- [Do not return the response object](#no-return-response-object)
- [Always handle errors](#error-handling)
- [`HeroListComponent` error handling](#hero-list-component)
* [Send data to the server](#update)
- [Headers](#headers)
- [JSON results](#json-results)
<ul><li if-docs="ts"> [Fall back to promises](#promises)</ul>
* [Cross-Origin Requests: Wikipedia example](#cors)
<ul if-docs="ts">
<li> [Search Wikipedia](#search-wikipedia)</li>
<li> [Search parameters](#search-parameters)</li>
<li> [The WikiComponent](#wikicomponent)</li>
</ul>
* [A wasteful app](#wasteful-app)
<li if-docs="ts"> [More fun with Observables](#more-observables)
<ul>
<li> [Create a stream of search terms](#create-stream)</li>
<li> [Listen for search terms](#listen-for-search-terms)</li>
</ul>
</li>
* [Guarding against Cross-Site Request Forgery](#xsrf)
* [Override default request headers (and other request options)](#override-default-request-options)
* [Appendix: Tour of Heroes _in-memory web api_](#in-mem-web-api)
A <live-example>live example</live-example> illustrates these topics.
{@a demos}
# Demos
This page describes server communication with the help of the following demos:
@ -58,7 +81,7 @@ Register providers by importing other NgModules to the root NgModule in `app.mod
The `HttpModule` is necessary for making HTTP calls.
Though the JsonpModule isn't necessary for plain HTTP,
Though the `JsonpModule` isn't necessary for plain HTTP,
there is a JSONP demo later in this page.
Loading its module now saves time.
## The Tour of Heroes HTTP client demo
@ -116,7 +139,7 @@ Components are easier to test and debug when their constructors are simple, and
{@a HeroService}
## Fetch data with http.get
## Fetch data with _http.get()_
In many of the previous samples the app faked the interaction with the server by
returning mock heroes in a service like this one:
@ -149,13 +172,15 @@ Alternatively, you can temporarily target a JSON file by changing the endpoint U
{@a extract-data}
## Process the response object
Remember that the `getHeroes()` method used an `!{_priv}extractData` helper method to map the `!{_priv}http.get` response object to heroes:
Remember that the `getHeroes()` method used an `!{_priv}extractData()` helper method to map the `!{_priv}http.get` response object to heroes:
{@example 'server-communication/ts/src/app/toh/hero.service.ts' region='extract-data'}
The `response` object doesn't hold the data in a form the app can use directly.
You must parse the response data into a JSON object.
{@a parse-to-json}
### Parse to JSON
Don't expect the decoded JSON to be the heroes !{_array} directly.
This server always wraps JSON results in an object with a `data`
@ -169,8 +194,12 @@ This is conventional web API behavior, driven by
Make no assumptions about the server API.
Not all servers return an object with a `data` property.
~~~
{@a no-return-response-object}
### Do not return the response object
The `getHeroes()` method _could_ have returned the HTTP response but this wouldn't
be a best practice.
@ -225,7 +254,7 @@ just the name of a new hero and returns an `Observable` of `Hero`. It begins lik
To implement it, you must know the server's API for creating heroes.
[This sample's data server](#server) follows typical REST guidelines.
[This sample's data server](#in-mem-web-api) follows typical REST guidelines.
It expects a [`POST`](http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html#sec9.5) request
at the same endpoint as `GET` heroes.
It expects the new hero data to arrive in the body of the request,
@ -240,14 +269,20 @@ The server generates the `id` and returns the entire `JSON` representation
of the new hero including its generated id. The hero arrives tucked inside a response object
with its own `data` property.
Now that you know how the API works, implement `addHero()`as follows:
Now that you know how the API works, implement `addHero()` as follows:
{@example 'server-communication/ts/src/app/toh/hero.service.ts' region='addhero'}
{@a headers}
### Headers
In the `headers` object, the `Content-Type` specifies that the body represents JSON.
{@a json-results}
### JSON results
As with `getHeroes()`, use the `!{_priv}extractData()` helper to [extract the data](#extract-data)
@ -270,10 +305,13 @@ This is called the [same-origin policy](https://en.wikipedia.org/wiki/Same-origi
Modern browsers do allow `XHR` requests to servers from a different origin if the server supports the
[CORS](https://en.wikipedia.org/wiki/Cross-origin_resource_sharing) protocol.
If the server requires user credentials, you'll enable them in the [request headers](#headers).
If the server requires user credentials, enable them in the [request headers](#headers).
Some servers do not support CORS but do support an older, read-only alternative called [JSONP](https://en.wikipedia.org/wiki/JSONP).
Wikipedia is one such server.
This [Stack Overflow answer](http://stackoverflow.com/questions/2067472/what-is-jsonp-all-about/2067584#2067584) covers many details of JSONP.### Search wikipedia
This [Stack Overflow answer](http://stackoverflow.com/questions/2067472/what-is-jsonp-all-about/2067584#2067584) covers many details of JSONP.
{@a search-wikipedia}
### Search Wikipedia
Here is a simple search that shows suggestions from Wikipedia as the user
types in a text box:
@ -289,7 +327,7 @@ types in a text box:
## Guarding against Cross-Site Request Forgery
In a cross-site request forgery (CSRF or XSRF), an attacker tricks the user into visiting
a different web page with malignant code that secretly sends a malicious request to your application's web server,
a different web page with malignant code that secretly sends a malicious request to your application's web server.
The server and client application must work together to thwart this attack.
Angular's `Http` client does its part by applying a default `CookieXSRFStrategy` automatically to all requests.
@ -311,7 +349,7 @@ Request options (such as headers) are merged into the
before the request is processed.
The `HttpModule` provides these default options via the `RequestOptions` token.
You can override these defaults to suit your application needs.
You can override these defaults to suit your application needs
by creating a custom sub-class of `RequestOptions`
that sets the default options for the application.
@ -326,7 +364,7 @@ Then it registers the provider in the root `AppModule`.
{@example 'server-communication/ts/src/app/app.module.ts' region='provide-default-request-options'}
Remember to include this provider during setup when unit testing the app's HTTP services.After this change, the `header` option setting in `HeroService.addHero` is no longer necessary,
Remember to include this provider during setup when unit testing the app's HTTP services.After this change, the `header` option setting in `HeroService.addHero()` is no longer necessary,
{@example 'server-communication/ts/src/app/toh/hero.service.ts' region='addhero'}

View File

@ -2,7 +2,7 @@
Setup for local development
@intro
Install the Angular QuickStart seed for faster, more efficient development on your machine
Install the Angular QuickStart seed for faster, more efficient development on your machine.
@description

View File

@ -19,15 +19,15 @@ how you can write your own structural directives to do the same thing.
- [What are structural directives?](#definition)
- [*NgIf* case study](#ngIf)
- [Group sibling elements with &lt;ng-container&gt;](#ng-container)
- [The asterisk (\*) prefix](#asterisk)
- [Inside *NgFor*](#ngfor)
- [The asterisk (*) prefix](#asterisk)
- [Inside *NgFor*](#ngFor)
- [microsyntax](#microsyntax)
- [template input variables](#template-input-variable)
- [one structural directive per element](#one-per-element)
- [Inside the *NgSwitch* directives](#ngSwitch)
- [Prefer the (\*) prefix](#prefer-asterisk)
- [Prefer the (*) prefix](#prefer-asterisk)
- [The &lt;template> element](#template)
- [Group sibling elements with &lt;ng-container&gt;](#ng-container)
- [Write a structural directive](#unless)
Try the <live-example></live-example>.
@ -45,15 +45,13 @@ As with other directives, you apply a structural directive to a _host element_.
The directive then does whatever it's supposed to do with that host element and its descendents.
Structural directives are easy to recognize.
An asterisk (\*) precedes the directive attribute name as in this example.
{@example 'structural-directives/ts/src/app/app.component.html' region='ngif'}
An asterisk (*) precedes the directive attribute name as in this example.
No brackets. No parentheses. Just `*ngIf` set to a string.
You'll learn in this guide that the [asterisk (\*) is a convenience notation](#asterisk)
and the string is a [_microsyntax_](#microsyntax) rather than the usual [template expression](template-syntax.html#template-expressions).
Angular "de-sugars" this notation into a marked-up `<template>` that surrounds the
You'll learn in this guide that the [asterisk (*) is a convenience notation](#asterisk)
and the string is a [_microsyntax_](#microsyntax) rather than the usual
[template expression](template-syntax.html#template-expressions).
Angular desugars this notation into a marked-up `<template>` that surrounds the
host element and its descendents.
Each structural directive does something different with that template.
@ -61,10 +59,6 @@ Three of the common, built-in structural directives&mdash;[NgIf](template-syntax
[NgFor](template-syntax.html#ngFor), and [NgSwitch...](template-syntax.html#ngSwitch)&mdash;are
described in the [_Template Syntax_](template-syntax.html) guide and seen in samples throughout the Angular documentation.
Here's an example of them in a template:
{@example 'structural-directives/ts/src/app/app.component.html' region='built-in'}
This guide won't repeat how to _use_ them. But it does explain _how they work_
and how to [write your own](#unless) structural directive.
@ -91,7 +85,8 @@ you apply the directive to an element in the HTML template.
~~~
There are two other kinds of Angular directives, described extensively elsewhere: (1)&nbsp;components and (2)&nbsp;attribute directives.
There are two other kinds of Angular directives, described extensively elsewhere:
(1)&nbsp;components and (2)&nbsp;attribute directives.
A *component* manages a region of HTML in the manner of a native HTML element.
Technically it's a directive with a template.
@ -107,14 +102,10 @@ You can [only apply one](#one-per-element) _structural_ directive to a host elem
{@a ngIf}
## NgIf Case Study
## NgIf case study
`NgIf` is the simplest structural directive and the easiest to understand.
It takes a boolean value and makes an entire chunk of the DOM appear or disappear.
{@example 'structural-directives/ts/src/app/app.component.html' region='ngif-true'}
It takes a boolean expression and makes an entire chunk of the DOM appear or disappear.
The `ngIf` directive doesn't hide elements with CSS. It adds and removes them physically from the DOM.
Confirm that fact using browser developer tools to inspect the DOM.
@ -133,9 +124,6 @@ The component and DOM nodes can be garbage-collected and free up memory.
### Why *remove* rather than *hide*?
A directive could hide the unwanted paragraph instead by setting its `display` style to `none`.
{@example 'structural-directives/ts/src/app/app.component.html' region='display-none'}
While invisible, the element remains in the DOM.
<figure class='image-display'>
@ -166,128 +154,24 @@ Before applying a structural directive, you might want to pause for a moment
to consider the consequences of adding and removing elements and of creating and destroying components.
{@a ngcontainer}
{@a ng-container}
## Group sibling elements with &lt;ng-container&gt;
There's often a _root_ element that can and should host the structural directive.
The list element (`<li>`) is a typical host element of an `NgFor` repeater.
{@example 'structural-directives/ts/src/app/app.component.html' region='ngfor-li'}
When there isn't a host element, you can usually wrap the content in a native HTML container element,
such as a `<div>`, and attach the directive to that wrapper.
{@example 'structural-directives/ts/src/app/app.component.html' region='ngif'}
Introducing another container element&mdash;typically a `<span>` or `<div>`&mdash;to
group the elements under a single _root_ is usually harmless.
_Usually_ ... but not _always_.
The grouping element may break the template appearance because CSS styles
neither expect nor accommodate the new layout.
For example, suppose you have the following paragraph layout.
{@example 'structural-directives/ts/src/app/app.component.html' region='ngif-span'}
You also have a CSS style rule that happens to apply to a `<span>` within a `<p>`aragraph.
{@example 'structural-directives/ts/src/app/app.component.css' region='p-span'}
The constructed paragraph renders strangely.
<figure class='image-display'>
<img src='assets/images/devguide/structural-directives/bad-paragraph.png' alt="spanned paragraph with bad style"> </img>
</figure>
The `p span` style, intended for use elsewhere, was inadvertently applied here.
Another problem: some HTML elements require all immediate children to be of a specific type.
For example, the `<select>` tag requires `<option>` children.
You can't wrap the _options_ in a conditional `<div>` or a `<span>`.
When you try this,
{@example 'structural-directives/ts/src/app/app.component.html' region='select-span'}
the drop down is empty.
<figure class='image-display'>
<img src='assets/images/devguide/structural-directives/bad-select.png' alt="spanned options don't work"> </img>
</figure>
The browser won't display an `<option>` within a `<span>`.
### &lt;ng-container&gt; to the rescue
The Angular `<ng-container>` is a grouping element that doesn't interfere with styles or layout
because Angular _doesn't put it in the DOM_.
Here's the conditional paragraph again, this time using `<ng-container>`.
{@example 'structural-directives/ts/src/app/app.component.html' region='ngif-ngcontainer'}
It renders properly.
<figure class='image-display'>
<img src='assets/images/devguide/structural-directives/good-paragraph.png' alt="ngcontainer paragraph with proper style"> </img>
</figure>
Now conditionally exclude a _select_ `<option>` with `<ng-container>`.
{@example 'structural-directives/ts/src/app/app.component.html' region='select-ngcontainer'}
The drop down works properly.
<figure class='image-display'>
<img src='assets/images/devguide/structural-directives/select-ngcontainer-anim.gif' alt="ngcontainer options work properly"> </img>
</figure>
The `<ng-container>` is a syntax element recognized by the Angular parser.
It's not a directive, component, class, or interface.
It's more like the curly braces in a JavaScript `if`-block:
<code-example language="javascript">
if (someCondition) {
statement1;
statement2;
statement3;
}
</code-example>
Without those braces JavaScript could only execute the first statement
when you intend to conditionally execute all of them as a single block.
The `<ng-container>` satisfies a similar need in Angular templates.
{@a asterisk}
## The asterisk (\*) prefix
## The asterisk (*) prefix
Surely you noticed the asterisk (\*) prefix to the directive name
Surely you noticed the asterisk (*) prefix to the directive name
and wondered why it is necessary and what it does.
Here is `*ngIf` displaying the hero's name if `hero` exists.
{@example 'structural-directives/ts/src/app/app.component.html' region='asterisk'}
The asterisk is "syntactic sugar" for something a bit more complicated.
Internally, Angular "de-sugars" it in two stages.
Internally, Angular desugars it in two stages.
First, it translates the `*ngIf="..."` into a template _attribute_, `template="ngIf ..."`,&nbsp; like this.
{@example 'structural-directives/ts/src/app/app.component.html' region='ngif-template-attr'}
Then it translates the template _attribute_ into a template _element_, wrapped around the host element, like this.
{@example 'structural-directives/ts/src/app/app.component.html' region='ngif-template'}
* The `*ngIf` directive moved to the `<template>` tag where it became a property binding,`[ngIf]`.
* The rest of the `<div>`, including its class attribute, moved inside the `<template>` tag.
* The `*ngIf` directive moved to the `<template>` element where it became a property binding,`[ngIf]`.
* The rest of the `<div>`, including its class attribute, moved inside the `<template>` element.
None of these forms are actually rendered.
Only the finished product ends up in the DOM.
<figure class='image-display'>
<img src='assets/images/devguide/structural-directives/hero-div-in-dom.png' alt="hero div in DOM"> </img>
</figure>
@ -295,25 +179,22 @@ Only the finished product ends up in the DOM.
Angular consumed the `<template>` content during its actual rendering and
replaced the `<template>` with a diagnostic comment.
The [`NgFor`](#ngfor) and [`NgSwitch...`](#ngswitch) directives follow the same pattern.
The [`NgFor`](#ngFor) and [`NgSwitch...`](#ngSwitch) directives follow the same pattern.
{@a ngfor}
{@a ngFor}
## Inside _*ngFor_
Angular transforms the `*ngFor` in similar fashion from asterisk (\*) syntax through
Angular transforms the `*ngFor` in similar fashion from asterisk (*) syntax through
template _attribute_ to template _element_.
Here's a full-featured application of `NgFor`, written all three ways:
{@example 'structural-directives/ts/src/app/app.component.html' region='inside-ngfor'}
This is manifestly more complicated than `ngIf` and rightly so.
The `NgFor` directive has more features, both required and optional, than the `NgIf` shown in this guide.
At minimum `NgFor` needs a looping variable (`let hero`) and a list (`heroes`).
You enable these features in the string assigned to `ngFor`, which you write in Angular's [microsyntax](microsyntax).
You enable these features in the string assigned to `ngFor`, which you write in Angular's [microsyntax](#microsyntax).
~~~ {.alert.is-helpful}
@ -328,7 +209,8 @@ In this example, the `[ngClass]="odd"` stays on the `<div>`.
{@a microsyntax}
### microsyntax
### Microsyntax
The Angular microsyntax lets you configure a directive in a compact, friendly string.
The microsyntax parser translates that string into attributes on the `<template>`:
@ -368,18 +250,18 @@ Studying the source code for `NgIf` and `NgFor` is a great way to learn more.
### Template input variable
A _template input variable_ is a variable whose value you can reference _within_ a single instance of the template.
There are several such variables in this example: `hero`, `li`, and `odd`.
There are several such variables in this example: `hero`, `i`, and `odd`.
All are preceded by the keyword `let`.
A _template input variable_ is **_not_** the same as a
[template _reference_ variable](template-syntax.html#ref-vars),
neither _semantically_ nor _syntactically_.
You declare a template _input_ variable declaration with the `let` keyword (`let hero`).
You declare a template _input_ variable using the `let` keyword (`let hero`).
The variable's scope is limited to a _single instance_ of the repeated template.
You can use the same variable name again in the definition of other structural directives.
You declare a template _reference_ variable declaration by prefixing the variable name with `#` (`#var`).
You declare a template _reference_ variable by prefixing the variable name with `#` (`#var`).
A _reference_ variable refers to its attached element, component or directive.
It can be accessed _anywhere_ in the _entire template_.
@ -404,16 +286,13 @@ There's an easy solution for this use case: put the `*ngIf` on a container eleme
One or both elements can be an [`ng-container`](#ngcontainer) so you don't have to introduce extra levels of HTML.
{@a ngswitch}
{@a ngSwitch}
## Inside the _NgSwitch_ directives
## Inside _NgSwitch_ directives
The Angular _NgSwitch_ is actually a set of cooperating directives: `NgSwitch`, `NgSwitchCase`, and `NgSwitchDefault`.
Here's an example.
{@example 'structural-directives/ts/src/app/app.component.html' region='ngswitch'}
The switch value assigned to `NgSwitch` (`hero.emotion`) determines which
(if any) of the switch cases are displayed.
@ -422,7 +301,7 @@ It's an _attribute_ directive that controls the behavior of the other two switch
That's why you write `[ngSwitch]`, never `*ngSwitch`.
`NgSwitchCase` and `NgSwitchDefault` _are_ structural directives.
You attach them to elements using the asterisk (\*) prefix notation.
You attach them to elements using the asterisk (*) prefix notation.
An `NgSwitchCase` displays its host element when its value matches the switch value.
The `NgSwitchDefault` displays its host element when no sibling `NgSwitchCase` matches the switch value.
@ -430,20 +309,14 @@ The element to which you apply a directive is its _host_ element.
The `<happy-hero>` is the host element for the happy `*ngSwitchCase`.
The `<unknown-hero>` is the host element for the `*ngSwitchDefault`.
As with other structural directives, the `NgSwitchCase` and `NgSwitchDefault`
can be "de-sugared" into the template _attribute_ form.
{@example 'structural-directives/ts/src/app/app.component.html' region='ngswitch-template-attr'}
That, in turn, can be "de-sugared" into the `<template>` element form.
{@example 'structural-directives/ts/src/app/app.component.html' region='ngswitch-template'}
can be desugared into the template _attribute_ form.
That, in turn, can be desugared into the `<template>` element form.
{@a prefer-asterisk}
## Prefer the asterisk (\*) syntax.
## Prefer the asterisk (*) syntax.
The asterisk (\*) syntax is more clear than the other "de-sugared" forms.
The asterisk (*) syntax is more clear than the other desugared forms.
Use [&lt;ng-container&gt;](#ng-container) when there's no single element
to host the directive.
@ -461,37 +334,116 @@ is a formula for rendering HTML.
It is never displayed directly.
In fact, before rendering the view, Angular _replaces_ the `<template>` and its contents with a comment.
If there is no structural directive, if you merely wrap some elements in a `<template>` and do nothing with it,
If there is no structural directive and you merely wrap some elements in a `<template>`,
those elements disappear.
That's the fate of the middle "hip" in the phrase "Hip! Hip! Hooray!".
That's the fate of the middle "Hip!" in the phrase "Hip! Hip! Hooray!".
Angular erases the middle "Hip!", leaving the cheer a bit less enthusiastic.
{@example 'structural-directives/ts/src/app/app.component.html' region='template-tag'}
Angular erases the middle "hip", leaving the cheer a bit less enthusiastic.
<figure class='image-display'>
<img src='assets/images/devguide/structural-directives/template-rendering.png' width="350" alt="template tag rendering"> </img>
</figure>
A structural directive puts a `<template>` to work
as you'll see when you write your own structural directive.
as you'll see when you [write your own structural directive](#unless).
{@a ngcontainer}
{@a ng-container}
## Group sibling elements with &lt;ng-container&gt;
There's often a _root_ element that can and should host the structural directive.
The list element (`<li>`) is a typical host element of an `NgFor` repeater.
When there isn't a host element, you can usually wrap the content in a native HTML container element,
such as a `<div>`, and attach the directive to that wrapper.
Introducing another container element&mdash;typically a `<span>` or `<div>`&mdash;to
group the elements under a single _root_ is usually harmless.
_Usually_ ... but not _always_.
The grouping element may break the template appearance because CSS styles
neither expect nor accommodate the new layout.
For example, suppose you have the following paragraph layout.
You also have a CSS style rule that happens to apply to a `<span>` within a `<p>`aragraph.
The constructed paragraph renders strangely.
<figure class='image-display'>
<img src='assets/images/devguide/structural-directives/bad-paragraph.png' alt="spanned paragraph with bad style"> </img>
</figure>
The `p span` style, intended for use elsewhere, was inadvertently applied here.
Another problem: some HTML elements require all immediate children to be of a specific type.
For example, the `<select>` element requires `<option>` children.
You can't wrap the _options_ in a conditional `<div>` or a `<span>`.
When you try this,
the drop down is empty.
<figure class='image-display'>
<img src='assets/images/devguide/structural-directives/bad-select.png' alt="spanned options don't work"> </img>
</figure>
The browser won't display an `<option>` within a `<span>`.
### &lt;ng-container&gt; to the rescue
The Angular `<ng-container>` is a grouping element that doesn't interfere with styles or layout
because Angular _doesn't put it in the DOM_.
Here's the conditional paragraph again, this time using `<ng-container>`.
It renders properly.
<figure class='image-display'>
<img src='assets/images/devguide/structural-directives/good-paragraph.png' alt="ngcontainer paragraph with proper style"> </img>
</figure>
Now conditionally exclude a _select_ `<option>` with `<ng-container>`.
The drop down works properly.
<figure class='image-display'>
<img src='assets/images/devguide/structural-directives/select-ngcontainer-anim.gif' alt="ngcontainer options work properly"> </img>
</figure>
The `<ng-container>` is a syntax element recognized by the Angular parser.
It's not a directive, component, class, or interface.
It's more like the curly braces in a JavaScript `if`-block:
<code-example language="javascript">
if (someCondition) {
statement1;
statement2;
statement3;
}
</code-example>
Without those braces, JavaScript would only execute the first statement
when you intend to conditionally execute all of them as a single block.
The `<ng-container>` satisfies a similar need in Angular templates.
{@a unless}
## Write a structural directive
In this section, you write a `UnlessDirective` structural directive
In this section, you write an `UnlessDirective` structural directive
that does the opposite of `NgIf`.
`NgIf` displays the template content when the condition is `true`.
`UnlessDirective` displays the content when the condition is ***false***.
Creating a directive is similar to creating a component.
* Import the `Directive` decorator (instead of the `Component` decorator).
{@example 'structural-directives/ts/src/app/app.component.html' region='myUnless-1'}
* Import the `Input`, `TemplateRef`, and `ViewContainerRef` symbols; you'll need them for _any_ structural directive.
* Apply the decorator to the directive class.
* Set the CSS *attribute selector* that identifies the directive when applied to an element in a template.
{@example 'structural-directives/ts/src/app/unless.directive.ts' region='skeleton'}
The directive's _selector_ is typically the directive's **attribute name** in square brackets.`[myUnless]`.
Here's how you might begin:
The directive's _selector_ is typically the directive's **attribute name** in square brackets, `[myUnless]`.
The brackets define a CSS
<a href="https://developer.mozilla.org/en-US/docs/Web/CSS/Attribute_selectors" target="_blank" title="MDN: Attribute selectors">attribute selector</a>.
@ -516,19 +468,12 @@ and access the _view container_ through a
[`ViewContainerRef`](../api/core/index/ViewContainerRef-class.html "API: ViewContainerRef").
You inject both in the directive constructor as private variables of the class.
{@example 'structural-directives/ts/src/app/unless.directive.ts' region='ctor'}
### The _myUnless_ property
The directive consumer expects to bind a true/false condition to `[myUnless]`.
That means the directive needs a `myUnless` property, decorated with `@Input`
Read about `@Input` in the [_Template Syntax_](template-syntax.html#inputs-outputs) guide.
{@example 'structural-directives/ts/src/app/unless.directive.ts' region='set'}
Angular sets the `myUnless` property whenever the value of the condition changes.
Because the `myUnless` property does work, it needs a setter.
@ -541,18 +486,12 @@ clear the container which also destroys the view.
Nobody reads the `myUnless` property so it doesn't need a getter.
The completed directive code looks like this:
{@example 'structural-directives/ts/src/app/unless.directive.ts' region='no-docs'}
Add this directive to the `!{_declsVsDirectives}` !{_array} of the !{_AppModuleVsAppComp}.
Then create some HTML to try it.
{@example 'structural-directives/ts/src/app/app.component.html' region='myUnless'}
When the `condition` is falsy, the top (A) paragraph appears and the bottom (B) paragraph disappears.
When the `condition` is truthy, the top (A) paragraph is removed and the bottom (B) paragraph appears.
<figure class='image-display'>
<img src='assets/images/devguide/structural-directives/unless-anim.gif' alt="UnlessDirective in action"> </img>
</figure>
@ -562,9 +501,10 @@ When the `condition` is truthy, the top (A) paragraph is removed and the bottom
{@a summary}
## Summary
You can both try and download the source code for this guide in the <live-example></live-example>.
Here is the source from the `app/` folder.
Here is the source from the `src/app/` folder.
<md-tab-group>
@ -606,9 +546,10 @@ Here is the source from the `app/` folder.
</md-tab-group>
You learned
* that structural directives manipulate HTML layout.
* to use [`<ng-container>`](#ngcontainer) as a grouping element when there is no suitable host element.
* that the angular "de-sugars" [asterisk (\*) syntax](#asterisk) into a `<template>`.
* that the Angular desugars [asterisk (*) syntax](#asterisk) into a `<template>`.
* how that works for the `NgIf`, `NgFor` and `NgSwitch` built-in directives.
* about the [_microsyntax_](#microsyntax) that expands into a [`<template>`](#template).
* to write a [custom structural directive](#unless), `UnlessDirective`.

File diff suppressed because it is too large Load Diff

View File

@ -2,7 +2,7 @@
TypeScript to JavaScript
@intro
Convert Angular TypeScript examples into ES6 and ES5 JavaScript
Convert Angular TypeScript examples into ES6 and ES5 JavaScript.
@description
Anything you can do with Angular in _TypeScript_, you can also do
@ -40,7 +40,7 @@ code shown in this cookbook.**
_TypeScript_
<a href="https://www.typescriptlang.org" target="_blank" title='"TypeScript is a typed, superset of JavaScript"'>is a typed superset of _ES6 JavaScript_</a>.
&nbsp; _ES6 JavaScript_ is a superset of _ES5 JavaScript_. &nbsp; _ES5_ is the kind of JavaScript that runs natively in all modern browsers.
_ES6 JavaScript_ is a superset of _ES5 JavaScript_. _ES5_ is the kind of JavaScript that runs natively in all modern browsers.
The transformation of _TypeScript_ code all the way down to _ES5_ code can be seen as "shedding" features.
The downgrade progression is

View File

@ -2,7 +2,7 @@
Visual Studio 2015 QuickStart
@intro
Use Visual Studio 2015 with the QuickStart files
Use Visual Studio 2015 with the QuickStart files.
@description
<a id="top"></a>Some developers prefer Visual Studio as their Integrated Development Environment (IDE).

View File

@ -2,7 +2,7 @@
Webpack: an introduction
@intro
Create Angular applications with a Webpack based tooling
Create Angular applications with a Webpack based tooling.
@description
@ -370,7 +370,7 @@ The development build relies on the Webpack development server, configured near
Although you tell Webpack to put output bundles in the `dist` folder,
the dev server keeps all bundles in memory; it doesn't write them to disk.
You won't find any files in the `dist` folder (at least not any generated from `this development build`).
You won't find any files in the `dist` folder (at least not any generated from *this development build*).
The `HtmlWebpackPlugin` (added in `webpack.common.js`) use the *publicPath* and the *filename* settings to generate

View File

@ -2,7 +2,7 @@
The Hero Editor
@intro
We build a simple hero editor
We build a simple hero editor.
@description
## Setup to develop locally

View File

@ -2,7 +2,7 @@
Master/Detail
@intro
We build a master/detail page with a list of heroes
We build a master/detail page with a list of heroes.
@description
Our story needs more heroes.

View File

@ -2,7 +2,7 @@
Multiple Components
@intro
We refactor the master/detail view into separate components
We refactor the master/detail view into separate components.
@description
Our app is growing.

View File

@ -2,7 +2,7 @@
Services
@intro
We create a reusable service to manage our hero data calls
We create a reusable service to manage our hero data calls.
@description
The Tour of Heroes is evolving and we anticipate adding more components in the near future.

View File

@ -2,7 +2,7 @@
Routing
@intro
We add the Angular Router and learn to navigate among the views
We add the Angular Router and learn to navigate among the views.
@description
We received new requirements for our Tour of Heroes application:

View File

@ -2,7 +2,7 @@
HTTP
@intro
We convert our service and components to use Angular's HTTP service
We convert our service and components to use Angular's HTTP service.
@description
Our stakeholders appreciate our progress.