docs(aio): move cookbooks into guide
Also update all docs with migrated versions from latest angular.io Fixes #14941
This commit is contained in:
parent
6497633529
commit
1847550ad1
|
@ -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>
|
||||
|
||||
|
|
@ -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)
|
|
@ -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,
|
||||
|
|
|
@ -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—the color that prevails until
|
||||
the user picks a highlight color—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}.
|
|
@ -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>.
|
|
@ -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?
|
|
@ -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.
|
|
@ -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.
|
||||
|
|
|
@ -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***,
|
|
@ -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
|
||||
|
|
|
@ -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.
|
|
@ -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`.
|
|
@ -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.
|
|
@ -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.
|
||||
|
||||
|
|
|
@ -51,8 +51,9 @@ 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.
|
||||
But you *can*.
|
||||
|
@ -67,6 +68,7 @@ All requests bubble up to the root <span if-docs="ts"><code>NgModule</code></spa
|
|||
## 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,27 +76,23 @@ 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 — and nowhere else —,
|
||||
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.
|
||||
|
@ -103,28 +101,30 @@ 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.
|
||||
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.
|
||||
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`.
|
||||
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.
|
||||
|
@ -138,17 +138,13 @@ 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.
|
||||
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,
|
||||
|
@ -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>.
|
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
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.
|
||||
|
@ -16,12 +16,17 @@ 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.
|
||||
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.
|
||||
|
||||
|
@ -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*.
|
||||
***@angular/compiler***: Angular's *Template Compiler*.
|
||||
It understands templates and can convert them to code that makes the application run and render.
|
||||
Typically you don’t 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. Don’t 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,16 +102,16 @@ 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).
|
||||
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)
|
||||
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)
|
||||
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,33 +136,32 @@ 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)*** -
|
||||
***[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`.
|
||||
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.
|
||||
*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".
|
||||
|
@ -178,7 +185,7 @@ The difference between a `dependency` and a `peerDependency` is roughly this:
|
|||
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.
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -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
|
||||
|
|
|
@ -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'}
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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 <ng-container>](#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 <template> element](#template)
|
||||
- [Group sibling elements with <ng-container>](#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—[NgIf](template-syntax
|
|||
[NgFor](template-syntax.html#ngFor), and [NgSwitch...](template-syntax.html#ngSwitch)—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) components and (2) attribute directives.
|
||||
There are two other kinds of Angular directives, described extensively elsewhere:
|
||||
(1) components and (2) 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 <ng-container>
|
||||
|
||||
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—typically a `<span>` or `<div>`—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>`.
|
||||
|
||||
### <ng-container> 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 ..."`, 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 [<ng-container>](#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 <ng-container>
|
||||
|
||||
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—typically a `<span>` or `<div>`—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>`.
|
||||
|
||||
### <ng-container> 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
|
@ -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>.
|
||||
_ES6 JavaScript_ is a superset of _ES5 JavaScript_. _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
|
|
@ -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).
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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.
|
||||
|
|
Loading…
Reference in New Issue