docs(aio): remove unnecessary blank lines

This commit is contained in:
Peter Bacon Darwin
2017-03-31 16:22:08 +01:00
committed by Pete Bacon Darwin
parent 0aa90c6be4
commit 46f8a6dd85
48 changed files with 1357 additions and 5587 deletions
File diff suppressed because it is too large Load Diff
+1 -18
View File
@@ -66,14 +66,12 @@ Animations are defined inside `@Component` metadata. Before you can add animatio
to import a few animation-specific imports and functions:
<code-example path="animations/src/app/app.module.ts" region="animations-module" linenums="false">
</code-example>
<code-example path="animations/src/app/hero-list-basic.component.ts" region="imports" linenums="false">
</code-example>
@@ -83,7 +81,6 @@ metadata. It uses animations to transition between two states: `active` and `ina
hero is active, the element appears in a slightly larger size and lighter color.
<code-example path="animations/src/app/hero-list-basic.component.ts" region="animationdef" linenums="false">
</code-example>
@@ -102,7 +99,6 @@ Now, using the `[@triggerName]` syntax, attach the animation that you just defin
one or more elements in the component's template.
<code-example path="animations/src/app/hero-list-basic.component.ts" region="template" linenums="false">
</code-example>
@@ -115,7 +111,6 @@ With this setup, an animated transition appears whenever a hero object changes s
Here's the full component implementation:
<code-example path="animations/src/app/hero-list-basic.component.ts">
</code-example>
@@ -134,7 +129,6 @@ component's template.
You can define *styles* for each animation state:
<code-example path="animations/src/app/hero-list-basic.component.ts" region="states" linenums="false">
</code-example>
@@ -147,7 +141,6 @@ After you define states, you can define *transitions* between the states. Each t
controls the timing of switching between one set of styles and the next:
<code-example path="animations/src/app/hero-list-basic.component.ts" region="transitions" linenums="false">
</code-example>
@@ -162,7 +155,6 @@ If several transitions have the same timing configuration, you can combine
them into the same `transition` definition:
<code-example path="animations/src/app/hero-list-combined-transitions.component.ts" region="transitions" linenums="false">
</code-example>
@@ -171,7 +163,6 @@ When both directions of a transition have the same timing, as in the previous
example, you can use the shorthand syntax `<=>`:
<code-example path="animations/src/app/hero-list-twoway.component.ts" region="transitions" linenums="false">
</code-example>
@@ -183,7 +174,6 @@ When the transition finishes, none of these styles are kept because they're not
defined in a `state`.
<code-example path="animations/src/app/hero-list-inline-styles.component.ts" region="transitions" linenums="false">
</code-example>
@@ -230,10 +220,9 @@ entering and leaving of elements:
* Enter: `void => *`
* Leave: `* => void`
For example, in the `animations` !{_array} below there are two transitions that use
For example, in the `animations` array below there are two transitions that use
the `void => *` and `* => void` syntax to animate the element in and out of the view.
<code-example path="animations/src/app/hero-list-enter-leave.component.ts" region="animationdef" linenums="false">
</code-example>
@@ -283,7 +272,6 @@ This gives you fine-grained control over each transition:
<code-example path="animations/src/app/hero-list-enter-leave-states.component.ts" region="animationdef" linenums="false">
</code-example>
@@ -325,7 +313,6 @@ In this example, the leave animation takes whatever height the element has befor
leaves and animates from that height to zero:
<code-example path="animations/src/app/hero-list-auto.component.ts" region="animationdef" linenums="false">
</code-example>
@@ -377,7 +364,6 @@ slight delay of 10 milliseconds as specified in `'0.2s 10 ease-out'`:
<code-example path="animations/src/app/hero-list-timings.component.ts" region="animationdef" linenums="false">
</code-example>
@@ -399,7 +385,6 @@ This example adds some "bounce" to the enter and leave animations with
keyframes:
<code-example path="animations/src/app/hero-list-multistep.component.ts" region="animationdef" linenums="false">
</code-example>
@@ -429,7 +414,6 @@ enter and leave allows for two different timing configurations. Both
are applied to the same element in parallel, but run independently of each other:
<code-example path="animations/src/app/hero-list-groups.component.ts" region="animationdef" linenums="false">
</code-example>
@@ -443,7 +427,6 @@ In the keyframes example, you have a `trigger` called `@flyInOut`. You can hook
those callbacks like this:
<code-example path="animations/src/app/hero-list-multistep.component.ts" region="template" linenums="false">
</code-example>
+5 -60
View File
@@ -11,6 +11,7 @@ during a build process.
{@a toc}
# Contents
- [Overview](guide/overview)
- [Ahead-of-time (AOT) vs just-in-time (JIT)](guide/aot-compiler#aot-jit)
- [Why do AOT compilation?](guide/aot-compiler#why-aot)
@@ -114,21 +115,16 @@ Take the <a href='../guide/setup.html'>Setup</a> as a starting point.
A few minor changes to the lone `app.component` lead to these two class and HTML files:
<code-tabs>
<code-pane title="src/app/app.component.html" path="cb-aot-compiler/src/app/app.component.html">
</code-pane>
<code-pane title="src/app/app.component.ts" path="cb-aot-compiler/src/app/app.component.ts">
</code-pane>
</code-tabs>
Install a few new npm dependencies with the following command:
@@ -147,7 +143,6 @@ Copy the original `src/tsconfig.json` to a file called `tsconfig-aot.json` on th
then modify it as follows.
<code-example path="cb-aot-compiler/tsconfig-aot.json" linenums="false">
</code-example>
@@ -241,21 +236,16 @@ Switch from the `platformBrowserDynamic.bootstrap` used in JIT compilation to
Here is AOT bootstrap in `main.ts` next to the original JIT version:
<code-tabs>
<code-pane title="src/main.ts" path="cb-aot-compiler/src/main.ts">
</code-pane>
<code-pane title="src/main-jit.ts" path="cb-aot-compiler/src/main-jit.ts">
</code-pane>
</code-tabs>
Be sure to [recompile](guide/aot-compiler#compiling-aot) with `ngc`!
@@ -310,7 +300,6 @@ in the project root directory to tell Rollup how to process the application.
The cookbook configuration file looks like this.
<code-example path="cb-aot-compiler/rollup-config.js" linenums="false">
</code-example>
@@ -339,8 +328,7 @@ Luckily, there is a Rollup plugin that modifies _RxJs_
to use the ES `import` and `export` statements that Rollup requires.
Rollup then preserves the parts of `RxJS` referenced by the application
in the final bundle. Using it is straigthforward. Add the following to
the `plugins` !{_array} in `rollup-config.js`:
the `plugins` array in `rollup-config.js`:
<code-example path="cb-aot-compiler/rollup-config.js" region="commonjs" linenums="false">
@@ -351,8 +339,7 @@ the `plugins` !{_array} in `rollup-config.js`:
Rollup tree shaking reduces code size considerably. Minification makes it smaller still.
This cookbook relies on the _uglify_ Rollup plugin to minify and mangle the code.
Add the following to the `plugins` !{_array}:
Add the following to the `plugins` array:
<code-example path="cb-aot-compiler/rollup-config.js" region="uglify" linenums="false">
@@ -404,7 +391,6 @@ Remove the scripts that concern SystemJS.
Instead, load the bundle file using a single `<script>` tag **_after_** the `</body>` tag:
<code-example path="cb-aot-compiler/src/index.html" region="bundle" linenums="false">
</code-example>
@@ -431,45 +417,32 @@ The server starts, launches a browser, and the app should appear.
Here's the pertinent source code:
<code-tabs>
<code-pane title="src/app/app.component.html" path="cb-aot-compiler/src/app/app.component.html">
</code-pane>
<code-pane title="src/app/app.component.ts" path="cb-aot-compiler/src/app/app.component.ts">
</code-pane>
<code-pane title="src/main.ts" path="cb-aot-compiler/src/main.ts">
</code-pane>
<code-pane title="src/index.html" path="cb-aot-compiler/src/index.html">
</code-pane>
<code-pane title="tsconfig-aot.json" path="cb-aot-compiler/tsconfig-aot.json">
</code-pane>
<code-pane title="rollup-config.js" path="cb-aot-compiler/rollup-config.js">
</code-pane>
</code-tabs>
@@ -501,7 +474,6 @@ The same source code can be built both ways. Here's one way to do that.
* Delete the script at the bottom of `index-jit.html` that loads `bundle.js`
* Restore the SystemJS scripts like this:
<code-example path="cb-aot-compiler/src/index-jit.html" region="jit" linenums="false">
</code-example>
@@ -516,14 +488,14 @@ Open a _different_ terminal window and enter `npm start`.
That compiles the app with JIT and launches the server.
The server loads `index.html` which is still the AOT version, which you can confirm in the browser console.
Change the address bar to `index-jit.html` and it loads the JIT version.
Change the address bar to `index-jit.html` and it loads the JIT version.
This is also evident in the browser console.
Develop as usual.
The server and TypeScript compiler are in "watch mode" so your changes are reflected immediately in the browser.
To see those changes in AOT, switch to the original terminal and re-run `npm run build:aot`.
When it finishes, go back to the browser and use the back button to
When it finishes, go back to the browser and use the back button to
return to the AOT version in the default `index.html`.
Now you can develop JIT and AOT, side-by-side.
@@ -554,21 +526,16 @@ The JIT and AOT apps require their own `index.html` files because they setup and
Here they are for comparison:
<code-tabs>
<code-pane title="aot/index.html (AOT)" path="toh-6/aot/index.html">
</code-pane>
<code-pane title="src/index.html (JIT)" path="toh-6/src/index.html">
</code-pane>
</code-tabs>
The JIT version relies on `SystemJS` to load individual modules.
@@ -584,21 +551,16 @@ The key differences, covered in the [Bootstrap](guide/aot-compiler#bootstrap) se
are evident in these `main` files which can and should reside in the same folder:
<code-tabs>
<code-pane title="main-aot.ts (AOT)" path="toh-6/src/main-aot.ts">
</code-pane>
<code-pane title="main.ts (JIT)" path="toh-6/src/main.ts">
</code-pane>
</code-tabs>
***TypeScript configuration***
@@ -610,21 +572,16 @@ AOT requires its own TypeScript configuration settings as well.
You'll need separate TypeScript configuration files such as these:
<code-tabs>
<code-pane title="tsconfig-aot.json (AOT)" path="toh-6/tsconfig-aot.json">
</code-pane>
<code-pane title="src/tsconfig.json (JIT)" path="toh-6/src/tsconfig.1.json">
</code-pane>
</code-tabs>
@@ -655,7 +612,6 @@ Edit your `tsconfig-aot.json` to fit your project's file structure.
Rollup does the tree shaking as before.
<code-example path="toh-6/rollup-config.js" linenums="false">
</code-example>
@@ -682,33 +638,24 @@ Run the JIT-compiled app with `npm start` as for all other JIT examples.
Compiling with AOT presupposes certain supporting files, most of them discussed above.
<code-tabs>
<code-pane title="src/index.html" path="toh-6/src/index.html">
</code-pane>
<code-pane title="copy-dist-files.js" path="toh-6/copy-dist-files.js">
</code-pane>
<code-pane title="rollup-config.js" path="toh-6/rollup-config.js">
</code-pane>
<code-pane title="tsconfig-aot.json" path="toh-6/tsconfig-aot.json">
</code-pane>
</code-tabs>
Extend the `scripts` section of the `package.json` with these npm scripts:Copy the AOT distribution files into the `/aot` folder with the node script:
@@ -761,9 +708,7 @@ showing exactly which application and Angular modules and classes are included i
Here's the map for _Tour of Heroes_.
<a href="assets/images/cookbooks/aot-compiler/toh6-bundle.png" target="_blank" title="View larger image">
<figure class='image-display'>
<img src="assets/images/cookbooks/aot-compiler/toh6-bundle.png" alt="TOH-6-bundle"> </img>
</figure>
</a>
-3
View File
@@ -14,7 +14,6 @@ The [setup](guide/setup) instructions produce a new project with the following m
You'll evolve this module as your application grows.
<code-example path="setup/src/app/app.module.ts" linenums="false">
</code-example>
@@ -136,7 +135,6 @@ and you'll run it in a browser. You can learn about other options later.
The recommended place to bootstrap a JIT-compiled browser application is in a separate file
in the `src` folder named `src/main.ts`
<code-example path="setup/src/main.ts" linenums="false">
</code-example>
@@ -151,7 +149,6 @@ creates an instance of the component and inserts it within the element tag ident
The `AppComponent` selector &mdash; here and in most documentation samples &mdash; is `my-app`
so Angular looks for a `<my-app>` tag in the `index.html` like this one ...
<code-example path="setup/src/index.html" region="my-app" linenums="false">
</code-example>
+10 -37
View File
@@ -6,7 +6,6 @@ The basic building blocks of Angular applications.
@description
Angular is a framework for building client applications in HTML and
either JavaScript or a language like TypeScript that compiles to JavaScript.
@@ -60,7 +59,6 @@ Learn these building blocks, and you're on your way.
<img src="assets/images/devguide/architecture/module.png" alt="Component" align="left" style="width:240px; margin-left:-40px;margin-right:10px"> </img>
</figure>
Angular apps are modular and Angular has its own modularity system called _Angular modules_ or _NgModules_.
_Angular modules_ are a big deal.
@@ -101,7 +99,6 @@ that hosts all other app views. Only the _root module_ should set this `bootstra
Here's a simple root module:
<code-example path="architecture/src/app/mini-app.ts" region="module" linenums="false">
</code-example>
@@ -118,7 +115,6 @@ Launch an application by _bootstrapping_ its root module.
During development you're likely to bootstrap the `AppModule` in a `main.ts` file like this one.
<code-example path="architecture/src/main.ts" linenums="false">
</code-example>
@@ -135,14 +131,12 @@ The module declares some objects to be public by marking them with the `export`
Other JavaScript modules use *import statements* to access public objects from other modules.
<code-example path="architecture/src/app/app.module.ts" region="imports" linenums="false">
</code-example>
<code-example path="architecture/src/app/app.module.ts" region="export" linenums="false">
</code-example>
@@ -163,31 +157,27 @@ These are two different and _complementary_ module systems. Use them both to wri
<img src="assets/images/devguide/architecture/library-module.png" alt="Component" align="left" style="width:240px; margin-left:-40px;margin-right:10px"> </img>
</figure>
Angular ships as a collection of JavaScript modules. You can think of them as library modules.
Each Angular library name begins with the `!{_at_angular}` prefix.
Each Angular library name begins with the `@angular` prefix.
You install them with the **npm** package manager and import parts of them with JavaScript `import` statements.
<br class="l-clear-both"><br>
For example, import Angular's `Component` decorator from the `@angular/core` library like this:
<code-example path="architecture/src/app/app.component.ts" region="import" linenums="false">
</code-example>
You also import Angular _modules_ from Angular _libraries_ using JavaScript import statements:
<code-example path="architecture/src/app/mini-app.ts" region="import-browser-module" linenums="false">
</code-example>
In the example of the simple root module above, the application module needs material from within that `BrowserModule`. To access that material, add it to the `@NgModule` metadata `imports` like this.
<code-example path="architecture/src/app/mini-app.ts" region="ngmodule-imports" linenums="false">
</code-example>
@@ -231,12 +221,11 @@ You define a component's application logic&mdash;what it does to support the vie
The class interacts with the view through an API of properties and methods.
<a id="component-code"></a>
For example, this `HeroListComponent` has a `heroes` property that returns !{_an} !{_array} of heroes
For example, this `HeroListComponent` has a `heroes` property that returns an array of heroes
that it acquires from a service.
`HeroListComponent` also has a `selectHero()` method that sets a `selectedHero` property when the user clicks to choose a hero from that list.
<code-example path="architecture/src/app/hero-list.component.ts" linenums="false" title="src/app/hero-list.component.ts (class)" region="class">
</code-example>
@@ -263,7 +252,6 @@ A template looks like regular HTML, except for a few differences. Here is a
template for our `HeroListComponent`:
<code-example path="architecture/src/app/hero-list.component.html">
</code-example>
@@ -305,18 +293,16 @@ In fact, `HeroListComponent` really is *just a class*. It's not a component unti
To tell Angular that `HeroListComponent` is a component, attach **metadata** to the class.
In !{_Lang}, you attach metadata by using !{_a} **!{_decorator}**.
In TypeScript, you attach metadata by using a **decorator**.
Here's some metadata for `HeroListComponent`:
<code-example path="architecture/src/app/hero-list.component.ts" linenums="false" title="src/app/hero-list.component.ts (metadata)" region="metadata">
</code-example>
Here is the `@Component` !{_decorator}, which identifies the class
Here is the `@Component` decorator, which identifies the class
immediately below it as a component class.
The `@Component` decorator takes a required configuration object with the
information Angular needs to create and present the component and its view.
@@ -327,8 +313,7 @@ For example, if an app's HTML contains `<hero-list></hero-list>`, then
Angular inserts an instance of the `HeroListComponent` view between those tags.
- `templateUrl`: module-relative address of this component's HTML template, shown [above](guide/architecture#templates).
- `providers`: !{_array} of **dependency injection providers** for services that the component requires.
- `providers`: array of **dependency injection providers** for services that the component requires.
This is one way to tell Angular that the component's constructor requires a `HeroService`
so it can get the list of heroes to display.
@@ -341,8 +326,8 @@ The metadata in the `@Component` tells Angular where to get the major building b
The template, metadata, and component together describe a view.
Apply other metadata !{_decorator}s in a similar fashion to guide Angular behavior.
`@Injectable`, `@Input`, and `@Output` are a few of the more popular !{_decorator}s.<br class="l-clear-both">The architectural takeaway is that you must add metadata to your code
Apply other metadata decorators in a similar fashion to guide Angular behavior.
`@Injectable`, `@Input`, and `@Output` are a few of the more popular decorators.<br class="l-clear-both">The architectural takeaway is that you must add metadata to your code
so that Angular knows what to do.
@@ -367,7 +352,6 @@ Add binding markup to the template HTML to tell Angular how to connect both side
As the diagram shows, there are four forms of data binding syntax. Each form has a direction &mdash; to the DOM, from the DOM, or in both directions.<br class="l-clear-both">The `HeroListComponent` [example](guide/architecture#templates) template has three forms:
<code-example path="architecture/src/app/hero-list.component.1.html" linenums="false" title="src/app/hero-list.component.html (binding)" region="binding">
</code-example>
@@ -385,7 +369,6 @@ that combines property and event binding in a single notation, using the `ngMode
Here's an example from the `HeroDetailComponent` template:
<code-example path="architecture/src/app/hero-detail.component.html" linenums="false" title="src/app/hero-detail.component.html (ngModel)" region="ngModel">
</code-example>
@@ -425,9 +408,9 @@ Data binding is also important for communication between parent and child compon
Angular templates are *dynamic*. When Angular renders them, it transforms the DOM
according to the instructions given by **directives**.
A directive is a class with a `@Directive` !{_decorator}.
A directive is a class with a `@Directive` decorator.
A component is a *directive-with-a-template*;
a `@Component` !{_decorator} is actually a `@Directive` !{_decorator} extended with template-oriented features.
a `@Component` decorator is actually a `@Directive` decorator extended with template-oriented features.
<br class="l-clear-both">
@@ -448,14 +431,12 @@ sometimes by name but more often as the target of an assignment or a binding.
The [example template](guide/architecture#templates) uses two built-in structural directives:
<code-example path="architecture/src/app/hero-list.component.1.html" linenums="false" title="src/app/hero-list.component.html (structural)" region="structural">
</code-example>
* [`*ngFor`](guide/displaying-data) tells Angular to stamp out one `<li>` per hero in the `heroes` list.
* [`*ngIf`](guide/displaying-data) includes the `HeroDetail` component only if a selected hero exists.
**Attribute** directives alter the appearance or behavior of an existing element.
In templates they look like regular HTML attributes, hence the name.
@@ -465,7 +446,6 @@ an existing element (typically an `<input>`)
by setting its display value property and responding to change events.
<code-example path="architecture/src/app/hero-detail.component.html" linenums="false" title="src/app/hero-detail.component.html (ngModel)" region="ngModel">
</code-example>
@@ -509,16 +489,14 @@ Yet services are fundamental to any Angular application. Components are big cons
Here's an example of a service class that logs to the browser console:
<code-example path="architecture/src/app/logger.service.ts" linenums="false" title="src/app/logger.service.ts (class)" region="class">
</code-example>
Here's a `HeroService` that uses a !{_PromiseLinked} to fetch heroes.
Here's a `HeroService` that uses a [Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) to fetch heroes.
The `HeroService` depends on the `Logger` service and another `BackendService` that handles the server communication grunt work.
<code-example path="architecture/src/app/hero.service.ts" linenums="false" title="src/app/hero.service.ts (class)" region="class">
</code-example>
@@ -558,7 +536,6 @@ Angular uses dependency injection to provide new components with the services th
For example, the constructor of your `HeroListComponent` needs a `HeroService`:
<code-example path="architecture/src/app/hero-list.component.ts" linenums="false" title="src/app/hero-list.component.ts (constructor)" region="ctor">
</code-example>
@@ -583,14 +560,12 @@ If the injector doesn't have a `HeroService`, how does it know how to make one?
In brief, you must have previously registered a **provider** of the `HeroService` with the injector.
A provider is something that can create or return a service, typically the service class itself.
You can register providers in modules or in components.
In general, add providers to the [root module](guide/architecture#module) so that
the same instance of a service is available everywhere.
<code-example path="architecture/src/app/app.module.ts" linenums="false" title="src/app/app.module.ts (module providers)" region="providers">
</code-example>
@@ -598,7 +573,6 @@ the same instance of a service is available everywhere.
Alternatively, register at a component level in the `providers` property of the `@Component` metadata:
<code-example path="architecture/src/app/hero-list.component.ts" linenums="false" title="src/app/hero-list.component.ts (component providers)" region="providers">
</code-example>
@@ -671,6 +645,5 @@ by implementing the lifecycle hook interfaces.
> [**Router**](guide/router): Navigate from page to page within the client
application and never leave the browser.
> [**Testing**](guide/testing): Run unit tests on your application parts as they interact with the Angular framework
using the _Angular Testing Platform_.
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -23,7 +23,6 @@ in which two or more components share information.
typically adorned with [@Input decorations](guide/template-syntax).
<code-example path="cb-component-communication/src/app/hero-child.component.ts">
</code-example>
@@ -35,7 +34,6 @@ binding its `master` string property to the child's `master` alias,
and each iteration's `hero` instance to the child's `hero` property.
<code-example path="cb-component-communication/src/app/hero-parent.component.ts">
</code-example>
@@ -52,7 +50,6 @@ The running application displays three heroes:
E2E test that all children were instantiated and displayed as expected:
<code-example path="cb-component-communication/e2e-spec.ts" region="parent-to-child">
</code-example>
@@ -67,7 +64,6 @@ The setter of the `name` input property in the child `NameChildComponent`
trims the whitespace from a name and replaces an empty value with default text.
<code-example path="cb-component-communication/src/app/name-child.component.ts">
</code-example>
@@ -75,7 +71,6 @@ trims the whitespace from a name and replaces an empty value with default text.
Here's the `NameParentComponent` demonstrating name variations including a name with all spaces:
<code-example path="cb-component-communication/src/app/name-parent.component.ts">
</code-example>
@@ -91,7 +86,6 @@ Here's the `NameParentComponent` demonstrating name variations including a name
E2E tests of input property setter with empty and non-empty names:
<code-example path="cb-component-communication/e2e-spec.ts" region="parent-to-child-setter">
</code-example>
@@ -113,7 +107,6 @@ Learn about `ngOnChanges()` in the [LifeCycle Hooks](guide/lifecycle-hooks) chap
This `VersionChildComponent` detects changes to the `major` and `minor` input properties and composes a log message reporting these changes:
<code-example path="cb-component-communication/src/app/version-child.component.ts">
</code-example>
@@ -121,7 +114,6 @@ This `VersionChildComponent` detects changes to the `major` and `minor` input pr
The `VersionParentComponent` supplies the `minor` and `major` values and binds buttons to methods that change them.
<code-example path="cb-component-communication/src/app/version-parent.component.ts">
</code-example>
@@ -139,7 +131,6 @@ Test that ***both*** input properties are set initially and that button clicks t
the expected `ngOnChanges` calls and values:
<code-example path="cb-component-communication/e2e-spec.ts" region="parent-to-child-onchanges">
</code-example>
@@ -156,7 +147,6 @@ The child's `EventEmitter` property is an ***output property***,
as seen in this `VoterComponent`:
<code-example path="cb-component-communication/src/app/voter.component.ts">
</code-example>
@@ -167,7 +157,6 @@ The parent `VoteTakerComponent` binds an event handler called `onVoted()` that r
payload `$event` and updates a counter.
<code-example path="cb-component-communication/src/app/votetaker.component.ts">
</code-example>
@@ -185,7 +174,6 @@ and the method processes it:
Test that clicking the *Agree* and *Disagree* buttons update the appropriate counters:
<code-example path="cb-component-communication/e2e-spec.ts" region="child-to-parent">
</code-example>
@@ -205,7 +193,6 @@ The following is a child `CountdownTimerComponent` that repeatedly counts down t
It has `start` and `stop` methods that control the clock and it displays a
countdown status message in its own template.
<code-example path="cb-component-communication/src/app/countdown-timer.component.ts">
</code-example>
@@ -213,7 +200,6 @@ countdown status message in its own template.
The `CountdownLocalVarParentComponent` that hosts the timer component is as follows:
<code-example path="cb-component-communication/src/app/countdown-parent.component.ts" region="lv">
</code-example>
@@ -245,7 +231,6 @@ match the seconds displayed in the child's status message.
Test also that clicking the *Stop* button pauses the countdown timer:
<code-example path="cb-component-communication/e2e-spec.ts" region="countdown-timer-tests">
</code-example>
@@ -278,7 +263,6 @@ is solely for the purpose of demonstration.
Here is the parent, `CountdownViewChildParentComponent`:
<code-example path="cb-component-communication/src/app/countdown-parent.component.ts" region="vc">
</code-example>
@@ -322,7 +306,6 @@ Components outside this component subtree have no access to the service or their
This `MissionService` connects the `MissionControlComponent` to multiple `AstronautComponent` children.
<code-example path="cb-component-communication/src/app/mission.service.ts">
</code-example>
@@ -331,7 +314,6 @@ The `MissionControlComponent` both provides the instance of the service that it
(through the `providers` metadata array) and injects that instance into itself through its constructor:
<code-example path="cb-component-communication/src/app/missioncontrol.component.ts">
</code-example>
@@ -340,7 +322,6 @@ The `AstronautComponent` also injects the service in its constructor.
Each `AstronautComponent` is a child of the `MissionControlComponent` and therefore receives its parent's service instance:
<code-example path="cb-component-communication/src/app/astronaut.component.ts">
</code-example>
@@ -374,7 +355,6 @@ Tests click buttons of both the parent `MissionControlComponent` and the `Astron
and verify that the history meets expectations:
<code-example path="cb-component-communication/e2e-spec.ts" region="bidirectional-service">
</code-example>
+4 -20
View File
@@ -33,11 +33,10 @@ but also the CSS styles that go with that template,
specifying any selectors, rules, and media queries that you need.
One way to do this is to set the `styles` property in the component metadata.
The `styles` property takes #{_an} #{_array} of strings that contain CSS code.
The `styles` property takes an array of strings that contain CSS code.
Usually you give it one string, as in the following example:
<code-example path="component-styles/src/app/hero-app.component.ts" linenums="false">
</code-example>
@@ -74,7 +73,6 @@ Use the `:host` pseudo-class selector to target styles in the element that *host
targeting elements *inside* the component's template).
<code-example path="component-styles/src/app/hero-details.component.css" region="host" linenums="false">
</code-example>
@@ -89,7 +87,6 @@ including another selector inside parentheses after `:host`.
The next example targets the host element again, but only when it also has the `active` CSS class.
<code-example path="component-styles/src/app/hero-details.component.css" region="hostfunction" linenums="false">
</code-example>
@@ -108,7 +105,6 @@ The following example applies a `background-color` style to all `<h2>` elements
if some ancestor element has the CSS class `theme-light`.
<code-example path="component-styles/src/app/hero-details.component.css" region="hostcontext" linenums="false">
</code-example>
@@ -124,7 +120,6 @@ children and content children of the component.
The following example targets all `<h3>` elements, from the host element down
through this component to all of its child elements in the DOM.
<code-example path="component-styles/src/app/hero-details.component.css" region="deep" linenums="false">
</code-example>
@@ -156,9 +151,8 @@ The scoping rules outlined earlier apply to each of these loading patterns.
### Styles in metadata
You can add a `styles` #{_array} property to the `@Component` #{_decorator}.
Each string in the #{_array} (usually just one string) defines the CSS.
You can add a `styles` array property to the `@Component` decorator.
Each string in the array (usually just one string) defines the CSS.
<code-example path="component-styles/src/app/hero-app.component.ts">
@@ -168,8 +162,7 @@ Each string in the #{_array} (usually just one string) defines the CSS.
### Style URLs in metadata
You can load styles from external CSS files by adding a `styleUrls` attribute
into a component's `@Component` #{_decorator}:
into a component's `@Component` decorator:
<code-example path="component-styles/src/app/hero-details.component.ts" region="styleurls">
@@ -178,7 +171,6 @@ into a component's `@Component` #{_decorator}:
~~~ {.alert.is-important}
The URL is relative to the *application root*, which is usually the
@@ -192,7 +184,6 @@ To specify a URL relative to the component file, see [Appendix 2](guide/componen
~~~ {.l-sub-section}
If you use module bundlers like Webpack, you can also use the `styles` attribute
@@ -215,7 +206,6 @@ You can embed styles directly into the HTML template by putting them
inside `<style>` tags.
<code-example path="component-styles/src/app/hero-controls.component.ts" region="inlinestyles">
</code-example>
@@ -228,7 +218,6 @@ As with `styleUrls`, the link tag's `href` URL is relative to the
application root, not the component file.
<code-example path="component-styles/src/app/hero-team.component.ts" region="stylelink">
</code-example>
@@ -238,11 +227,9 @@ application root, not the component file.
You can also import CSS files into the CSS files using the standard CSS `@import` rule.
For details, see [`@import`](https://developer.mozilla.org/en/docs/Web/CSS/@import)
on the [MDN](https://developer.mozilla.org) site.
In this case, the URL is relative to the CSS file into which you're importing.
<code-example path="component-styles/src/app/hero-details.component.css" region="import">
</code-example>
@@ -276,7 +263,6 @@ Choose from the following modes:
To set the components encapsulation mode, use the `encapsulation` property in the component metadata:
<code-example path="component-styles/src/app/quest-summary.component.ts" region="encapsulation.native" linenums="false">
</code-example>
@@ -355,11 +341,9 @@ It's common practice to split a component's code, HTML, and CSS into three separ
You include the template and CSS files by setting the `templateUrl` and `styleUrls` metadata properties respectively.
Because these files are co-located with the component,
it would be nice to refer to them by name without also having to specify a path back to the root of the application.
You can use a relative URL by prefixing your filenames with `./`:
<code-example path="component-styles/src/app/quest-summary.component.ts">
</code-example>
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+43 -42
View File
@@ -22,7 +22,7 @@ The final UI looks like this:
# Contents
* [Showing component properties with interpolation](guide/displaying-data#interpolation).
* [Showing !{_an} !{_array} property with NgFor](guide/displaying-data#ngFor).
* [Showing an array property with NgFor](guide/displaying-data#ngFor).
* [Conditional display with NgIf](guide/displaying-data#ngIf).
@@ -41,15 +41,14 @@ is to bind the property name through interpolation.
With interpolation, you put the property name in the view template, enclosed in double curly braces: `{{myHero}}`.
Follow the [setup](guide/setup) instructions for creating a new project
named <ngio-ex path="displaying-data"></ngio-ex>.
named <code>displaying-data</code>.
Then modify the <ngio-ex path="app.component.ts"></ngio-ex> file by
Then modify the <code>app.component.ts</code> file by
changing the template and the body of the component.
When you're done, it should look like this:
<code-example path="displaying-data/src/app/app.component.1.ts">
</code-example>
@@ -60,11 +59,22 @@ The revised template displays the two component properties using double curly br
interpolation:
<code-example path="displaying-data/src/app/app.component.1.ts" linenums="false" title="src/app/app.component.ts (template)" region="template">
</code-example>
~~~ {.l-sub-section}
The template is a multi-line string within ECMAScript 2015 backticks (<code>\`</code>).
The backtick (<code>\`</code>)&mdash;which is *not* the same character as a single
quote (`'`)&mdash;allows you to compose a string over several lines, which makes the
HTML more readable.
~~~
Angular automatically pulls the value of the `title` and `myHero` properties from the component and
inserts those values into the browser. Angular updates the display
when these properties change.
@@ -81,16 +91,15 @@ the view, such as a keystroke, a timer completion, or a response to an HTTP requ
Notice that you don't call **new** to create an instance of the `AppComponent` class.
Angular is creating an instance for you. How?
The CSS `selector` in the `@Component` !{_decorator} specifies an element named `<my-app>`.
The CSS `selector` in the `@Component` decorator specifies an element named `<my-app>`.
That element is a placeholder in the body of your `index.html` file:
<code-example path="displaying-data/src/index.html" linenums="false" title="src/index.html (body)" region="body">
</code-example>
When you bootstrap with the `AppComponent` class (in <ngio-ex path="main.ts"></ngio-ex>), Angular looks for a `<my-app>`
When you bootstrap with the `AppComponent` class (in <code>main.ts</code>), Angular looks for a `<my-app>`
in the `index.html`, finds it, instantiates an instance of `AppComponent`, and renders it
inside the `<my-app>` tag.
@@ -100,12 +109,13 @@ Now run the app. It should display the title and hero name:
<img src="assets/images/devguide/displaying-data/title-and-hero.png" alt="Title and Hero"> </img>
</figure>
The next few sections review some of the coding choices in the app.
## Template inline or template file?
You can store your component's template in one of two places.
You can define it *inline* using the `template` property, or you can define
the template in a separate HTML file and link to it in
the component metadata using the `@Component` !{_decorator}'s `templateUrl` property.
the component metadata using the `@Component` decorator's `templateUrl` property.
The choice between inline and separate HTML is a matter of taste,
circumstances, and organization policy.
@@ -113,11 +123,20 @@ Here the app uses inline HTML because the template is small and the demo
is simpler without the additional HTML file.
In either style, the template data bindings have the same access to the component's properties.
## Constructor or variable initialization?
## Showing !{_an} !{_array} property with ***ngFor**
Although this example uses variable assignment to initialize the components, you can instead declare and initialize the properties using a constructor:
To display a list of heroes, begin by adding !{_an} !{_array} of hero names to the component and redefine `myHero` to be the first name in the !{_array}.
<code-example path="displaying-data/src/app/app-ctor.component.ts" linenums="false" title="src/app/app-ctor.component.ts (class)" region="class">
</code-example>
This app uses more terse "variable assignment" style simply for brevity.
## Showing an array property with ***ngFor**
To display a list of heroes, begin by adding an array of hero names to the component and redefine `myHero` to be the first name in the array.
<code-example path="displaying-data/src/app/app.component.2.ts" linenums="false" title="src/app/app.component.ts (class)" region="class">
@@ -128,7 +147,6 @@ Now use the Angular `ngFor` directive in the template to display
each item in the `heroes` list.
<code-example path="displaying-data/src/app/app.component.2.ts" linenums="false" title="src/app/app.component.ts (template)" region="template">
</code-example>
@@ -138,7 +156,6 @@ in the `<li>` element is the Angular "repeater" directive.
It marks that `<li>` element (and its children) as the "repeater template":
<code-example path="displaying-data/src/app/app.component.2.ts" linenums="false" title="src/app/app.component.ts (li)" region="li">
</code-example>
@@ -165,8 +182,8 @@ context for the interpolation in the double curly braces.
~~~ {.l-sub-section}
In this case, `ngFor` is displaying !{_an} !{_array}, but `ngFor` can
repeat items for any [iterable](guide/!{_iterableUrl}) object.
In this case, `ngFor` is displaying an array, but `ngFor` can
repeat items for any [iterable](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols) object.
~~~
@@ -183,21 +200,19 @@ Now the heroes appear in an unordered list.
The app's code defines the data directly inside the component, which isn't best practice.
In a simple demo, however, it's fine.
At the moment, the binding is to !{_an} !{_array} of strings.
At the moment, the binding is to an array of strings.
In real applications, most bindings are to more specialized objects.
To convert this binding to use specialized objects, turn the !{_array}
of hero names into !{_an} !{_array} of `Hero` objects. For that you'll need a `Hero` class.
Create a new file in the `!{_appDir}` folder called <ngio-ex path="hero.ts"></ngio-ex> with the following code:
To convert this binding to use specialized objects, turn the array
of hero names into an array of `Hero` objects. For that you'll need a `Hero` class.
Create a new file in the `app` folder called `hero.ts` with the following code:
<code-example path="displaying-data/src/app/hero.ts" linenums="false" title="src/app/hero.ts (excerpt)">
</code-example>
You've defined a class with a constructor and two properties: `id` and `name`.
It might not look like the class has properties, but it does.
@@ -206,7 +221,6 @@ The declaration of the constructor parameters takes advantage of a TypeScript sh
Consider the first parameter:
<code-example path="displaying-data/src/app/hero.ts" linenums="false" title="src/app/hero.ts (id)" region="id">
</code-example>
@@ -218,11 +232,10 @@ That brief syntax does a lot:
## Using the Hero class
After importing the `Hero` class, the `AppComponent.heroes` property can return a _typed_ !{_array}
After importing the `Hero` class, the `AppComponent.heroes` property can return a _typed_ array
of `Hero` objects:
<code-example path="displaying-data/src/app/app.component.3.ts" linenums="false" title="src/app/app.component.ts (heroes)" region="heroes">
</code-example>
@@ -232,7 +245,6 @@ At the moment it displays the hero's `id` and `name`.
Fix that to display only the hero's `name` property.
<code-example path="displaying-data/src/app/app.component.3.ts" linenums="false" title="src/app/app.component.ts (template)" region="template">
</code-example>
@@ -245,11 +257,10 @@ Sometimes an app needs to display a view or a portion of a view only under speci
Let's change the example to display a message if there are more than three heroes.
The Angular `ngIf` directive inserts or removes an element based on a !{_boolean} condition.
The Angular `ngIf` directive inserts or removes an element based on a _truthy/falsy_ condition.
To see it in action, add the following paragraph at the bottom of the template:
<code-example path="displaying-data/src/app/app.component.ts" linenums="false" title="src/app/app.component.ts (message)" region="message">
</code-example>
@@ -265,7 +276,7 @@ Read more about `ngIf` and `*` in the [ngIf section](guide/template-syntax) of t
~~~
The template expression inside the double quotes,
`*ngIf="heros.length > 3"`, looks and behaves much like !{_Lang}.
`*ngIf="heros.length > 3"`, looks and behaves much like TypeScript.
When the component's list of heroes has more than three items, Angular adds the paragraph
to the DOM and the message appears. If there are three or fewer items, Angular omits the
paragraph, so no message appears. For more information,
@@ -281,47 +292,37 @@ big chunks of HTML with many data bindings.
~~~
Try it out. Because the !{_array} has four items, the message should appear.
Go back into <ngio-ex path="app.component.ts"></ngio-ex> and delete or comment out one of the elements from the hero !{_array}.
Try it out. Because the array has four items, the message should appear.
Go back into <code>app.component.ts"</code> and delete or comment out one of the elements from the hero array.
The browser should refresh automatically and the message should disappear.
## Summary
Now you know how to use:
- **Interpolation** with double curly braces to display a component property.
- **ngFor** to display !{_an} !{_array} of items.
- A !{_Lang} class to shape the **model data** for your component and display properties of that model.
- **ngFor** to display an array of items.
- A TypeScript class to shape the **model data** for your component and display properties of that model.
- **ngIf** to conditionally display a chunk of HTML based on a boolean expression.
Here's the final code:
<code-tabs>
<code-pane title="src/app/app.component.ts" path="displaying-data/src/app/app.component.ts" region="final">
</code-pane>
<code-pane title="src/app/hero.ts" path="displaying-data/src/app/hero.ts">
</code-pane>
<code-pane title="src/app/app.module.ts" path="displaying-data/src/app/app.module.ts">
</code-pane>
<code-pane title="main.ts" path="displaying-data/src/main.ts">
</code-pane>
</code-tabs>
@@ -37,7 +37,6 @@ Before components can be added we have to define an anchor point to mark where c
The ad banner uses a helper directive called `AdDirective` to mark valid insertion points in the template.
<code-example path="cb-dynamic-component-loader/src/app/ad.directive.ts" linenums="false">
</code-example>
@@ -51,39 +50,28 @@ The next step is to implement the ad banner. Most of the implementation is in `A
We start by adding a `template` element with the `AdDirective` directive applied.
<code-tabs>
<code-pane title="ad-banner.component.ts" path="cb-dynamic-component-loader/src/app/ad-banner.component.ts">
</code-pane>
<code-pane title="ad.service.ts" path="cb-dynamic-component-loader/src/app/ad.service.ts">
</code-pane>
<code-pane title="ad-item.ts" path="cb-dynamic-component-loader/src/app/ad-item.ts">
</code-pane>
<code-pane title="app.module.ts" path="cb-dynamic-component-loader/src/app/app.module.ts">
</code-pane>
<code-pane title="app.component" path="cb-dynamic-component-loader/src/app/app.component.ts">
</code-pane>
</code-tabs>
The `template` element decorated with the `ad-host` directive marks where dynamically loaded components will be added.
@@ -91,7 +79,6 @@ The `template` element decorated with the `ad-host` directive marks where dynami
Using a `template` element is recommended since it doesn't render any additional output.
<code-example path="cb-dynamic-component-loader/src/app/ad-banner.component.ts" region="ad-host" linenums="false">
</code-example>
@@ -115,7 +102,6 @@ Generally the compiler will generate a component factory for any component refer
With dynamically loaded components there are no selector references in the templates since components are loaded at runtime. In order to ensure that the compiler will still generate a factory, dynamically loaded components have to be added to their `NgModule`'s `entryComponents` array.
<code-example path="cb-dynamic-component-loader/src/app/app.module.ts" region="entry-components" linenums="false">
</code-example>
@@ -129,27 +115,20 @@ In the Ad banner, all components implement a common `AdComponent` interface to s
Two sample components and the `AdComponent` interface are shown below:
<code-tabs>
<code-pane title="hero-job-ad.component.ts" path="cb-dynamic-component-loader/src/app/hero-job-ad.component.ts">
</code-pane>
<code-pane title="hero-profile.component.ts" path="cb-dynamic-component-loader/src/app/hero-profile.component.ts">
</code-pane>
<code-pane title="ad.component.ts" path="cb-dynamic-component-loader/src/app/ad.component.ts">
</code-pane>
</code-tabs>
The final ad banner looks like this:
-21
View File
@@ -43,21 +43,16 @@ Reactive Forms belongs to a different `NgModule` called `ReactiveFormsModule`, s
We bootstrap our `AppModule` in main.ts.
<code-tabs>
<code-pane title="app.module.ts" path="cb-dynamic-form/src/app/app.module.ts">
</code-pane>
<code-pane title="main.ts" path="cb-dynamic-form/src/main.ts">
</code-pane>
</code-tabs>
@@ -70,7 +65,6 @@ The "question" is the most fundamental object in the model.
We have created `QuestionBase` as the most fundamental question class.
<code-example path="cb-dynamic-form/src/app/question-base.ts">
</code-example>
@@ -81,7 +75,6 @@ The idea is that the form will be bound to specific question types and render th
`TextboxQuestion` supports multiple html5 types like text, email, url etc via the `type` property.
<code-example path="cb-dynamic-form/src/app/question-textbox.ts" linenums="false">
</code-example>
@@ -89,7 +82,6 @@ The idea is that the form will be bound to specific question types and render th
`DropdownQuestion` presents a list of choices in a select box.
<code-example path="cb-dynamic-form/src/app/question-dropdown.ts" linenums="false">
</code-example>
@@ -98,7 +90,6 @@ Next we have defined `QuestionControlService`, a simple service for transforming
In a nutshell, the form group consumes the metadata from the question model and allows us to specify default values and validation rules.
<code-example path="cb-dynamic-form/src/app/question-control.service.ts" linenums="false">
</code-example>
@@ -107,21 +98,16 @@ In a nutshell, the form group consumes the metadata from the question model and
Now that we have defined the complete model we are ready to create components to represent the dynamic form.
`DynamicFormComponent` is the entry point and the main container for the form.
<code-tabs>
<code-pane title="dynamic-form.component.html" path="cb-dynamic-form/src/app/dynamic-form.component.html">
</code-pane>
<code-pane title="dynamic-form.component.ts" path="cb-dynamic-form/src/app/dynamic-form.component.ts">
</code-pane>
</code-tabs>
It presents a list of questions, each question bound to a `<df-question>` component element.
@@ -129,21 +115,16 @@ The `<df-question>` tag matches the `DynamicFormQuestionComponent`,
the component responsible for rendering the details of each _individual_ question based on values in the data-bound question object.
<code-tabs>
<code-pane title="dynamic-form-question.component.html" path="cb-dynamic-form/src/app/dynamic-form-question.component.html">
</code-pane>
<code-pane title="dynamic-form-question.component.ts" path="cb-dynamic-form/src/app/dynamic-form-question.component.ts">
</code-pane>
</code-tabs>
Notice this component can present any type of question in our model.
@@ -163,7 +144,6 @@ underlying control objects, populated from the question model with display and v
Questionnaire maintenance is a simple matter of adding, updating, and removing objects from the `questions` array.
<code-example path="cb-dynamic-form/src/app/question.service.ts">
</code-example>
@@ -171,7 +151,6 @@ underlying control objects, populated from the question model with display and v
Finally, we display an instance of the form in the `AppComponent` shell.
<code-example path="cb-dynamic-form/src/app/app.component.ts">
</code-example>
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -79,7 +79,7 @@ Thus, a provider in an intermediate injector intercepts a request for a service
It effectively "reconfigures" and "shadows" a provider at a higher level in the tree.
If you only specify providers at the top level (typically the root `AppModule`), the tree of injectors appears to be flat.
All requests bubble up to the root <span if-docs="ts"><code>NgModule</code></span> injector that you configured with the `!{_bootstrapModule}` method.
All requests bubble up to the root <code>NgModule</code> injector that you configured with the `bootstrapModule` method.
## Component injectors
@@ -101,7 +101,6 @@ That's not supposed to happen but providing the service in the root `AppModule`
Instead, provide the `VillainsService` in the `providers` metadata of the `VillainsListComponent` like this:
<code-example path="hierarchical-dependency-injection/src/app/villains-list.component.ts" linenums="false" title="src/app/villains-list.component.ts (metadata)" region="metadata">
</code-example>
@@ -145,7 +144,6 @@ It caches a single `HeroTaxReturn`, tracks changes to that return, and can save
It also delegates to the application-wide singleton `HeroService`, which it gets by injection.
<code-example path="hierarchical-dependency-injection/src/app/hero-tax-return.service.ts">
</code-example>
@@ -153,7 +151,6 @@ It also delegates to the application-wide singleton `HeroService`, which it gets
Here is the `HeroTaxReturnComponent` that makes use of it.
<code-example path="hierarchical-dependency-injection/src/app/hero-tax-return.component.ts">
</code-example>
@@ -171,7 +168,6 @@ What a mess!
Look closely at the metadata for the `HeroTaxReturnComponent`. Notice the `providers` property.
<code-example path="hierarchical-dependency-injection/src/app/hero-tax-return.component.ts" linenums="false" title="src/app/hero-tax-return.component.ts (providers)" region="providers">
</code-example>
-33
View File
@@ -85,7 +85,6 @@ After translation, the compiler removes it.
In the accompanying sample, an `<h1>` tag displays a simple English language greeting
that you translate into Spanish:
<code-example path="cb-i18n/src/app/app.component.1.html" region="greeting" linenums="false">
</code-example>
@@ -93,7 +92,6 @@ that you translate into Spanish:
Add the `i18n` attribute to the tag to mark it for translation.
<code-example path="cb-i18n/src/app/app.component.1.html" region="i18n-attribute" linenums="false">
</code-example>
@@ -105,7 +103,6 @@ need a description of the message.
Assign a description to the i18n attribute:
<code-example path="cb-i18n/src/app/app.component.1.html" region="i18n-attribute-desc" linenums="false">
</code-example>
@@ -117,7 +114,6 @@ In front of the description, add some contextual meaning to the assigned string,
separating it from the description with the `|` character (`<meaning>|<description>`):
<code-example path="cb-i18n/src/app/app.component.html" region="i18n-attribute-meaning" linenums="false">
</code-example>
@@ -138,7 +134,6 @@ Here are two techniques to try.
(1) Wrap the text in an `<ng-container>` element. The `<ng-container>` is never renderered:
<code-example path="cb-i18n/src/app/app.component.html" region="i18n-ng-container" linenums="false">
</code-example>
@@ -146,7 +141,6 @@ Here are two techniques to try.
(2) Wrap the text in a pair of HTML comments:
<code-example path="cb-i18n/src/app/app.component.html" region="i18n-with-comment" linenums="false">
</code-example>
@@ -159,7 +153,6 @@ Here are two techniques to try.
You've added an image to your template. You care about accessibility too so you add a `title` attribute:
<code-example path="cb-i18n/src/app/app.component.1.html" region="i18n-title" linenums="false">
</code-example>
@@ -171,7 +164,6 @@ name of the attribute to translate.
To translate the `title` on the `img` tag from the previous example, write:
<code-example path="cb-i18n/src/app/app.component.html" region="i18n-title-translate" linenums="false">
</code-example>
@@ -192,7 +184,6 @@ Other languages might express the _cardinality_ differently.
Here's how you could mark up the component template to display the phrase appropriate to the number of wolves:
<code-example path="cb-i18n/src/app/app.component.html" region="i18n-plural" linenums="false">
</code-example>
@@ -249,7 +240,6 @@ property, which outputs either an "m" or an "f".
The message maps those values to the appropriate translation:
<code-example path="cb-i18n/src/app/app.component.html" region="i18n-select" linenums="false">
</code-example>
@@ -394,7 +384,6 @@ This sample file is easy to translate without a special editor or knowledge of S
Open `messages.es.xlf` and find the first `<trans-unit>` section:
<code-example path="cb-i18n/src/locale/messages.es.xlf.html" region="translated-hello" linenums="false">
</code-example>
@@ -404,7 +393,6 @@ This XML element represents the translation of the `<h1>` greeting tag you marke
Using the _source_, _description_, and _meaning_ elements to guide your translation,
replace the `<target/>` tag with the Spanish greeting:
<code-example path="cb-i18n/src/locale/messages.es.xlf.html" region="translated-hello" linenums="false">
</code-example>
@@ -424,7 +412,6 @@ See the **[translation file maintenance discussion](guide/i18n#maintenance)**.
Translate the other text nodes the same way:
<code-example path="cb-i18n/src/locale/messages.es.xlf.html" region="translated-other-nodes" linenums="false">
</code-example>
@@ -446,7 +433,6 @@ In this example, you know the translation unit for the `select` must be just bel
To translate a `plural`, translate its ICU format match values:
<code-example path="cb-i18n/src/locale/messages.es.xlf.html" region="translated-plural" linenums="false">
</code-example>
@@ -455,7 +441,6 @@ To translate a `plural`, translate its ICU format match values:
The `select` behaves a little differently. Here again is the ICU format message in the component template:
<code-example path="cb-i18n/src/app/app.component.html" region="i18n-select" linenums="false">
</code-example>
@@ -467,7 +452,6 @@ In place of the `select` is a placeholder, `<x id="ICU">`, that represents the `
Translate the text and leave the placeholder where it is.
<code-example path="cb-i18n/src/locale/messages.es.xlf.html" region="translate-select-1" linenums="false">
</code-example>
@@ -475,7 +459,6 @@ Translate the text and leave the placeholder where it is.
The second translation unit, immediately below the first one, contains the `select` message. Translate that.
<code-example path="cb-i18n/src/locale/messages.es.xlf.html" region="translate-select-2" linenums="false">
</code-example>
@@ -483,7 +466,6 @@ The second translation unit, immediately below the first one, contains the `sele
Here they are together, after translation:
<code-example path="cb-i18n/src/locale/messages.es.xlf.html" region="translated-select" linenums="false">
</code-example>
@@ -507,39 +489,28 @@ time to incorporate that translation into the application.
When the previous steps finish, the sample app _and_ its translation file are as follows:
<code-tabs>
<code-pane title="src/app/app.component.html" path="cb-i18n/src/app/app.component.html">
</code-pane>
<code-pane title="src/app/app.component.ts" path="cb-i18n/src/app/app.component.ts">
</code-pane>
<code-pane title="src/app/app.module.ts" path="cb-i18n/src/app/app.module.ts">
</code-pane>
<code-pane title="src/main.ts" path="cb-i18n/src/main.1.ts">
</code-pane>
<code-pane title="src/locale/messages.es.xlf" path="cb-i18n/src/locale/messages.es.xlf.html">
</code-pane>
</code-tabs>
@@ -580,7 +551,6 @@ Translation with the JIT compiler is a dynamic process of:
Open `index.html` and revise the launch script as follows:
<code-example path="cb-i18n/src/index.html" region="i18n" linenums="false">
</code-example>
@@ -600,7 +570,6 @@ You'll need it to import the language translation file.
SystemJS doesn't ship with a raw text plugin but it's easy to add.
Create the following `systemjs-text-plugin.js` in the `src/` folder:
<code-example path="cb-i18n/src/systemjs-text-plugin.js" linenums="false">
</code-example>
@@ -618,7 +587,6 @@ The `getTranslationProviders` function in the following `src/app/i18n-providers.
creates those providers based on the user's _locale_
and the corresponding translation file:
<code-example path="cb-i18n/src/app/i18n-providers.ts">
</code-example>
@@ -648,7 +616,6 @@ You'll create an _options_ object with the translation providers from `getTransl
and pass it to `bootstrapModule`.
Open the `src/main.ts` and modify the bootstrap code as follows:
<code-example path="cb-i18n/src/main.ts" linenums="false">
</code-example>
-40
View File
@@ -18,131 +18,91 @@ a collection of pages devoted to that theme.
<table width="100%">
<col width="15%">
</col>
<col>
</col>
<tr style=top>
<td>
<b><a href="../quickstart.html">QuickStart</a></b>
</td>
<td>
A first taste of Angular<span if-docs="ts"> with zero installation.
Run "Hello World" in an online code editor and start playing with live code</span>.
</td>
</tr>
<tr style=top>
<td>
<b>Guide</b>
</td>
<td>
Learn the Angular basics (you're already here!) like the setup for local development,
displaying data and accepting user input, injecting application services into components,
and building simple forms.
</td>
</tr>
<tr style=top>
<td>
<b><a href="../api/">API Reference</a></b>
</td>
<td>
Authoritative details about each of the Angular libraries.
</td>
</tr>
<tr style=top>
<td>
<b><a href="../tutorial/">Tutorial</a></b>
</td>
<td>
A step-by-step, immersive approach to learning Angular that
introduces the major features of Angular in an application context.
</td>
</tr>
<tr style=top>
<td>
<b><a href=" ">Advanced</a></b>
</td>
<td>
In-depth analysis of Angular features and development practices.
</td>
</tr>
<tr style=top if-docs="ts">
<td>
<b><a href="../cookbook/">Cookbook</a></b>
</td>
<td>
Recipes for specific application challenges, mostly code snippets with a minimum of exposition.
</td>
</tr>
</table>
A few early pages are written as tutorials and are clearly marked as such.
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+25 -51
View File
@@ -31,7 +31,6 @@ In this page, you'll use pipes to transform a component's birthday property into
a human-friendly date.
<code-example path="pipes/src/app/hero-birthday1.component.ts" linenums="false">
</code-example>
@@ -39,7 +38,6 @@ a human-friendly date.
Focus on the component's template.
<code-example path="pipes/src/app/app.component.html" region="hero-birthday-template" linenums="false">
</code-example>
@@ -92,7 +90,6 @@ Modify the birthday template to give the date pipe a format parameter.
After formatting the hero's April 15th birthday, it renders as **<samp>04/15/88</samp>**:
<code-example path="pipes/src/app/app.component.html" region="format-birthday" linenums="false">
</code-example>
@@ -107,7 +104,6 @@ Write a second component that *binds* the pipe's format parameter
to the component's `format` property. Here's the template for that component:
<code-example path="pipes/src/app/hero-birthday2.component.ts" region="template" linenums="false">
</code-example>
@@ -117,7 +113,6 @@ That method toggles the component's `format` property between a short form
(`'shortDate'`) and a longer form (`'fullDate'`).
<code-example path="pipes/src/app/hero-birthday2.component.ts" region="class" linenums="false">
</code-example>
@@ -149,7 +144,6 @@ the birthday is chained to the `DatePipe` and on to the `UpperCasePipe`.
The birthday displays as **<samp>APR 15, 1988</samp>**.
<code-example path="pipes/src/app/app.component.html" region="chained-birthday" linenums="false">
</code-example>
@@ -158,7 +152,6 @@ This example&mdash;which displays **<samp>FRIDAY, APRIL 15, 1988</samp>**&mdash;
the same pipes as above, but passes in a parameter to `date` as well.
<code-example path="pipes/src/app/app.component.html" region="chained-parameter-birthday" linenums="false">
</code-example>
@@ -170,7 +163,6 @@ You can write your own custom pipes.
Here's a custom pipe named `ExponentialStrengthPipe` that can boost a hero's powers:
<code-example path="pipes/src/app/exponential-strength.pipe.ts" linenums="false">
</code-example>
@@ -183,8 +175,8 @@ accepts an input value followed by optional parameters and returns the transform
* There will be one additional argument to the `transform` method for each parameter passed to the pipe.
Your pipe has one such parameter: the `exponent`.
* To tell Angular that this is a pipe, you apply the
`@Pipe` #{_decorator}, which you import from the core Angular library.
* The `@Pipe` #{_decorator} allows you to define the
`@Pipe` decorator, which you import from the core Angular library.
* The `@Pipe` decorator allows you to define the
pipe name that you'll use within template expressions. It must be a valid JavaScript identifier.
Your pipe's name is `exponentialStrength`.
@@ -202,7 +194,6 @@ Technically, it's optional; Angular looks for and executes the `transform` metho
Now you need a component to demonstrate the pipe.
<code-example path="pipes/src/app/power-booster.component.ts" linenums="false">
</code-example>
@@ -216,7 +207,7 @@ Now you need a component to demonstrate the pipe.
Note the following:
* You use your custom pipe the same way you use built-in pipes.
* You must include your pipe in the `!{_decls}` #{_array} of the `!{_appMod}`.
* You must include your pipe in the `declarations` array of the `AppModule`.
~~~ {.callout.is-helpful}
@@ -224,7 +215,7 @@ Note the following:
<header>
Remember the
Remember the declarations array
</header>
You must manually register custom pipes.
@@ -245,7 +236,6 @@ Upgrade the example to a "Power Boost Calculator" that combines
your pipe and two-way data binding with `ngModel`.
<code-example path="pipes/src/app/power-boost-calculator.component.ts">
</code-example>
@@ -271,37 +261,33 @@ Angular picks a simpler, faster change detection algorithm when you use a pipe.
### No pipe
In the next example, the component uses the default, aggressive change detection strategy to monitor and update
its display of every hero in the `heroes` #{_array}. Here's the template:
its display of every hero in the `heroes` array. Here's the template:
<code-example path="pipes/src/app/flying-heroes.component.html" region="template-1" linenums="false">
</code-example>
The companion component class provides heroes, adds heroes into the #{_array}, and can reset the #{_array}.
The companion component class provides heroes, adds heroes into the array, and can reset the array.
<code-example path="pipes/src/app/flying-heroes.component.ts" region="v1" linenums="false">
</code-example>
You can add heroes and Angular updates the display when you do.
If you click the `reset` button, Angular replaces `heroes` with a new #{_array} of the original heroes and updates the display.
If you click the `reset` button, Angular replaces `heroes` with a new array of the original heroes and updates the display.
If you added the ability to remove or change a hero, Angular would detect those changes and update the display as well.
### Flying-heroes pipe
Add a `FlyingHeroesPipe` to the `*ngFor` repeater that filters the list of heroes to just those heroes who can fly.
<code-example path="pipes/src/app/flying-heroes.component.html" region="template-flying-heroes" linenums="false">
</code-example>
Here's the `FlyingHeroesPipe` implementation, which follows the pattern for custom pipes described earlier.
<code-example path="pipes/src/app/flying-heroes.pipe.ts" region="pure" linenums="false">
</code-example>
@@ -314,20 +300,19 @@ It's just using a different change-detection algorithm that ignores changes to t
Notice how a hero is added:
<code-example path="pipes/src/app/flying-heroes.component.ts" region="push" linenums="false">
</code-example>
You add the hero into the `heroes` #{_array}. The reference to the #{_array} hasn't changed.
It's the same #{_array}. That's all Angular cares about. From its perspective, *same #{_array}, no change, no display update*.
You add the hero into the `heroes` array. The reference to the array hasn't changed.
It's the same array. That's all Angular cares about. From its perspective, *same array, no change, no display update*.
To fix that, create an #{_array} with the new hero appended and assign that to `heroes`.
This time Angular detects that the #{_array} reference has changed.
It executes the pipe and updates the display with the new #{_array}, which includes the new flying hero.
To fix that, create an array with the new hero appended and assign that to `heroes`.
This time Angular detects that the array reference has changed.
It executes the pipe and updates the display with the new array, which includes the new flying hero.
If you *mutate* the #{_array}, no pipe is invoked and the display isn't updated;
if you *replace* the #{_array}, the pipe executes and the display is updated.
If you *mutate* the array, no pipe is invoked and the display isn't updated;
if you *replace* the array, the pipe executes and the display is updated.
The Flying Heroes application extends the
code with checkbox switches and additional displays to help you experience these effects.
@@ -336,8 +321,8 @@ code with checkbox switches and additional displays to help you experience these
<img src='assets/images/devguide/pipes/flying-heroes-anim.gif' alt="Flying Heroes"> </img>
</figure>
Replacing the #{_array} is an efficient way to signal Angular to update the display.
When do you replace the #{_array}? When the data change.
Replacing the array is an efficient way to signal Angular to update the display.
When do you replace the array? When the data change.
That's an easy rule to follow in *this* example
where the only way to change the data is by adding a hero.
@@ -359,7 +344,6 @@ You make a pipe impure by setting its pure flag to false. You could make the `Fl
impure like this:
<code-example path="pipes/src/app/flying-heroes.pipe.ts" region="pipe-decorator" linenums="false">
</code-example>
@@ -373,7 +357,7 @@ A pure change is either a change to a primitive input value (`String`, `Number`,
or a changed object reference (`Date`, `Array`, `Function`, `Object`).
Angular ignores changes within (composite) objects.
It won't call a pure pipe if you change an input month, add to an input #{_array}, or update an input object property.
It won't call a pure pipe if you change an input month, add to an input array, or update an input object property.
This may seem restrictive but it's also fast.
An object reference check is fast&mdash;much faster than a deep check for
@@ -407,21 +391,16 @@ An expensive, long-running pipe could destroy the user experience.
A flip of the switch turns the `FlyingHeroesPipe` into a `FlyingHeroesImpurePipe`.
The complete implementation is as follows:
<code-tabs>
<code-pane title="FlyingHeroesImpurePipe" path="pipes/src/app/flying-heroes.pipe.ts" region="impure">
</code-pane>
<code-pane title="FlyingHeroesPipe" path="pipes/src/app/flying-heroes.pipe.ts" region="pure">
</code-pane>
</code-tabs>
You inherit from `FlyingHeroesPipe` to prove the point that nothing changed internally.
@@ -430,7 +409,6 @@ The only difference is the `pure` flag in the pipe metadata.
This is a good candidate for an impure pipe because the `transform` function is trivial and fast.
<code-example path="pipes/src/app/flying-heroes.pipe.ts" linenums="false" title="src/app/flying-heroes.pipe.ts (filter)" region="filter">
</code-example>
@@ -438,14 +416,13 @@ This is a good candidate for an impure pipe because the `transform` function is
You can derive a `FlyingHeroesImpureComponent` from `FlyingHeroesComponent`.
<code-example path="pipes/src/app/flying-heroes" linenums="false" title="src/app/flying-heroes (_region)" region="_region">
<code-example path="pipes/src/app/flying-heroes-impure.component.html" linenums="false" title="src/app/flying-heroes-impure.component.html (excerpt)" region="template-flying-heroes">
</code-example>
The only substantive change is the pipe in the template.
You can confirm in the <live-example></live-example> that the _flying heroes_
display updates as you add heroes, even when you mutate the `heroes` #{_array}.
display updates as you add heroes, even when you mutate the `heroes` array.
<h3 id='async-pipe'>
@@ -453,16 +430,15 @@ display updates as you add heroes, even when you mutate the `heroes` #{_array}.
</h3>
The Angular `AsyncPipe` is an interesting example of an impure pipe.
The `AsyncPipe` accepts a `#{_Promise}` or `#{_Observable}` as input
The `AsyncPipe` accepts a `Promise` or `Observable` as input
and subscribes to the input automatically, eventually returning the emitted values.
The `AsyncPipe` is also stateful.
The pipe maintains a subscription to the input `#{_Observable}` and
keeps delivering values from that `#{_Observable}` as they arrive.
This next example binds an `#{_Observable}` of message strings
(`message#{_dollar}`) to a view with the `async` pipe.
The pipe maintains a subscription to the input `Observable` and
keeps delivering values from that `Observable` as they arrive.
This next example binds an `Observable` of message strings
(`message$`) to a view with the `async` pipe.
<code-example path="pipes/src/app/hero-async-message.component.ts">
@@ -483,8 +459,7 @@ Remember that impure pipes are called every few milliseconds.
If you're not careful, this pipe will punish the server with requests.
In the following code, the pipe only calls the server when the request URL changes and it caches the server response.
The code<span if-docs="ts"> uses the [Angular http](guide/server-communication) client to retrieve data</span>:
The code uses the [Angular http](guide/server-communication) client to retrieve data</span>:
<code-example path="pipes/src/app/fetch-json.pipe.ts">
@@ -495,7 +470,6 @@ Now demonstrate it in a harness component whose template defines two bindings to
both requesting the heroes from the `heroes.json` file.
<code-example path="pipes/src/app/hero-list.component.ts">
</code-example>
+25 -5
View File
@@ -4,7 +4,6 @@ Angular applications are made up of _components_.
A _component_ is the combination of an HTML template and a component class that controls a portion of the screen. Here is an example of a component that displays a simple string:
<code-example path="quickstart/src/app/app.component.ts" linenums="false">
</code-example>
@@ -21,13 +20,11 @@ and prepare for development of a real Angular application.
~~~
Every component begins with an `@Component` [!{_decorator}](guide/glossary)
<span if-docs="ts">function</span> that
<span if-docs="ts">takes a _metadata_ object. The metadata object</span> describes how the HTML template and component class work together.
Every component begins with an `@Component` [decorator](guide/glossary)
function that takes a _metadata_ object. The metadata object describes how the HTML template and component class work together.
The `selector` property tells Angular to display the component inside a custom `<my-app>` tag in the `index.html`.
<code-example path="quickstart/src/index.html" region="my-app" linenums="false">
</code-example>
@@ -37,6 +34,29 @@ The message starts with "Hello" and ends with `{{name}}`,
which is an Angular [interpolation binding](guide/guide/displaying-data) expression.
At runtime, Angular replaces `{{name}}` with the value of the component's `name` property.
Interpolation binding is one of many Angular features you'll discover in this documentation.
In the example, change the component class's `name` property from `'Angular'` to `'World'` and see what happens.
~~~ {.callout.is-helpful}
<header>
A word about TypeScript
</header>
<p>
This example is written in <a href="http://www.typescriptlang.org/" target="_blank" title="TypeScript">TypeScript</a>, a superset of JavaScript. Angular
uses TypeScript because its types make it easy to support developer productivity with tooling. You can also write Angular code in JavaScript; <a href="cookbook/ts-to-js.html">this guide</a> explains how.
</p>
~~~
~~~ {.l-sub-section}
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+9 -9
View File
@@ -12,6 +12,15 @@ scripting attacks. It doesn't cover application-level security, such as authenti
this user?_) and authorization (_What can this user do?_).
For more information about the attacks and mitigations described below, see [OWASP Guide Project](https://www.owasp.org/index.php/Category:OWASP_Guide_Project).
# Contents
* [Reporting vulnerabilities](guide/security#report-issues).
* [Best practices](guide/security#best-practices).
* [Preventing cross-site scripting (XSS)](guide/security#xss).
* [Trusting safe values](guide/security#bypass-security-apis).
* [HTTP-Level vulnerabilities](guide/security#http).
* [Auditing Angular applications](guide/security#code-review).
You can run the <live-example></live-example> in Plunker and download the code from there.
@@ -97,7 +106,6 @@ The following template binds the value of `htmlSnippet`, once by interpolating i
content, and once by binding it to the `innerHTML` property of an element:
<code-example path="security/src/app/inner-html-binding.component.html">
</code-example>
@@ -110,12 +118,10 @@ a value that an attacker might control into `innerHTML` normally causes an XSS
vulnerability. For example, code contained in a `<script>` tag is executed:
<code-example path="security/src/app/inner-html-binding.component.ts" linenums="false" title="src/app/inner-html-binding.component.ts (class)" region="class">
</code-example>
Angular recognizes the value as unsafe and automatically sanitizes it, which removes the `<script>`
tag but keeps safe content such as the text content of the `<script>` tag and the `<b>` element.
@@ -160,7 +166,6 @@ carries a high risk of introducing template-injection vulnerabilities.
<h2 id='bypass-security-apis'>
Trusting safe values
</h2>
@@ -186,7 +191,6 @@ your intended use of the value. Imagine that the following template needs to bin
`javascript:alert(...)` call:
<code-example path="security/src/app/bypass-security.component.html" linenums="false" title="src/app/bypass-security.component.html (URL)" region="URL">
</code-example>
@@ -196,7 +200,6 @@ in development mode, logs this action to the console. To prevent
this, mark the URL value as a trusted URL using the `bypassSecurityTrustUrl` call:
<code-example path="security/src/app/bypass-security.component.ts" linenums="false" title="src/app/bypass-security.component.ts (trust-url)" region="trust-url">
</code-example>
@@ -215,14 +218,12 @@ could execute. So call a method on the controller to construct a trusted video U
Angular to allow binding into `<iframe src>`:
<code-example path="security/src/app/bypass-security.component.html" linenums="false" title="src/app/bypass-security.component.html (iframe)" region="iframe">
</code-example>
<code-example path="security/src/app/bypass-security.component.ts" linenums="false" title="src/app/bypass-security.component.ts (trust-video-url)" region="trust-video-url">
</code-example>
@@ -230,7 +231,6 @@ Angular to allow binding into `<iframe src>`:
<h2 id='http'>
HTTP-level vulnerabilities
</h2>

Some files were not shown because too many files have changed in this diff Show More