docs(aio): ensure blank lines before HTML blocks in markdown
This commit is contained in:
parent
8ef621ad2a
commit
2d14c3b17a
@ -24,6 +24,7 @@ You'll pursue these ends in the following high-level steps:
|
|||||||
And you can also <a href="/resources/zips/cli-quickstart/cli-quickstart.zip">download the example.</a>
|
And you can also <a href="/resources/zips/cli-quickstart/cli-quickstart.zip">download the example.</a>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<h2 id='devenv'>
|
<h2 id='devenv'>
|
||||||
Step 1. Set up the Development Environment
|
Step 1. Set up the Development Environment
|
||||||
</h2>
|
</h2>
|
||||||
@ -43,6 +44,7 @@ Older versions produce errors, but newer versions are fine.
|
|||||||
|
|
||||||
Then **install the [Angular CLI](https://github.com/angular/angular-cli)** globally.
|
Then **install the [Angular CLI](https://github.com/angular/angular-cli)** globally.
|
||||||
|
|
||||||
|
|
||||||
<code-example language="sh" class="code-shell">
|
<code-example language="sh" class="code-shell">
|
||||||
npm install -g @angular/cli
|
npm install -g @angular/cli
|
||||||
|
|
||||||
@ -50,6 +52,7 @@ Then **install the [Angular CLI](https://github.com/angular/angular-cli)** globa
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<h2 id='create-project'>
|
<h2 id='create-project'>
|
||||||
Step 2. Create a new project
|
Step 2. Create a new project
|
||||||
</h2>
|
</h2>
|
||||||
@ -57,6 +60,7 @@ Then **install the [Angular CLI](https://github.com/angular/angular-cli)** globa
|
|||||||
Open a terminal window.
|
Open a terminal window.
|
||||||
Generate a new project and skeleton application by running the following commands:
|
Generate a new project and skeleton application by running the following commands:
|
||||||
|
|
||||||
|
|
||||||
<code-example language="sh" class="code-shell">
|
<code-example language="sh" class="code-shell">
|
||||||
ng new my-app
|
ng new my-app
|
||||||
|
|
||||||
@ -74,12 +78,14 @@ It takes time to set up a new project, most of it spent installing npm packages.
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<h2 id='serve'>
|
<h2 id='serve'>
|
||||||
Step 3: Serve the application
|
Step 3: Serve the application
|
||||||
</h2>
|
</h2>
|
||||||
|
|
||||||
Go to the project directory and launch the server.
|
Go to the project directory and launch the server.
|
||||||
|
|
||||||
|
|
||||||
<code-example language="sh" class="code-shell">
|
<code-example language="sh" class="code-shell">
|
||||||
cd my-app
|
cd my-app
|
||||||
ng serve --open
|
ng serve --open
|
||||||
@ -94,12 +100,14 @@ on `http://localhost:4200/`.
|
|||||||
|
|
||||||
Your app greets you with a message:
|
Your app greets you with a message:
|
||||||
|
|
||||||
|
|
||||||
<figure class='image-display'>
|
<figure class='image-display'>
|
||||||
<img src='assets/images/devguide/cli-quickstart/app-works.png' alt="The app works!"> </img>
|
<img src='assets/images/devguide/cli-quickstart/app-works.png' alt="The app works!"> </img>
|
||||||
</figure>
|
</figure>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<h2 id='first-component'>
|
<h2 id='first-component'>
|
||||||
Step 4: Edit your first Angular component
|
Step 4: Edit your first Angular component
|
||||||
</h2>
|
</h2>
|
||||||
@ -110,6 +118,7 @@ You can find it in `./src/app/app.component.ts`.
|
|||||||
Open the component file and change the `title` property from _app works!_ to _My First Angular App_:
|
Open the component file and change the `title` property from _app works!_ to _My First Angular App_:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="cli-quickstart/src/app/app.component.ts" region="title" linenums="false">
|
<code-example path="cli-quickstart/src/app/app.component.ts" region="title" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -119,11 +128,13 @@ The browser reloads automatically with the revised title. That's nice, but it co
|
|||||||
Open `src/app/app.component.css` and give the component some style.
|
Open `src/app/app.component.css` and give the component some style.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="cli-quickstart/src/app/app.component.css" linenums="false">
|
<code-example path="cli-quickstart/src/app/app.component.css" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<figure class='image-display'>
|
<figure class='image-display'>
|
||||||
<img src='assets/images/devguide/cli-quickstart/my-first-app.png' alt="Output of QuickStart app"> </img>
|
<img src='assets/images/devguide/cli-quickstart/my-first-app.png' alt="Output of QuickStart app"> </img>
|
||||||
</figure>
|
</figure>
|
||||||
@ -155,32 +166,40 @@ Your app lives in the `src` folder.
|
|||||||
All Angular components, templates, styles, images, and anything else your app needs go here.
|
All Angular components, templates, styles, images, and anything else your app needs go here.
|
||||||
Any files outside of this folder are meant to support building your app.
|
Any files outside of this folder are meant to support building your app.
|
||||||
|
|
||||||
|
|
||||||
<aio-filetree>
|
<aio-filetree>
|
||||||
|
|
||||||
|
|
||||||
<aio-folder>
|
<aio-folder>
|
||||||
src
|
src
|
||||||
|
|
||||||
<aio-folder>
|
<aio-folder>
|
||||||
app
|
app
|
||||||
|
|
||||||
<aio-file>
|
<aio-file>
|
||||||
app.component.css
|
app.component.css
|
||||||
</aio-file>
|
</aio-file>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<aio-file>
|
<aio-file>
|
||||||
app.component.html
|
app.component.html
|
||||||
</aio-file>
|
</aio-file>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<aio-file>
|
<aio-file>
|
||||||
app.component.spec.ts
|
app.component.spec.ts
|
||||||
</aio-file>
|
</aio-file>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<aio-file>
|
<aio-file>
|
||||||
app.component.ts
|
app.component.ts
|
||||||
</aio-file>
|
</aio-file>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<aio-file>
|
<aio-file>
|
||||||
app.module.ts
|
app.module.ts
|
||||||
</aio-file>
|
</aio-file>
|
||||||
@ -189,8 +208,10 @@ Any files outside of this folder are meant to support building your app.
|
|||||||
</aio-folder>
|
</aio-folder>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<aio-folder>
|
<aio-folder>
|
||||||
assets
|
assets
|
||||||
|
|
||||||
<aio-file>
|
<aio-file>
|
||||||
.gitkeep
|
.gitkeep
|
||||||
</aio-file>
|
</aio-file>
|
||||||
@ -199,13 +220,16 @@ Any files outside of this folder are meant to support building your app.
|
|||||||
</aio-folder>
|
</aio-folder>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<aio-folder>
|
<aio-folder>
|
||||||
environments
|
environments
|
||||||
|
|
||||||
<aio-file>
|
<aio-file>
|
||||||
environment.prod.ts
|
environment.prod.ts
|
||||||
</aio-file>
|
</aio-file>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<aio-file>
|
<aio-file>
|
||||||
environment.ts
|
environment.ts
|
||||||
</aio-file>
|
</aio-file>
|
||||||
@ -214,41 +238,49 @@ Any files outside of this folder are meant to support building your app.
|
|||||||
</aio-folder>
|
</aio-folder>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<aio-file>
|
<aio-file>
|
||||||
favicon.ico
|
favicon.ico
|
||||||
</aio-file>
|
</aio-file>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<aio-file>
|
<aio-file>
|
||||||
index.html
|
index.html
|
||||||
</aio-file>
|
</aio-file>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<aio-file>
|
<aio-file>
|
||||||
main.ts
|
main.ts
|
||||||
</aio-file>
|
</aio-file>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<aio-file>
|
<aio-file>
|
||||||
polyfills.ts
|
polyfills.ts
|
||||||
</aio-file>
|
</aio-file>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<aio-file>
|
<aio-file>
|
||||||
styles.css
|
styles.css
|
||||||
</aio-file>
|
</aio-file>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<aio-file>
|
<aio-file>
|
||||||
test.ts
|
test.ts
|
||||||
</aio-file>
|
</aio-file>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<aio-file>
|
<aio-file>
|
||||||
tsconfig.app.json
|
tsconfig.app.json
|
||||||
</aio-file>
|
</aio-file>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<aio-file>
|
<aio-file>
|
||||||
tsconfig.spec.json
|
tsconfig.spec.json
|
||||||
</aio-file>
|
</aio-file>
|
||||||
@ -260,30 +292,37 @@ Any files outside of this folder are meant to support building your app.
|
|||||||
</aio-filetree>
|
</aio-filetree>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
td, th {vertical-align: top}
|
td, th {vertical-align: top}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<table width="100%">
|
<table width="100%">
|
||||||
|
|
||||||
|
|
||||||
<col width="20%">
|
<col width="20%">
|
||||||
|
|
||||||
</col>
|
</col>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<col width="80%">
|
<col width="80%">
|
||||||
|
|
||||||
</col>
|
</col>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
|
|
||||||
|
|
||||||
<th>
|
<th>
|
||||||
File
|
File
|
||||||
</th>
|
</th>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<th>
|
<th>
|
||||||
Purpose
|
Purpose
|
||||||
</th>
|
</th>
|
||||||
@ -292,13 +331,16 @@ Any files outside of this folder are meant to support building your app.
|
|||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
<code>app/app.component.{ts,html,css,spec.ts}</code>
|
<code>app/app.component.{ts,html,css,spec.ts}</code>
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
Defines the `AppComponent` along with an HTML template, CSS stylesheet, and a unit test.
|
Defines the `AppComponent` along with an HTML template, CSS stylesheet, and a unit test.
|
||||||
It is the **root** component of what will become a tree of nested components
|
It is the **root** component of what will become a tree of nested components
|
||||||
@ -309,13 +351,16 @@ Any files outside of this folder are meant to support building your app.
|
|||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
<code>app/app.module.ts</code>
|
<code>app/app.module.ts</code>
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
Defines `AppModule`, the [root module](guide/appmodule) that tells Angular how to assemble the application.
|
Defines `AppModule`, the [root module](guide/appmodule) that tells Angular how to assemble the application.
|
||||||
Right now it declares only the `AppComponent`.
|
Right now it declares only the `AppComponent`.
|
||||||
@ -326,13 +371,16 @@ Any files outside of this folder are meant to support building your app.
|
|||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
<code>assets/*</code>
|
<code>assets/*</code>
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
A folder where you can put images and anything else to be copied wholesale
|
A folder where you can put images and anything else to be copied wholesale
|
||||||
when you build your application.
|
when you build your application.
|
||||||
@ -342,13 +390,16 @@ Any files outside of this folder are meant to support building your app.
|
|||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
<code>environments/*</code>
|
<code>environments/*</code>
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
This folder contains one file for each of your destination environments,
|
This folder contains one file for each of your destination environments,
|
||||||
each exporting simple configuration variables to use in your application.
|
each exporting simple configuration variables to use in your application.
|
||||||
@ -363,13 +414,16 @@ Any files outside of this folder are meant to support building your app.
|
|||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
<code>favicon.ico</code>
|
<code>favicon.ico</code>
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
Every site wants to look good on the bookmark bar.
|
Every site wants to look good on the bookmark bar.
|
||||||
Get started with your very own Angular icon.
|
Get started with your very own Angular icon.
|
||||||
@ -379,13 +433,16 @@ Any files outside of this folder are meant to support building your app.
|
|||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
<code>index.html</code>
|
<code>index.html</code>
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
The main HTML page that is served when someone visits your site.
|
The main HTML page that is served when someone visits your site.
|
||||||
Most of the time you'll never need to edit it.
|
Most of the time you'll never need to edit it.
|
||||||
@ -397,13 +454,16 @@ Any files outside of this folder are meant to support building your app.
|
|||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
<code>main.ts</code>
|
<code>main.ts</code>
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
The main entry point for your app.
|
The main entry point for your app.
|
||||||
Compiles the application with the [JIT compiler](glossary)
|
Compiles the application with the [JIT compiler](glossary)
|
||||||
@ -416,13 +476,16 @@ Any files outside of this folder are meant to support building your app.
|
|||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
<code>polyfills.ts</code>
|
<code>polyfills.ts</code>
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
Different browsers have different levels of support of the web standards.
|
Different browsers have different levels of support of the web standards.
|
||||||
Polyfills help normalize those differences.
|
Polyfills help normalize those differences.
|
||||||
@ -434,13 +497,16 @@ Any files outside of this folder are meant to support building your app.
|
|||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
<code>styles.css</code>
|
<code>styles.css</code>
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
Your global styles go here.
|
Your global styles go here.
|
||||||
Most of the time you'll want to have local styles in your components for easier maintenance,
|
Most of the time you'll want to have local styles in your components for easier maintenance,
|
||||||
@ -451,13 +517,16 @@ Any files outside of this folder are meant to support building your app.
|
|||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
<code>test.ts</code>
|
<code>test.ts</code>
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
This is the main entry point for your unit tests.
|
This is the main entry point for your unit tests.
|
||||||
It has some custom configuration that might be unfamiliar, but it's not something you'll
|
It has some custom configuration that might be unfamiliar, but it's not something you'll
|
||||||
@ -468,13 +537,16 @@ Any files outside of this folder are meant to support building your app.
|
|||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
<code>tsconfig.{app|spec}.json</code>
|
<code>tsconfig.{app|spec}.json</code>
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
TypeScript compiler configuration for the Angular app (`tsconfig.app.json`)
|
TypeScript compiler configuration for the Angular app (`tsconfig.app.json`)
|
||||||
and for the unit tests (`tsconfig.spec.json`).
|
and for the unit tests (`tsconfig.spec.json`).
|
||||||
@ -494,22 +566,28 @@ The `src/` folder is just one of the items inside the project's root folder.
|
|||||||
Other files help you build, test, maintain, document, and deploy the app.
|
Other files help you build, test, maintain, document, and deploy the app.
|
||||||
These files go in the root folder next to `src/`.
|
These files go in the root folder next to `src/`.
|
||||||
|
|
||||||
|
|
||||||
<aio-filetree>
|
<aio-filetree>
|
||||||
|
|
||||||
|
|
||||||
<aio-folder>
|
<aio-folder>
|
||||||
my-app
|
my-app
|
||||||
|
|
||||||
<aio-folder>
|
<aio-folder>
|
||||||
e2e
|
e2e
|
||||||
|
|
||||||
<aio-file>
|
<aio-file>
|
||||||
app.e2e-spec.ts
|
app.e2e-spec.ts
|
||||||
</aio-file>
|
</aio-file>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<aio-file>
|
<aio-file>
|
||||||
app.po.ts
|
app.po.ts
|
||||||
</aio-file>
|
</aio-file>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<aio-file>
|
<aio-file>
|
||||||
tsconfig.e2e.json
|
tsconfig.e2e.json
|
||||||
</aio-file>
|
</aio-file>
|
||||||
@ -518,56 +596,67 @@ These files go in the root folder next to `src/`.
|
|||||||
</aio-folder>
|
</aio-folder>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<aio-file>
|
<aio-file>
|
||||||
node_modules/...
|
node_modules/...
|
||||||
</aio-file>
|
</aio-file>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<aio-file>
|
<aio-file>
|
||||||
src/...
|
src/...
|
||||||
</aio-file>
|
</aio-file>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<aio-file>
|
<aio-file>
|
||||||
.angular-cli.json
|
.angular-cli.json
|
||||||
</aio-file>
|
</aio-file>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<aio-file>
|
<aio-file>
|
||||||
.editorconfig
|
.editorconfig
|
||||||
</aio-file>
|
</aio-file>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<aio-file>
|
<aio-file>
|
||||||
.gitignore
|
.gitignore
|
||||||
</aio-file>
|
</aio-file>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<aio-file>
|
<aio-file>
|
||||||
karma.conf.js
|
karma.conf.js
|
||||||
</aio-file>
|
</aio-file>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<aio-file>
|
<aio-file>
|
||||||
package.json
|
package.json
|
||||||
</aio-file>
|
</aio-file>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<aio-file>
|
<aio-file>
|
||||||
protractor.conf.js
|
protractor.conf.js
|
||||||
</aio-file>
|
</aio-file>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<aio-file>
|
<aio-file>
|
||||||
README.md
|
README.md
|
||||||
</aio-file>
|
</aio-file>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<aio-file>
|
<aio-file>
|
||||||
tsconfig.json
|
tsconfig.json
|
||||||
</aio-file>
|
</aio-file>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<aio-file>
|
<aio-file>
|
||||||
tslint.json
|
tslint.json
|
||||||
</aio-file>
|
</aio-file>
|
||||||
@ -579,30 +668,37 @@ These files go in the root folder next to `src/`.
|
|||||||
</aio-filetree>
|
</aio-filetree>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
td, th {vertical-align: top}
|
td, th {vertical-align: top}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<table width="100%">
|
<table width="100%">
|
||||||
|
|
||||||
|
|
||||||
<col width="20%">
|
<col width="20%">
|
||||||
|
|
||||||
</col>
|
</col>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<col width="80%">
|
<col width="80%">
|
||||||
|
|
||||||
</col>
|
</col>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
|
|
||||||
|
|
||||||
<th>
|
<th>
|
||||||
File
|
File
|
||||||
</th>
|
</th>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<th>
|
<th>
|
||||||
Purpose
|
Purpose
|
||||||
</th>
|
</th>
|
||||||
@ -611,13 +707,16 @@ These files go in the root folder next to `src/`.
|
|||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
<code>e2e/</code>
|
<code>e2e/</code>
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
Inside `e2e/` live the End-to-End tests.
|
Inside `e2e/` live the End-to-End tests.
|
||||||
They shouldn't be inside `src/` because e2e tests are really a separate app that
|
They shouldn't be inside `src/` because e2e tests are really a separate app that
|
||||||
@ -629,13 +728,16 @@ These files go in the root folder next to `src/`.
|
|||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
<code>node_modules/</code>
|
<code>node_modules/</code>
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
`Node.js` creates this folder and puts all third party modules listed in
|
`Node.js` creates this folder and puts all third party modules listed in
|
||||||
`package.json` inside of it.
|
`package.json` inside of it.
|
||||||
@ -645,13 +747,16 @@ These files go in the root folder next to `src/`.
|
|||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
<code>.angular-cli.json</code>
|
<code>.angular-cli.json</code>
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
Configuration for Angular CLI.
|
Configuration for Angular CLI.
|
||||||
In this file you can set several defaults and also configure what files are included
|
In this file you can set several defaults and also configure what files are included
|
||||||
@ -663,13 +768,16 @@ These files go in the root folder next to `src/`.
|
|||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
<code>.editorconfig</code>
|
<code>.editorconfig</code>
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
Simple configuration for your editor to make sure everyone that uses your project
|
Simple configuration for your editor to make sure everyone that uses your project
|
||||||
has the same basic configuration.
|
has the same basic configuration.
|
||||||
@ -681,13 +789,16 @@ These files go in the root folder next to `src/`.
|
|||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
<code>.gitignore</code>
|
<code>.gitignore</code>
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
Git configuration to make sure autogenerated files are not commited to source control.
|
Git configuration to make sure autogenerated files are not commited to source control.
|
||||||
</td>
|
</td>
|
||||||
@ -696,13 +807,16 @@ These files go in the root folder next to `src/`.
|
|||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
<code>karma.conf.js</code>
|
<code>karma.conf.js</code>
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
Unit test configuration for the [Karma test runner](https://karma-runner.github.io),
|
Unit test configuration for the [Karma test runner](https://karma-runner.github.io),
|
||||||
used when running `ng test`.
|
used when running `ng test`.
|
||||||
@ -712,13 +826,16 @@ These files go in the root folder next to `src/`.
|
|||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
<code>package.json</code>
|
<code>package.json</code>
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
`npm` configuration listing the third party packages your project uses.
|
`npm` configuration listing the third party packages your project uses.
|
||||||
You can also add your own [custom scripts](https://docs.npmjs.com/misc/scripts) here.
|
You can also add your own [custom scripts](https://docs.npmjs.com/misc/scripts) here.
|
||||||
@ -728,13 +845,16 @@ These files go in the root folder next to `src/`.
|
|||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
<code>protractor.conf.js</code>
|
<code>protractor.conf.js</code>
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
End-to-end test configuration for [Protractor](http://www.protractortest.org/),
|
End-to-end test configuration for [Protractor](http://www.protractortest.org/),
|
||||||
used when running `ng e2e`.
|
used when running `ng e2e`.
|
||||||
@ -744,13 +864,16 @@ These files go in the root folder next to `src/`.
|
|||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
<code>README.md</code>
|
<code>README.md</code>
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
Basic documentation for your project, pre-filled with CLI command information.
|
Basic documentation for your project, pre-filled with CLI command information.
|
||||||
Make sure to enhance it with project documentation so that anyone
|
Make sure to enhance it with project documentation so that anyone
|
||||||
@ -761,13 +884,16 @@ These files go in the root folder next to `src/`.
|
|||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
<code>tsconfig.json</code>
|
<code>tsconfig.json</code>
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
TypeScript compiler configuration for your IDE to pick up and give you helpful tooling.
|
TypeScript compiler configuration for your IDE to pick up and give you helpful tooling.
|
||||||
</td>
|
</td>
|
||||||
@ -776,13 +902,16 @@ These files go in the root folder next to `src/`.
|
|||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
<code>tslint.json</code>
|
<code>tslint.json</code>
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
Linting configuration for [TSLint](https://palantir.github.io/tslint/) together with
|
Linting configuration for [TSLint](https://palantir.github.io/tslint/) together with
|
||||||
[Codelyzer](http://codelyzer.com/), used when running `ng lint`.
|
[Codelyzer](http://codelyzer.com/), used when running `ng lint`.
|
||||||
|
12
aio/content/examples/.gitignore
vendored
12
aio/content/examples/.gitignore
vendored
@ -1,4 +1,4 @@
|
|||||||
# _boilerplate files
|
# boilerplate files
|
||||||
**/src/styles.css
|
**/src/styles.css
|
||||||
**/src/systemjs-angular-loader.js
|
**/src/systemjs-angular-loader.js
|
||||||
**/src/systemjs.config.js
|
**/src/systemjs.config.js
|
||||||
@ -23,12 +23,18 @@ protractor-helpers.js
|
|||||||
dist/
|
dist/
|
||||||
|
|
||||||
# special
|
# special
|
||||||
!_boilerplate/
|
|
||||||
!/*
|
!/*
|
||||||
!systemjs.config.*.js
|
|
||||||
!*.1.*
|
!*.1.*
|
||||||
!*.2.*
|
!*.2.*
|
||||||
!*.3.*
|
!*.3.*
|
||||||
|
*.1.js
|
||||||
|
*.2.js
|
||||||
|
*.3.js
|
||||||
|
*.1.js.map
|
||||||
|
*.2.js.map
|
||||||
|
*.3.js.map
|
||||||
|
!systemjs.config.*.js
|
||||||
|
!karma-test-shim.*.js
|
||||||
|
|
||||||
# AngularJS files
|
# AngularJS files
|
||||||
!**/*.ajs.js
|
!**/*.ajs.js
|
||||||
|
@ -25,6 +25,15 @@ to a<span if-docs="ts"> module</span> factory, meaning you don't need to include
|
|||||||
Ahead-of-time compiled applications also benefit from decreased load time and increased performance.
|
Ahead-of-time compiled applications also benefit from decreased load time and increased performance.
|
||||||
|
|
||||||
|
|
||||||
|
~~~
|
||||||
|
|
||||||
|
## Annotation
|
||||||
|
|
||||||
|
~~~ {.l-sub-section}
|
||||||
|
|
||||||
|
In practice, a synonym for [Decoration](glossary#decorator).
|
||||||
|
|
||||||
|
|
||||||
~~~
|
~~~
|
||||||
|
|
||||||
|
|
||||||
@ -58,7 +67,6 @@ binding an HTML object property to a data object property.
|
|||||||
|
|
||||||
Sometimes refers to a [dependency-injection](glossary#dependency-injection) binding
|
Sometimes refers to a [dependency-injection](glossary#dependency-injection) binding
|
||||||
between a "token"—also referred to as a "key"—and a dependency [provider](glossary#provider).
|
between a "token"—also referred to as a "key"—and a dependency [provider](glossary#provider).
|
||||||
When using this more rare usage, be clear in context.
|
|
||||||
|
|
||||||
|
|
||||||
~~~
|
~~~
|
||||||
@ -67,9 +75,12 @@ When using this more rare usage, be clear in context.
|
|||||||
|
|
||||||
~~~ {.l-sub-section}
|
~~~ {.l-sub-section}
|
||||||
|
|
||||||
|
You launch an Angular application by "bootstrapping" it using the application root Angular module (`AppModule`).
|
||||||
|
Bootstrapping identifies an application's top level "root" [component](glossary#component),
|
||||||
|
which is the first component that is loaded for the application.
|
||||||
|
For more information, see the [Setup](!{docsLatest}/guide/setup) page.
|
||||||
|
|
||||||
You launch an Angular application by "bootstrapping" it using the application root Angular module (`AppModule`). Bootstrapping identifies an application's top level "root" [component](glossary#component), which is the first component that is loaded for the application.
|
You can bootstrap multiple apps in the same `index.html`, each app with its own top-level root.
|
||||||
For more information, see the [Setup](!{docsLatest}/guide/setup) page.You can bootstrap multiple apps in the same `index.html`, each app with its own top-level root.
|
|
||||||
|
|
||||||
|
|
||||||
~~~
|
~~~
|
||||||
@ -154,6 +165,48 @@ operations and supporting declaration syntax.
|
|||||||
* [Two-way data binding with ngModel](!{docsLatest}/guide/template-syntax).
|
* [Two-way data binding with ngModel](!{docsLatest}/guide/template-syntax).
|
||||||
|
|
||||||
|
|
||||||
|
~~~
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
{@a decorator}
|
||||||
|
|
||||||
|
|
||||||
|
{@a decoration}
|
||||||
|
## Decorator | decoration
|
||||||
|
|
||||||
|
~~~ {.l-sub-section}
|
||||||
|
|
||||||
|
A *function* that adds metadata to a class, its members (properties, methods) and function arguments.
|
||||||
|
|
||||||
|
Decorators are a JavaScript language [feature](https://github.com/wycats/javascript-decorators), implemented in TypeScript and proposed for ES2016 (also known as ES7).
|
||||||
|
|
||||||
|
To apply a decorator, position it immediately above or to the left of the item it decorates.
|
||||||
|
|
||||||
|
Angular has its own set of decorators to help it interoperate with your application parts.
|
||||||
|
The following example is a `@Component` decorator that identifies a
|
||||||
|
class as an Angular [component](glossary#component) and an `@Input` decorator applied to the `name` property
|
||||||
|
of that component. The elided object argument to the `@Component` decorator would contain the pertinent component metadata.
|
||||||
|
```
|
||||||
|
@Component({...})
|
||||||
|
export class AppComponent {
|
||||||
|
constructor(@Inject('SpecialFoo') public foo:Foo) {}
|
||||||
|
@Input() name:string;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
The scope of a decorator is limited to the language feature
|
||||||
|
that it decorates. None of the decorations shown here will "leak" to other
|
||||||
|
classes that follow it in the file.
|
||||||
|
|
||||||
|
|
||||||
|
~~~ {.alert.is-important}
|
||||||
|
|
||||||
|
Always include parentheses `()` when applying a decorator.
|
||||||
|
|
||||||
|
|
||||||
|
~~~
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
~~~
|
~~~
|
||||||
|
|
||||||
@ -226,7 +279,7 @@ Read more in the [Dependency Injection](!{docsLatest}/guide/dependency-injection
|
|||||||
An Angular class responsible for creating, reshaping, and interacting with HTML elements
|
An Angular class responsible for creating, reshaping, and interacting with HTML elements
|
||||||
in the browser DOM. The directive is Angular's most fundamental feature.
|
in the browser DOM. The directive is Angular's most fundamental feature.
|
||||||
|
|
||||||
A directive is ususally associated with an HTML element or attribute.
|
A directive is usually associated with an HTML element or attribute.
|
||||||
This element or attribute is often referred to as the directive itself.
|
This element or attribute is often referred to as the directive itself.
|
||||||
|
|
||||||
When Angular finds a directive in an HTML template,
|
When Angular finds a directive in an HTML template,
|
||||||
@ -238,23 +291,21 @@ associate with your custom directives. You add this custom markup to HTML templa
|
|||||||
as if you were writing native HTML. In this way, directives become extensions of
|
as if you were writing native HTML. In this way, directives become extensions of
|
||||||
HTML itself.
|
HTML itself.
|
||||||
|
|
||||||
|
|
||||||
Directives fall into one of the following categories:
|
Directives fall into one of the following categories:
|
||||||
|
|
||||||
* [Components](glossary#component) combine application logic with an HTML template to
|
* [Components](glossary#component) combine application logic with an HTML template to
|
||||||
render application [views](glossary#view). Components are usually represented as HTML elements.
|
render application [views](glossary#view). Components are usually represented as HTML elements.
|
||||||
They are the building blocks of an Angular application.
|
They are the building blocks of an Angular application.
|
||||||
|
|
||||||
1. [Attribute directives](glossary#attribute-directive) can listen to and modify the behavior of
|
* [Attribute directives](glossary#attribute-directive) can listen to and modify the behavior of
|
||||||
other HTML elements, attributes, properties, and components. They are usually represented
|
other HTML elements, attributes, properties, and components. They are usually represented
|
||||||
as HTML attributes, hence the name.
|
as HTML attributes, hence the name.
|
||||||
|
|
||||||
1. [Structural directives](glossary#structural-directive) are responsible for
|
* [Structural directives](glossary#structural-directive) are responsible for
|
||||||
shaping or reshaping HTML layout, typically by adding, removing, or manipulating
|
shaping or reshaping HTML layout, typically by adding, removing, or manipulating
|
||||||
elements and their children.
|
elements and their children.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
~~~
|
~~~
|
||||||
|
|
||||||
|
|
||||||
@ -349,6 +400,7 @@ renders as text. That text may be concatenated with neighboring text
|
|||||||
before it is assigned to an element property
|
before it is assigned to an element property
|
||||||
or displayed between element tags, as in this example.
|
or displayed between element tags, as in this example.
|
||||||
|
|
||||||
|
|
||||||
<code-example language="html" escape="html">
|
<code-example language="html" escape="html">
|
||||||
<label>My current hero is {{hero.name}}</label>
|
<label>My current hero is {{hero.name}}</label>
|
||||||
|
|
||||||
@ -421,7 +473,6 @@ Read more in the [Lifecycle Hooks](!{docsLatest}/guide/lifecycle-hooks) page.
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
~~~ {.alert.is-important}
|
~~~ {.alert.is-important}
|
||||||
|
|
||||||
Angular has the following types of modules:
|
Angular has the following types of modules:
|
||||||
@ -501,6 +552,7 @@ display in a [view](glossary#view).
|
|||||||
Here's an example that uses the built-in `currency` pipe to display
|
Here's an example that uses the built-in `currency` pipe to display
|
||||||
a numeric value in the local currency.
|
a numeric value in the local currency.
|
||||||
|
|
||||||
|
|
||||||
<code-example language="html" escape="html">
|
<code-example language="html" escape="html">
|
||||||
<label>Price: </label>{{product.price | currency}}
|
<label>Price: </label>{{product.price | currency}}
|
||||||
|
|
||||||
@ -527,6 +579,24 @@ It relates a lookup token to code—sometimes called a "recipe"—that c
|
|||||||
|
|
||||||
{@a Q}
|
{@a Q}
|
||||||
|
|
||||||
|
## Reactive forms
|
||||||
|
|
||||||
|
~~~ {.l-sub-section}
|
||||||
|
|
||||||
|
A technique for building Angular forms through code in a component.
|
||||||
|
The alternative technique is [template-driven forms](glossary#template-driven-forms).
|
||||||
|
|
||||||
|
When building reactive forms:
|
||||||
|
- The "source of truth" is the component. The validation is defined using code in the component.
|
||||||
|
- Each control is explicitly created in the component class with `new FormControl()` or with `FormBuilder`.
|
||||||
|
- The template input elements do *not* use `ngModel`.
|
||||||
|
- The associated Angular directives are all prefixed with `Form`, such as `FormGroup`, `FormControl`, and `FormControlName`.
|
||||||
|
|
||||||
|
Reactive forms are powerful, flexible, and a good choice for more complex data-entry form scenarios, such as dynamic generation of form controls.
|
||||||
|
|
||||||
|
|
||||||
|
~~~
|
||||||
|
|
||||||
## Router
|
## Router
|
||||||
|
|
||||||
~~~ {.l-sub-section}
|
~~~ {.l-sub-section}
|
||||||
@ -539,6 +609,17 @@ replace one view with another.
|
|||||||
The Angular component router is a richly featured mechanism for configuring and managing the entire view navigation process, including the creation and destruction
|
The Angular component router is a richly featured mechanism for configuring and managing the entire view navigation process, including the creation and destruction
|
||||||
of views.
|
of views.
|
||||||
|
|
||||||
|
~~~
|
||||||
|
|
||||||
|
## Router module
|
||||||
|
|
||||||
|
~~~ {.l-sub-section}
|
||||||
|
|
||||||
|
A separate [Angular module](glossary#angular-module) that provides the necessary service providers and directives for navigating through application views.
|
||||||
|
|
||||||
|
For more information, see the [Routing & Navigation](!{docsLatest}/guide/router) page.
|
||||||
|
|
||||||
|
|
||||||
~~~
|
~~~
|
||||||
|
|
||||||
## Routing component
|
## Routing component
|
||||||
@ -553,6 +634,30 @@ For more information, see the [Routing & Navigation](!{docsLatest}/guide/router)
|
|||||||
~~~
|
~~~
|
||||||
|
|
||||||
|
|
||||||
|
## Scoped package
|
||||||
|
|
||||||
|
~~~ {.l-sub-section}
|
||||||
|
|
||||||
|
A way to group related *npm* packages.
|
||||||
|
Read more at the [npm-scope](https://docs.npmjs.com/misc/scope) page.
|
||||||
|
|
||||||
|
Angular modules are delivered within *scoped packages* such as `@angular/core`,
|
||||||
|
`@angular/common`, `@angular/platform-browser-dynamic`, `@angular/http`, and `@angular/router`.
|
||||||
|
|
||||||
|
Import a scoped package the same way that you import a normal package.
|
||||||
|
The only difference, from a consumer perspective,
|
||||||
|
is that the scoped package name begins with the Angular *scope name*, `@angular`.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<code-example path="architecture/src/app/app.component.ts" linenums="false" title="architecture/ts/src/app/app.component.ts (import)" region="import">
|
||||||
|
|
||||||
|
</code-example>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
~~~
|
||||||
|
|
||||||
## Service
|
## Service
|
||||||
|
|
||||||
~~~ {.l-sub-section}
|
~~~ {.l-sub-section}
|
||||||
@ -579,10 +684,8 @@ For more information, see the [Services](!{docsLatest}/tutorial/toh-pt4) page of
|
|||||||
{@a snake-case}
|
{@a snake-case}
|
||||||
## snake_case
|
## snake_case
|
||||||
|
|
||||||
|
|
||||||
~~~ {.l-sub-section}
|
~~~ {.l-sub-section}
|
||||||
|
|
||||||
|
|
||||||
The practice of writing compound words or phrases such that an
|
The practice of writing compound words or phrases such that an
|
||||||
underscore (`_`) separates one word from the next. This form is also known as *underscore case*.
|
underscore (`_`) separates one word from the next. This form is also known as *underscore case*.
|
||||||
|
|
||||||
@ -603,7 +706,7 @@ A category of [directive](glossary#directive) that can
|
|||||||
shape or reshape HTML layout, typically by adding and removing elements in the DOM.
|
shape or reshape HTML layout, typically by adding and removing elements in the DOM.
|
||||||
The `ngIf` "conditional element" directive and the `ngFor` "repeater" directive are well-known examples.
|
The `ngIf` "conditional element" directive and the `ngFor` "repeater" directive are well-known examples.
|
||||||
|
|
||||||
Read more in the [_Structural Directives_](!{docsLatest}/guide/structural-directives) guide.
|
Read more in the [Structural Directives](!{docsLatest}/guide/structural-directives) page.
|
||||||
|
|
||||||
|
|
||||||
~~~
|
~~~
|
||||||
@ -618,6 +721,26 @@ the support and guidance of an Angular [directive](glossary#directive),
|
|||||||
most notably a [component](glossary#component).
|
most notably a [component](glossary#component).
|
||||||
|
|
||||||
|
|
||||||
|
~~~
|
||||||
|
|
||||||
|
## Template-driven forms
|
||||||
|
|
||||||
|
~~~ {.l-sub-section}
|
||||||
|
|
||||||
|
A technique for building Angular forms using HTML forms and input elements in the view.
|
||||||
|
The alternate technique is [Reactive Forms](glossary#reactive-forms).
|
||||||
|
|
||||||
|
When building template-driven forms:
|
||||||
|
- The "source of truth" is the template. The validation is defined using attributes on the individual input elements.
|
||||||
|
- [Two-way binding](glossary#data-binding) with `ngModel` keeps the component model synchronized with the user's entry into the input elements.
|
||||||
|
- Behind the scenes, Angular creates a new control for each input element, provided you have set up a `name` attribute and two-way binding for each input.
|
||||||
|
- The associated Angular directives are all prefixed with `ng` such as `ngForm`, `ngModel`, and `ngModelGroup`.
|
||||||
|
|
||||||
|
Template-driven forms are convenient, quick, and simple. They are a good choice for many basic data-entry form scenarios.
|
||||||
|
|
||||||
|
Read about how to build template-driven forms
|
||||||
|
in the [Forms](!{docsLatest}/guide/forms) page.
|
||||||
|
|
||||||
|
|
||||||
~~~
|
~~~
|
||||||
|
|
||||||
@ -702,7 +825,6 @@ under the control of a [router](glossary#router).
|
|||||||
|
|
||||||
~~~ {.l-sub-section}
|
~~~ {.l-sub-section}
|
||||||
|
|
||||||
|
|
||||||
A mechanism for encapsulating and intercepting
|
A mechanism for encapsulating and intercepting
|
||||||
a JavaScript application's asynchronous activity.
|
a JavaScript application's asynchronous activity.
|
||||||
|
|
||||||
|
@ -31,25 +31,31 @@ by mapping AngularJS syntax to the equivalent Angular syntax.
|
|||||||
Templates are the user-facing part of an Angular application and are written in HTML.
|
Templates are the user-facing part of an Angular application and are written in HTML.
|
||||||
The following table lists some of the key AngularJS template features with their equivalent Angular template syntax.
|
The following table lists some of the key AngularJS template features with their equivalent Angular template syntax.
|
||||||
|
|
||||||
|
|
||||||
<table width="100%">
|
<table width="100%">
|
||||||
|
|
||||||
|
|
||||||
<col width="50%">
|
<col width="50%">
|
||||||
|
|
||||||
</col>
|
</col>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<col width="50%">
|
<col width="50%">
|
||||||
|
|
||||||
</col>
|
</col>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
|
|
||||||
|
|
||||||
<th>
|
<th>
|
||||||
AngularJS
|
AngularJS
|
||||||
</th>
|
</th>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<th>
|
<th>
|
||||||
Angular
|
Angular
|
||||||
</th>
|
</th>
|
||||||
@ -58,10 +64,13 @@ The following table lists some of the key AngularJS template features with their
|
|||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<tr style=top>
|
<tr style=top>
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
### Bindings/interpolation
|
### Bindings/interpolation
|
||||||
|
|
||||||
<code-example>
|
<code-example>
|
||||||
Your favorite hero is: {{vm.favoriteHero}}
|
Your favorite hero is: {{vm.favoriteHero}}
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -76,9 +85,11 @@ The following table lists some of the key AngularJS template features with their
|
|||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
### Bindings/interpolation
|
### Bindings/interpolation
|
||||||
|
|
||||||
|
|
||||||
<code-example path="cb-ajs-quick-reference/src/app/movie-list.component.html" region="interpolation" linenums="false">
|
<code-example path="cb-ajs-quick-reference/src/app/movie-list.component.html" region="interpolation" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -96,10 +107,13 @@ The following table lists some of the key AngularJS template features with their
|
|||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<tr style=top>
|
<tr style=top>
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
### Filters
|
### Filters
|
||||||
|
|
||||||
<code-example>
|
<code-example>
|
||||||
<td>{{movie.title | uppercase}}</td>
|
<td>{{movie.title | uppercase}}</td>
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -110,9 +124,11 @@ The following table lists some of the key AngularJS template features with their
|
|||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
### Pipes
|
### Pipes
|
||||||
|
|
||||||
|
|
||||||
<code-example path="cb-ajs-quick-reference/src/app/app.component.html" region="uppercase" linenums="false">
|
<code-example path="cb-ajs-quick-reference/src/app/app.component.html" region="uppercase" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -128,10 +144,13 @@ The following table lists some of the key AngularJS template features with their
|
|||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<tr style=top>
|
<tr style=top>
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
### Local variables
|
### Local variables
|
||||||
|
|
||||||
<code-example format="">
|
<code-example format="">
|
||||||
<tr ng-repeat="movie in vm.movies">
|
<tr ng-repeat="movie in vm.movies">
|
||||||
<td>{{movie.title}}</td>
|
<td>{{movie.title}}</td>
|
||||||
@ -142,9 +161,11 @@ The following table lists some of the key AngularJS template features with their
|
|||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
### Input variables
|
### Input variables
|
||||||
|
|
||||||
|
|
||||||
<code-example path="cb-ajs-quick-reference/src/app/app.component.html" region="local" linenums="false">
|
<code-example path="cb-ajs-quick-reference/src/app/app.component.html" region="local" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -168,25 +189,31 @@ AngularJS provides more than seventy built-in directives for templates.
|
|||||||
Many of them aren't needed in Angular because of its more capable and expressive binding system.
|
Many of them aren't needed in Angular because of its more capable and expressive binding system.
|
||||||
The following are some of the key AngularJS built-in directives and their equivalents in Angular.
|
The following are some of the key AngularJS built-in directives and their equivalents in Angular.
|
||||||
|
|
||||||
|
|
||||||
<table width="100%">
|
<table width="100%">
|
||||||
|
|
||||||
|
|
||||||
<col width="50%">
|
<col width="50%">
|
||||||
|
|
||||||
</col>
|
</col>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<col width="50%">
|
<col width="50%">
|
||||||
|
|
||||||
</col>
|
</col>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
|
|
||||||
|
|
||||||
<th>
|
<th>
|
||||||
AngularJS
|
AngularJS
|
||||||
</th>
|
</th>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<th>
|
<th>
|
||||||
Angular
|
Angular
|
||||||
</th>
|
</th>
|
||||||
@ -195,10 +222,13 @@ The following are some of the key AngularJS built-in directives and their equiva
|
|||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<tr style=top>
|
<tr style=top>
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
### ng-app
|
### ng-app
|
||||||
|
|
||||||
<code-example>
|
<code-example>
|
||||||
<body ng-app="movieHunter">
|
<body ng-app="movieHunter">
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -211,15 +241,18 @@ The following are some of the key AngularJS built-in directives and their equiva
|
|||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
### Bootstrapping
|
### Bootstrapping
|
||||||
|
|
||||||
|
|
||||||
<code-example path="cb-ajs-quick-reference/src/main.ts" linenums="false">
|
<code-example path="cb-ajs-quick-reference/src/main.ts" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
|
|
||||||
<br>
|
<br>
|
||||||
|
|
||||||
|
|
||||||
<code-example path="cb-ajs-quick-reference/src/app/app.module.1.ts" linenums="false">
|
<code-example path="cb-ajs-quick-reference/src/app/app.module.1.ts" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -236,10 +269,13 @@ The following are some of the key AngularJS built-in directives and their equiva
|
|||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<tr style=top>
|
<tr style=top>
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
### ng-class
|
### ng-class
|
||||||
|
|
||||||
<code-example format="">
|
<code-example format="">
|
||||||
<div ng-class="{active: isActive}">
|
<div ng-class="{active: isActive}">
|
||||||
<div ng-class="{active: isActive,
|
<div ng-class="{active: isActive,
|
||||||
@ -257,9 +293,11 @@ The following are some of the key AngularJS built-in directives and their equiva
|
|||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
### ngClass
|
### ngClass
|
||||||
|
|
||||||
|
|
||||||
<code-example path="cb-ajs-quick-reference/src/app/app.component.html" region="ngClass" linenums="false">
|
<code-example path="cb-ajs-quick-reference/src/app/app.component.html" region="ngClass" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -283,10 +321,13 @@ The following are some of the key AngularJS built-in directives and their equiva
|
|||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<tr style=top>
|
<tr style=top>
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
### ng-click
|
### ng-click
|
||||||
|
|
||||||
<code-example format="">
|
<code-example format="">
|
||||||
<button ng-click="vm.toggleImage()">
|
<button ng-click="vm.toggleImage()">
|
||||||
<button ng-click="vm.toggleImage($event)">
|
<button ng-click="vm.toggleImage($event)">
|
||||||
@ -301,9 +342,11 @@ The following are some of the key AngularJS built-in directives and their equiva
|
|||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
### Bind to the `click` event
|
### Bind to the `click` event
|
||||||
|
|
||||||
|
|
||||||
<code-example path="cb-ajs-quick-reference/src/app/app.component.html" region="event-binding" linenums="false">
|
<code-example path="cb-ajs-quick-reference/src/app/app.component.html" region="event-binding" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -332,10 +375,13 @@ The following are some of the key AngularJS built-in directives and their equiva
|
|||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<tr style=top>
|
<tr style=top>
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
### ng-controller
|
### ng-controller
|
||||||
|
|
||||||
<code-example format="">
|
<code-example format="">
|
||||||
<div ng-controller="MovieListCtrl as vm">
|
<div ng-controller="MovieListCtrl as vm">
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -346,9 +392,11 @@ The following are some of the key AngularJS built-in directives and their equiva
|
|||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
### Component decorator
|
### Component decorator
|
||||||
|
|
||||||
|
|
||||||
<code-example path="cb-ajs-quick-reference/src/app/movie-list.component.ts" region="component" linenums="false">
|
<code-example path="cb-ajs-quick-reference/src/app/movie-list.component.ts" region="component" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -364,8 +412,10 @@ The following are some of the key AngularJS built-in directives and their equiva
|
|||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<tr style=top>
|
<tr style=top>
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
### ng-hide
|
### ng-hide
|
||||||
In AngularJS, the `ng-hide` directive shows or hides the associated HTML element based on
|
In AngularJS, the `ng-hide` directive shows or hides the associated HTML element based on
|
||||||
@ -373,6 +423,7 @@ The following are some of the key AngularJS built-in directives and their equiva
|
|||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
### Bind to the `hidden` property
|
### Bind to the `hidden` property
|
||||||
In Angular, you use property binding; there is no built-in *hide* directive.
|
In Angular, you use property binding; there is no built-in *hide* directive.
|
||||||
@ -383,10 +434,13 @@ The following are some of the key AngularJS built-in directives and their equiva
|
|||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<tr style=top>
|
<tr style=top>
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
### ng-href
|
### ng-href
|
||||||
|
|
||||||
<code-example format="">
|
<code-example format="">
|
||||||
<a ng-href="angularDocsUrl">Angular Docs</a>
|
<a ng-href="angularDocsUrl">Angular Docs</a>
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -396,6 +450,7 @@ The following are some of the key AngularJS built-in directives and their equiva
|
|||||||
fetches from that URL.
|
fetches from that URL.
|
||||||
|
|
||||||
In AngularJS, the `ng-href` is often used to activate a route as part of navigation.
|
In AngularJS, the `ng-href` is often used to activate a route as part of navigation.
|
||||||
|
|
||||||
<code-example format="">
|
<code-example format="">
|
||||||
<a ng-href="#movies">Movies</a>
|
<a ng-href="#movies">Movies</a>
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -404,9 +459,11 @@ The following are some of the key AngularJS built-in directives and their equiva
|
|||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
### Bind to the `href` property
|
### Bind to the `href` property
|
||||||
|
|
||||||
|
|
||||||
<code-example path="cb-ajs-quick-reference/src/app/app.component.html" region="href" linenums="false">
|
<code-example path="cb-ajs-quick-reference/src/app/app.component.html" region="href" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -419,6 +476,7 @@ The following are some of the key AngularJS built-in directives and their equiva
|
|||||||
|
|
||||||
In Angular, `href` is no longer used for routing. Routing uses `routerLink`, as shown in the following example.
|
In Angular, `href` is no longer used for routing. Routing uses `routerLink`, as shown in the following example.
|
||||||
|
|
||||||
|
|
||||||
<code-example path="cb-ajs-quick-reference/src/app/app.component.html" region="router-link" linenums="false">
|
<code-example path="cb-ajs-quick-reference/src/app/app.component.html" region="router-link" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -432,10 +490,13 @@ The following are some of the key AngularJS built-in directives and their equiva
|
|||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<tr style=top>
|
<tr style=top>
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
### ng-if
|
### ng-if
|
||||||
|
|
||||||
<code-example format="">
|
<code-example format="">
|
||||||
<table ng-if="movies.length">
|
<table ng-if="movies.length">
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -447,9 +508,11 @@ The following are some of the key AngularJS built-in directives and their equiva
|
|||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
### *ngIf
|
### *ngIf
|
||||||
|
|
||||||
|
|
||||||
<code-example path="cb-ajs-quick-reference/src/app/movie-list.component.html" region="ngIf" linenums="false">
|
<code-example path="cb-ajs-quick-reference/src/app/movie-list.component.html" region="ngIf" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -467,10 +530,13 @@ The following are some of the key AngularJS built-in directives and their equiva
|
|||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<tr style=top>
|
<tr style=top>
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
### ng-model
|
### ng-model
|
||||||
|
|
||||||
<code-example format="">
|
<code-example format="">
|
||||||
<input ng-model="vm.favoriteHero"/>
|
<input ng-model="vm.favoriteHero"/>
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -480,9 +546,11 @@ The following are some of the key AngularJS built-in directives and their equiva
|
|||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
### ngModel
|
### ngModel
|
||||||
|
|
||||||
|
|
||||||
<code-example path="cb-ajs-quick-reference/src/app/movie-list.component.html" region="ngModel" linenums="false">
|
<code-example path="cb-ajs-quick-reference/src/app/movie-list.component.html" region="ngModel" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -499,10 +567,13 @@ The following are some of the key AngularJS built-in directives and their equiva
|
|||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<tr style=top>
|
<tr style=top>
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
### ng-repeat
|
### ng-repeat
|
||||||
|
|
||||||
<code-example format="">
|
<code-example format="">
|
||||||
<tr ng-repeat="movie in vm.movies">
|
<tr ng-repeat="movie in vm.movies">
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -514,9 +585,11 @@ The following are some of the key AngularJS built-in directives and their equiva
|
|||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
### *ngFor
|
### *ngFor
|
||||||
|
|
||||||
|
|
||||||
<code-example path="cb-ajs-quick-reference/src/app/movie-list.component.html" region="ngFor" linenums="false">
|
<code-example path="cb-ajs-quick-reference/src/app/movie-list.component.html" region="ngFor" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -538,10 +611,13 @@ The following are some of the key AngularJS built-in directives and their equiva
|
|||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<tr style=top>
|
<tr style=top>
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
### ng-show
|
### ng-show
|
||||||
|
|
||||||
<code-example format="">
|
<code-example format="">
|
||||||
<h3 ng-show="vm.favoriteHero">
|
<h3 ng-show="vm.favoriteHero">
|
||||||
Your favorite hero is: {{vm.favoriteHero}}
|
Your favorite hero is: {{vm.favoriteHero}}
|
||||||
@ -555,9 +631,11 @@ The following are some of the key AngularJS built-in directives and their equiva
|
|||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
### Bind to the `hidden` property
|
### Bind to the `hidden` property
|
||||||
|
|
||||||
|
|
||||||
<code-example path="cb-ajs-quick-reference/src/app/movie-list.component.html" region="hidden" linenums="false">
|
<code-example path="cb-ajs-quick-reference/src/app/movie-list.component.html" region="hidden" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -578,10 +656,13 @@ The following are some of the key AngularJS built-in directives and their equiva
|
|||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<tr style=top>
|
<tr style=top>
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
### ng-src
|
### ng-src
|
||||||
|
|
||||||
<code-example format="">
|
<code-example format="">
|
||||||
<img ng-src="{{movie.imageurl}}">
|
<img ng-src="{{movie.imageurl}}">
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -592,9 +673,11 @@ The following are some of the key AngularJS built-in directives and their equiva
|
|||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
### Bind to the `src` property
|
### Bind to the `src` property
|
||||||
|
|
||||||
|
|
||||||
<code-example path="cb-ajs-quick-reference/src/app/app.component.html" region="src" linenums="false">
|
<code-example path="cb-ajs-quick-reference/src/app/app.component.html" region="src" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -610,10 +693,13 @@ The following are some of the key AngularJS built-in directives and their equiva
|
|||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<tr style=top>
|
<tr style=top>
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
### ng-style
|
### ng-style
|
||||||
|
|
||||||
<code-example format="">
|
<code-example format="">
|
||||||
<div ng-style="{color: colorPreference}">
|
<div ng-style="{color: colorPreference}">
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -627,9 +713,11 @@ The following are some of the key AngularJS built-in directives and their equiva
|
|||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
### ngStyle
|
### ngStyle
|
||||||
|
|
||||||
|
|
||||||
<code-example path="cb-ajs-quick-reference/src/app/app.component.html" region="ngStyle" linenums="false">
|
<code-example path="cb-ajs-quick-reference/src/app/app.component.html" region="ngStyle" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -651,10 +739,13 @@ The following are some of the key AngularJS built-in directives and their equiva
|
|||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<tr style=top>
|
<tr style=top>
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
### ng-switch
|
### ng-switch
|
||||||
|
|
||||||
<code-example format="">
|
<code-example format="">
|
||||||
<div ng-switch="vm.favoriteHero &&
|
<div ng-switch="vm.favoriteHero &&
|
||||||
vm.checkMovieHero(vm.favoriteHero)">
|
vm.checkMovieHero(vm.favoriteHero)">
|
||||||
@ -680,9 +771,11 @@ The following are some of the key AngularJS built-in directives and their equiva
|
|||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
### ngSwitch
|
### ngSwitch
|
||||||
|
|
||||||
|
|
||||||
<code-example path="cb-ajs-quick-reference/src/app/movie-list.component.html" region="ngSwitch" linenums="false">
|
<code-example path="cb-ajs-quick-reference/src/app/movie-list.component.html" region="ngSwitch" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -718,25 +811,31 @@ Angular **pipes** provide formatting and transformation for data in the template
|
|||||||
Many of the built-in filters in AngularJS have corresponding pipes in Angular.
|
Many of the built-in filters in AngularJS have corresponding pipes in Angular.
|
||||||
For more information on pipes, see [Pipes](guide/pipes).
|
For more information on pipes, see [Pipes](guide/pipes).
|
||||||
|
|
||||||
|
|
||||||
<table width="100%">
|
<table width="100%">
|
||||||
|
|
||||||
|
|
||||||
<col width="50%">
|
<col width="50%">
|
||||||
|
|
||||||
</col>
|
</col>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<col width="50%">
|
<col width="50%">
|
||||||
|
|
||||||
</col>
|
</col>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
|
|
||||||
|
|
||||||
<th>
|
<th>
|
||||||
AngularJS
|
AngularJS
|
||||||
</th>
|
</th>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<th>
|
<th>
|
||||||
Angular
|
Angular
|
||||||
</th>
|
</th>
|
||||||
@ -745,10 +844,13 @@ For more information on pipes, see [Pipes](guide/pipes).
|
|||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<tr style=top>
|
<tr style=top>
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
### currency
|
### currency
|
||||||
|
|
||||||
<code-example>
|
<code-example>
|
||||||
<td>{{movie.price | currency}}</td>
|
<td>{{movie.price | currency}}</td>
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -757,9 +859,11 @@ For more information on pipes, see [Pipes](guide/pipes).
|
|||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
### currency
|
### currency
|
||||||
|
|
||||||
|
|
||||||
<code-example path="cb-ajs-quick-reference/src/app/app.component.html" region="currency" linenums="false">
|
<code-example path="cb-ajs-quick-reference/src/app/app.component.html" region="currency" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -771,10 +875,13 @@ For more information on pipes, see [Pipes](guide/pipes).
|
|||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<tr style=top>
|
<tr style=top>
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
### date
|
### date
|
||||||
|
|
||||||
<code-example>
|
<code-example>
|
||||||
<td>{{movie.releaseDate | date}}</td>
|
<td>{{movie.releaseDate | date}}</td>
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -783,9 +890,11 @@ For more information on pipes, see [Pipes](guide/pipes).
|
|||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
### date
|
### date
|
||||||
|
|
||||||
|
|
||||||
<code-example path="cb-ajs-quick-reference/src/app/app.component.html" region="date" linenums="false">
|
<code-example path="cb-ajs-quick-reference/src/app/app.component.html" region="date" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -798,10 +907,13 @@ For more information on pipes, see [Pipes](guide/pipes).
|
|||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<tr style=top>
|
<tr style=top>
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
### filter
|
### filter
|
||||||
|
|
||||||
<code-example>
|
<code-example>
|
||||||
<tr ng-repeat="movie in movieList | filter: {title:listFilter}">
|
<tr ng-repeat="movie in movieList | filter: {title:listFilter}">
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -810,6 +922,7 @@ For more information on pipes, see [Pipes](guide/pipes).
|
|||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
### none
|
### none
|
||||||
For performance reasons, no comparable pipe exists in Angular. Do all your filtering in the component. If you need the same filtering code in several templates, consider building a custom pipe.
|
For performance reasons, no comparable pipe exists in Angular. Do all your filtering in the component. If you need the same filtering code in several templates, consider building a custom pipe.
|
||||||
@ -820,10 +933,13 @@ For more information on pipes, see [Pipes](guide/pipes).
|
|||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<tr style=top>
|
<tr style=top>
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
### json
|
### json
|
||||||
|
|
||||||
<code-example>
|
<code-example>
|
||||||
<pre>{{movie | json}}</pre>
|
<pre>{{movie | json}}</pre>
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -832,9 +948,11 @@ For more information on pipes, see [Pipes](guide/pipes).
|
|||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
### json
|
### json
|
||||||
|
|
||||||
|
|
||||||
<code-example path="cb-ajs-quick-reference/src/app/app.component.html" region="json" linenums="false">
|
<code-example path="cb-ajs-quick-reference/src/app/app.component.html" region="json" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -846,10 +964,13 @@ For more information on pipes, see [Pipes](guide/pipes).
|
|||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<tr style=top>
|
<tr style=top>
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
### limitTo
|
### limitTo
|
||||||
|
|
||||||
<code-example>
|
<code-example>
|
||||||
<tr ng-repeat="movie in movieList | limitTo:2:0">
|
<tr ng-repeat="movie in movieList | limitTo:2:0">
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -859,9 +980,11 @@ For more information on pipes, see [Pipes](guide/pipes).
|
|||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
### slice
|
### slice
|
||||||
|
|
||||||
|
|
||||||
<code-example path="cb-ajs-quick-reference/src/app/app.component.html" region="slice" linenums="false">
|
<code-example path="cb-ajs-quick-reference/src/app/app.component.html" region="slice" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -876,10 +999,13 @@ For more information on pipes, see [Pipes](guide/pipes).
|
|||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<tr style=top>
|
<tr style=top>
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
### lowercase
|
### lowercase
|
||||||
|
|
||||||
<code-example>
|
<code-example>
|
||||||
<div>{{movie.title | lowercase}}</div>
|
<div>{{movie.title | lowercase}}</div>
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -888,9 +1014,11 @@ For more information on pipes, see [Pipes](guide/pipes).
|
|||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
### lowercase
|
### lowercase
|
||||||
|
|
||||||
|
|
||||||
<code-example path="cb-ajs-quick-reference/src/app/app.component.html" region="lowercase" linenums="false">
|
<code-example path="cb-ajs-quick-reference/src/app/app.component.html" region="lowercase" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -902,10 +1030,13 @@ For more information on pipes, see [Pipes](guide/pipes).
|
|||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<tr style=top>
|
<tr style=top>
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
### number
|
### number
|
||||||
|
|
||||||
<code-example>
|
<code-example>
|
||||||
<td>{{movie.starRating | number}}</td>
|
<td>{{movie.starRating | number}}</td>
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -914,9 +1045,11 @@ For more information on pipes, see [Pipes](guide/pipes).
|
|||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
### number
|
### number
|
||||||
|
|
||||||
|
|
||||||
<code-example path="cb-ajs-quick-reference/src/app/app.component.html" region="number" linenums="false">
|
<code-example path="cb-ajs-quick-reference/src/app/app.component.html" region="number" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -933,10 +1066,13 @@ For more information on pipes, see [Pipes](guide/pipes).
|
|||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<tr style=top>
|
<tr style=top>
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
### orderBy
|
### orderBy
|
||||||
|
|
||||||
<code-example>
|
<code-example>
|
||||||
<tr ng-repeat="movie in movieList | orderBy : 'title'">
|
<tr ng-repeat="movie in movieList | orderBy : 'title'">
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -946,6 +1082,7 @@ For more information on pipes, see [Pipes](guide/pipes).
|
|||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
### none
|
### none
|
||||||
For performance reasons, no comparable pipe exists in Angular.
|
For performance reasons, no comparable pipe exists in Angular.
|
||||||
@ -973,25 +1110,31 @@ In Angular, you build a **component**.
|
|||||||
Because much AngularJS code is in JavaScript, JavaScript code is shown in the AngularJS column.
|
Because much AngularJS code is in JavaScript, JavaScript code is shown in the AngularJS column.
|
||||||
The Angular code is shown using TypeScript.
|
The Angular code is shown using TypeScript.
|
||||||
|
|
||||||
|
|
||||||
<table width="100%">
|
<table width="100%">
|
||||||
|
|
||||||
|
|
||||||
<col width="50%">
|
<col width="50%">
|
||||||
|
|
||||||
</col>
|
</col>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<col width="50%">
|
<col width="50%">
|
||||||
|
|
||||||
</col>
|
</col>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
|
|
||||||
|
|
||||||
<th>
|
<th>
|
||||||
AngularJS
|
AngularJS
|
||||||
</th>
|
</th>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<th>
|
<th>
|
||||||
Angular
|
Angular
|
||||||
</th>
|
</th>
|
||||||
@ -1000,10 +1143,13 @@ The Angular code is shown using TypeScript.
|
|||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<tr style=top>
|
<tr style=top>
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
### IIFE
|
### IIFE
|
||||||
|
|
||||||
<code-example>
|
<code-example>
|
||||||
(function () {
|
(function () {
|
||||||
...
|
...
|
||||||
@ -1016,6 +1162,7 @@ The Angular code is shown using TypeScript.
|
|||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
### none
|
### none
|
||||||
This is a nonissue in Angular because ES 2015 modules
|
This is a nonissue in Angular because ES 2015 modules
|
||||||
@ -1029,10 +1176,13 @@ The Angular code is shown using TypeScript.
|
|||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<tr style=top>
|
<tr style=top>
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
### Angular modules
|
### Angular modules
|
||||||
|
|
||||||
<code-example>
|
<code-example>
|
||||||
angular.module("movieHunter", ["ngRoute"]);
|
angular.module("movieHunter", ["ngRoute"]);
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -1042,9 +1192,11 @@ The Angular code is shown using TypeScript.
|
|||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
### Angular modules
|
### Angular modules
|
||||||
|
|
||||||
|
|
||||||
<code-example path="cb-ajs-quick-reference/src/app/app.module.1.ts" linenums="false">
|
<code-example path="cb-ajs-quick-reference/src/app/app.module.1.ts" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -1060,10 +1212,13 @@ The Angular code is shown using TypeScript.
|
|||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<tr style=top>
|
<tr style=top>
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
### Controller registration
|
### Controller registration
|
||||||
|
|
||||||
<code-example>
|
<code-example>
|
||||||
angular
|
angular
|
||||||
.module("movieHunter")
|
.module("movieHunter")
|
||||||
@ -1080,9 +1235,11 @@ The Angular code is shown using TypeScript.
|
|||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
### Component decorator
|
### Component decorator
|
||||||
|
|
||||||
|
|
||||||
<code-example path="cb-ajs-quick-reference/src/app/movie-list.component.ts" region="component" linenums="false">
|
<code-example path="cb-ajs-quick-reference/src/app/movie-list.component.ts" region="component" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -1101,10 +1258,13 @@ The Angular code is shown using TypeScript.
|
|||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<tr style=top>
|
<tr style=top>
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
### Controller function
|
### Controller function
|
||||||
|
|
||||||
<code-example>
|
<code-example>
|
||||||
function MovieListCtrl(movieService) {
|
function MovieListCtrl(movieService) {
|
||||||
}
|
}
|
||||||
@ -1114,9 +1274,11 @@ The Angular code is shown using TypeScript.
|
|||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
### Component class
|
### Component class
|
||||||
|
|
||||||
|
|
||||||
<code-example path="cb-ajs-quick-reference/src/app/movie-list.component.ts" region="class" linenums="false">
|
<code-example path="cb-ajs-quick-reference/src/app/movie-list.component.ts" region="class" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -1133,10 +1295,13 @@ The Angular code is shown using TypeScript.
|
|||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<tr style=top>
|
<tr style=top>
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
### Dependency injection
|
### Dependency injection
|
||||||
|
|
||||||
<code-example>
|
<code-example>
|
||||||
MovieListCtrl.$inject = ['MovieService'];
|
MovieListCtrl.$inject = ['MovieService'];
|
||||||
function MovieListCtrl(movieService) {
|
function MovieListCtrl(movieService) {
|
||||||
@ -1151,9 +1316,11 @@ The Angular code is shown using TypeScript.
|
|||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
### Dependency injection
|
### Dependency injection
|
||||||
|
|
||||||
|
|
||||||
<code-example path="cb-ajs-quick-reference/src/app/movie-list.component.ts" region="di" linenums="false">
|
<code-example path="cb-ajs-quick-reference/src/app/movie-list.component.ts" region="di" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -1184,25 +1351,31 @@ As the application grows over time, the styles for the many parts of the applica
|
|||||||
merge, which can cause unexpected results.
|
merge, which can cause unexpected results.
|
||||||
In Angular, you can still define style sheets for your entire application. But now you can
|
In Angular, you can still define style sheets for your entire application. But now you can
|
||||||
also encapsulate a style sheet within a specific component.
|
also encapsulate a style sheet within a specific component.
|
||||||
|
|
||||||
<table width="100%">
|
<table width="100%">
|
||||||
|
|
||||||
|
|
||||||
<col width="50%">
|
<col width="50%">
|
||||||
|
|
||||||
</col>
|
</col>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<col width="50%">
|
<col width="50%">
|
||||||
|
|
||||||
</col>
|
</col>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
|
|
||||||
|
|
||||||
<th>
|
<th>
|
||||||
AngularJS
|
AngularJS
|
||||||
</th>
|
</th>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<th>
|
<th>
|
||||||
Angular
|
Angular
|
||||||
</th>
|
</th>
|
||||||
@ -1211,10 +1384,13 @@ also encapsulate a style sheet within a specific component.
|
|||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<tr style=top>
|
<tr style=top>
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
### Link tag
|
### Link tag
|
||||||
|
|
||||||
<code-example>
|
<code-example>
|
||||||
<link href="styles.css" rel="stylesheet" />
|
<link href="styles.css" rel="stylesheet" />
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -1224,9 +1400,11 @@ also encapsulate a style sheet within a specific component.
|
|||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
### Link tag
|
### Link tag
|
||||||
|
|
||||||
|
|
||||||
<code-example path="cb-ajs-quick-reference/src/index.html" region="style" linenums="false">
|
<code-example path="cb-ajs-quick-reference/src/index.html" region="style" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -1236,6 +1414,7 @@ also encapsulate a style sheet within a specific component.
|
|||||||
In Angular, you can use the `styles` or `styleUrls` property of the `@Component` metadata to define
|
In Angular, you can use the `styles` or `styleUrls` property of the `@Component` metadata to define
|
||||||
a style sheet for a particular component.
|
a style sheet for a particular component.
|
||||||
|
|
||||||
|
|
||||||
<code-example path="cb-ajs-quick-reference/src/app/movie-list.component.ts" region="style-url" linenums="false">
|
<code-example path="cb-ajs-quick-reference/src/app/movie-list.component.ts" region="style-url" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
|
@ -54,6 +54,7 @@ The examples in this page are available as a <live-example></live-example>.
|
|||||||
{@a example-transitioning-between-states}
|
{@a example-transitioning-between-states}
|
||||||
|
|
||||||
## Quickstart example: Transitioning between two states
|
## Quickstart example: Transitioning between two states
|
||||||
|
|
||||||
<figure>
|
<figure>
|
||||||
<img src="assets/images/devguide/animations/animation_basic_click.gif" alt="A simple transition animation" align="right" style="width:220px;margin-left:20px"> </img>
|
<img src="assets/images/devguide/animations/animation_basic_click.gif" alt="A simple transition animation" align="right" style="width:220px;margin-left:20px"> </img>
|
||||||
</figure>
|
</figure>
|
||||||
@ -65,12 +66,14 @@ Animations are defined inside `@Component` metadata. Before you can add animatio
|
|||||||
to import a few animation-specific imports and functions:
|
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 path="animations/src/app/app.module.ts" region="animations-module" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="animations/src/app/hero-list-basic.component.ts" region="imports" linenums="false">
|
<code-example path="animations/src/app/hero-list-basic.component.ts" region="imports" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -80,6 +83,7 @@ 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.
|
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 path="animations/src/app/hero-list-basic.component.ts" region="animationdef" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -98,6 +102,7 @@ Now, using the `[@triggerName]` syntax, attach the animation that you just defin
|
|||||||
one or more elements in the component's template.
|
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 path="animations/src/app/hero-list-basic.component.ts" region="template" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -110,6 +115,7 @@ With this setup, an animated transition appears whenever a hero object changes s
|
|||||||
Here's the full component implementation:
|
Here's the full component implementation:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="animations/src/app/hero-list-basic.component.ts">
|
<code-example path="animations/src/app/hero-list-basic.component.ts">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -128,6 +134,7 @@ component's template.
|
|||||||
You can define *styles* for each animation state:
|
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 path="animations/src/app/hero-list-basic.component.ts" region="states" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -140,11 +147,13 @@ 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:
|
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 path="animations/src/app/hero-list-basic.component.ts" region="transitions" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<figure class='image-display'>
|
<figure class='image-display'>
|
||||||
<img src="assets/images/devguide/animations/ng_animate_transitions_inactive_active.png" alt="In Angular animations you define states and transitions between states" width="400"> </img>
|
<img src="assets/images/devguide/animations/ng_animate_transitions_inactive_active.png" alt="In Angular animations you define states and transitions between states" width="400"> </img>
|
||||||
</figure>
|
</figure>
|
||||||
@ -153,6 +162,7 @@ If several transitions have the same timing configuration, you can combine
|
|||||||
them into the same `transition` definition:
|
them into the same `transition` definition:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="animations/src/app/hero-list-combined-transitions.component.ts" region="transitions" linenums="false">
|
<code-example path="animations/src/app/hero-list-combined-transitions.component.ts" region="transitions" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -161,6 +171,7 @@ When both directions of a transition have the same timing, as in the previous
|
|||||||
example, you can use the shorthand syntax `<=>`:
|
example, you can use the shorthand syntax `<=>`:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="animations/src/app/hero-list-twoway.component.ts" region="transitions" linenums="false">
|
<code-example path="animations/src/app/hero-list-twoway.component.ts" region="transitions" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -172,6 +183,7 @@ When the transition finishes, none of these styles are kept because they're not
|
|||||||
defined in a `state`.
|
defined in a `state`.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="animations/src/app/hero-list-inline-styles.component.ts" region="transitions" linenums="false">
|
<code-example path="animations/src/app/hero-list-inline-styles.component.ts" region="transitions" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -184,6 +196,7 @@ transitions that apply regardless of which state the animation is in. For exampl
|
|||||||
* The `active => *` transition applies when the element's state changes from `active` to anything else.
|
* The `active => *` transition applies when the element's state changes from `active` to anything else.
|
||||||
* The `* => *` transition applies when *any* change between two states takes place.
|
* The `* => *` transition applies when *any* change between two states takes place.
|
||||||
|
|
||||||
|
|
||||||
<figure class='image-display'>
|
<figure class='image-display'>
|
||||||
<img src="assets/images/devguide/animations/ng_animate_transitions_inactive_active_wildcards.png" alt="The wildcard state can be used to match many different transitions at once" width="400"> </img>
|
<img src="assets/images/devguide/animations/ng_animate_transitions_inactive_active_wildcards.png" alt="The wildcard state can be used to match many different transitions at once" width="400"> </img>
|
||||||
</figure>
|
</figure>
|
||||||
@ -198,6 +211,7 @@ leave animations.
|
|||||||
For example the `* => void` transition applies when the element leaves the view,
|
For example the `* => void` transition applies when the element leaves the view,
|
||||||
regardless of what state it was in before it left.
|
regardless of what state it was in before it left.
|
||||||
|
|
||||||
|
|
||||||
<figure class='image-display'>
|
<figure class='image-display'>
|
||||||
<img src="assets/images/devguide/animations/ng_animate_transitions_void_in.png" alt="The void state can be used for enter and leave transitions" width="400"> </img>
|
<img src="assets/images/devguide/animations/ng_animate_transitions_void_in.png" alt="The void state can be used for enter and leave transitions" width="400"> </img>
|
||||||
</figure>
|
</figure>
|
||||||
@ -205,6 +219,7 @@ regardless of what state it was in before it left.
|
|||||||
The wildcard state `*` also matches `void`.
|
The wildcard state `*` also matches `void`.
|
||||||
|
|
||||||
## Example: Entering and leaving
|
## Example: Entering and leaving
|
||||||
|
|
||||||
<figure>
|
<figure>
|
||||||
<img src="assets/images/devguide/animations/animation_enter_leave.gif" alt="Enter and leave animations" align="right" style="width:250px;"> </img>
|
<img src="assets/images/devguide/animations/animation_enter_leave.gif" alt="Enter and leave animations" align="right" style="width:250px;"> </img>
|
||||||
</figure>
|
</figure>
|
||||||
@ -218,6 +233,7 @@ entering and leaving of elements:
|
|||||||
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.
|
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 path="animations/src/app/hero-list-enter-leave.component.ts" region="animationdef" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -231,6 +247,7 @@ and leaves to the right.
|
|||||||
~~~ {.l-sub-section}
|
~~~ {.l-sub-section}
|
||||||
|
|
||||||
These two common animations have their own aliases:
|
These two common animations have their own aliases:
|
||||||
|
|
||||||
<code-example language="typescript">
|
<code-example language="typescript">
|
||||||
transition(':enter', [ ... ]); // void => *
|
transition(':enter', [ ... ]); // void => *
|
||||||
transition(':leave', [ ... ]); // * => void
|
transition(':leave', [ ... ]); // * => void
|
||||||
@ -242,6 +259,7 @@ These two common animations have their own aliases:
|
|||||||
~~~
|
~~~
|
||||||
|
|
||||||
## Example: Entering and leaving from different states
|
## Example: Entering and leaving from different states
|
||||||
|
|
||||||
<figure>
|
<figure>
|
||||||
<img src="assets/images/devguide/animations/animation_enter_leave_states.gif" alt="Enter and leave animations combined with state animations" align="right" style="width:200px"> </img>
|
<img src="assets/images/devguide/animations/animation_enter_leave_states.gif" alt="Enter and leave animations combined with state animations" align="right" style="width:200px"> </img>
|
||||||
</figure>
|
</figure>
|
||||||
@ -258,12 +276,14 @@ is:
|
|||||||
|
|
||||||
This gives you fine-grained control over each transition:
|
This gives you fine-grained control over each transition:
|
||||||
|
|
||||||
|
|
||||||
<figure class='image-display'>
|
<figure class='image-display'>
|
||||||
<img src="assets/images/devguide/animations/ng_animate_transitions_inactive_active_void.png" alt="This example transitions between active, inactive, and void states" width="400"> </img>
|
<img src="assets/images/devguide/animations/ng_animate_transitions_inactive_active_void.png" alt="This example transitions between active, inactive, and void states" width="400"> </img>
|
||||||
</figure>
|
</figure>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="animations/src/app/hero-list-enter-leave-states.component.ts" region="animationdef" linenums="false">
|
<code-example path="animations/src/app/hero-list-enter-leave-states.component.ts" region="animationdef" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -288,6 +308,7 @@ If you don't provide a unit when specifying dimension, Angular assumes the defau
|
|||||||
* `50` is the same as saying `'50px'`
|
* `50` is the same as saying `'50px'`
|
||||||
|
|
||||||
## Automatic property calculation
|
## Automatic property calculation
|
||||||
|
|
||||||
<figure>
|
<figure>
|
||||||
<img src="assets/images/devguide/animations/animation_auto.gif" alt="Animation with automated height calculation" align="right" style="width:220px;margin-left:20px"> </img>
|
<img src="assets/images/devguide/animations/animation_auto.gif" alt="Animation with automated height calculation" align="right" style="width:220px;margin-left:20px"> </img>
|
||||||
</figure>
|
</figure>
|
||||||
@ -304,6 +325,7 @@ In this example, the leave animation takes whatever height the element has befor
|
|||||||
leaves and animates from that height to zero:
|
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 path="animations/src/app/hero-list-auto.component.ts" region="animationdef" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -342,6 +364,7 @@ and the delay (or as the *second* value when there is no delay):
|
|||||||
* Wait for 100ms and then run for 200ms, with easing: `'0.2s 100ms ease-out'`
|
* Wait for 100ms and then run for 200ms, with easing: `'0.2s 100ms ease-out'`
|
||||||
* Run for 200ms, with easing: `'0.2s ease-in-out'`
|
* Run for 200ms, with easing: `'0.2s ease-in-out'`
|
||||||
|
|
||||||
|
|
||||||
<figure>
|
<figure>
|
||||||
<img src="assets/images/devguide/animations/animation_timings.gif" alt="Animations with specific timings" align="right" style="width:220px;margin-left:20px"> </img>
|
<img src="assets/images/devguide/animations/animation_timings.gif" alt="Animations with specific timings" align="right" style="width:220px;margin-left:20px"> </img>
|
||||||
</figure>
|
</figure>
|
||||||
@ -354,11 +377,13 @@ 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 path="animations/src/app/hero-list-timings.component.ts" region="animationdef" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
|
|
||||||
## Multi-step animations with keyframes
|
## Multi-step animations with keyframes
|
||||||
|
|
||||||
<figure>
|
<figure>
|
||||||
<img src="assets/images/devguide/animations/animation_multistep.gif" alt="Animations with some bounce implemented with keyframes" align="right" style="width:220px;margin-left:20px"> </img>
|
<img src="assets/images/devguide/animations/animation_multistep.gif" alt="Animations with some bounce implemented with keyframes" align="right" style="width:220px;margin-left:20px"> </img>
|
||||||
</figure>
|
</figure>
|
||||||
@ -374,6 +399,7 @@ This example adds some "bounce" to the enter and leave animations with
|
|||||||
keyframes:
|
keyframes:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="animations/src/app/hero-list-multistep.component.ts" region="animationdef" linenums="false">
|
<code-example path="animations/src/app/hero-list-multistep.component.ts" region="animationdef" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -386,6 +412,7 @@ Defining offsets for keyframes is optional. If you omit them, offsets with even
|
|||||||
spacing are automatically assigned. For example, three keyframes without predefined
|
spacing are automatically assigned. For example, three keyframes without predefined
|
||||||
offsets receive offsets `0`, `0.5`, and `1`.
|
offsets receive offsets `0`, `0.5`, and `1`.
|
||||||
## Parallel animation groups
|
## Parallel animation groups
|
||||||
|
|
||||||
<figure>
|
<figure>
|
||||||
<img src="assets/images/devguide/animations/animation_groups.gif" alt="Parallel animations with different timings, implemented with groups" align="right" style="width:220px;margin-left:20px"> </img>
|
<img src="assets/images/devguide/animations/animation_groups.gif" alt="Parallel animations with different timings, implemented with groups" align="right" style="width:220px;margin-left:20px"> </img>
|
||||||
</figure>
|
</figure>
|
||||||
@ -402,6 +429,7 @@ enter and leave allows for two different timing configurations. Both
|
|||||||
are applied to the same element in parallel, but run independently of each other:
|
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 path="animations/src/app/hero-list-groups.component.ts" region="animationdef" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -415,6 +443,7 @@ In the keyframes example, you have a `trigger` called `@flyInOut`. You can hook
|
|||||||
those callbacks like this:
|
those callbacks like this:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="animations/src/app/hero-list-multistep.component.ts" region="template" linenums="false">
|
<code-example path="animations/src/app/hero-list-multistep.component.ts" region="template" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
|
@ -114,13 +114,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:
|
A few minor changes to the lone `app.component` lead to these two class and HTML files:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-tabs>
|
<code-tabs>
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="src/app/app.component.html" path="cb-aot-compiler/src/app/app.component.html">
|
<code-pane title="src/app/app.component.html" path="cb-aot-compiler/src/app/app.component.html">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="src/app/app.component.ts" path="cb-aot-compiler/src/app/app.component.ts">
|
<code-pane title="src/app/app.component.ts" path="cb-aot-compiler/src/app/app.component.ts">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
@ -129,6 +132,7 @@ A few minor changes to the lone `app.component` lead to these two class and HTML
|
|||||||
</code-tabs>
|
</code-tabs>
|
||||||
|
|
||||||
Install a few new npm dependencies with the following command:
|
Install a few new npm dependencies with the following command:
|
||||||
|
|
||||||
<code-example language="none" class="code-shell">
|
<code-example language="none" class="code-shell">
|
||||||
npm install @angular/compiler-cli @angular/platform-server --save
|
npm install @angular/compiler-cli @angular/platform-server --save
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -143,6 +147,7 @@ Copy the original `src/tsconfig.json` to a file called `tsconfig-aot.json` on th
|
|||||||
then modify it as follows.
|
then modify it as follows.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="cb-aot-compiler/tsconfig-aot.json" linenums="false">
|
<code-example path="cb-aot-compiler/tsconfig-aot.json" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -167,6 +172,7 @@ While JIT app URLs are more flexible, stick with _component-relative_ URLs for c
|
|||||||
***Compiling the application***
|
***Compiling the application***
|
||||||
|
|
||||||
Initiate AOT compilation from the command line using the previously installed `ngc` compiler by executing:
|
Initiate AOT compilation from the command line using the previously installed `ngc` compiler by executing:
|
||||||
|
|
||||||
<code-example language="none" class="code-shell">
|
<code-example language="none" class="code-shell">
|
||||||
node_modules/.bin/ngc -p tsconfig-aot.json
|
node_modules/.bin/ngc -p tsconfig-aot.json
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -176,6 +182,7 @@ Initiate AOT compilation from the command line using the previously installed `n
|
|||||||
~~~ {.l-sub-section}
|
~~~ {.l-sub-section}
|
||||||
|
|
||||||
Windows users should surround the `ngc` command in double quotes:
|
Windows users should surround the `ngc` command in double quotes:
|
||||||
|
|
||||||
<code-example format='.'>
|
<code-example format='.'>
|
||||||
"node_modules/.bin/ngc" -p tsconfig-aot.json
|
"node_modules/.bin/ngc" -p tsconfig-aot.json
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -234,13 +241,16 @@ Switch from the `platformBrowserDynamic.bootstrap` used in JIT compilation to
|
|||||||
Here is AOT bootstrap in `main.ts` next to the original JIT version:
|
Here is AOT bootstrap in `main.ts` next to the original JIT version:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-tabs>
|
<code-tabs>
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="src/main.ts" path="cb-aot-compiler/src/main.ts">
|
<code-pane title="src/main.ts" path="cb-aot-compiler/src/main.ts">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="src/main-jit.ts" path="cb-aot-compiler/src/main-jit.ts">
|
<code-pane title="src/main-jit.ts" path="cb-aot-compiler/src/main-jit.ts">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
@ -290,6 +300,7 @@ What matters is that the code uses ES `import` and `export` statements rather th
|
|||||||
~~~
|
~~~
|
||||||
|
|
||||||
In the terminal window, install the Rollup dependencies with this command:
|
In the terminal window, install the Rollup dependencies with this command:
|
||||||
|
|
||||||
<code-example language="none" class="code-shell">
|
<code-example language="none" class="code-shell">
|
||||||
npm install rollup rollup-plugin-node-resolve rollup-plugin-commonjs rollup-plugin-uglify --save-dev
|
npm install rollup rollup-plugin-node-resolve rollup-plugin-commonjs rollup-plugin-uglify --save-dev
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -299,6 +310,7 @@ in the project root directory to tell Rollup how to process the application.
|
|||||||
The cookbook configuration file looks like this.
|
The cookbook configuration file looks like this.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="cb-aot-compiler/rollup-config.js" linenums="false">
|
<code-example path="cb-aot-compiler/rollup-config.js" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -330,6 +342,7 @@ 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">
|
<code-example path="cb-aot-compiler/rollup-config.js" region="commonjs" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -341,6 +354,7 @@ 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">
|
<code-example path="cb-aot-compiler/rollup-config.js" region="uglify" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -360,6 +374,7 @@ the code into an even smaller package going over the wire.
|
|||||||
{@a run-rollup}
|
{@a run-rollup}
|
||||||
### Run Rollup
|
### Run Rollup
|
||||||
Execute the Rollup process with this command:
|
Execute the Rollup process with this command:
|
||||||
|
|
||||||
<code-example language="none" class="code-shell">
|
<code-example language="none" class="code-shell">
|
||||||
node_modules/.bin/rollup -c rollup-config.js
|
node_modules/.bin/rollup -c rollup-config.js
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -369,6 +384,7 @@ Execute the Rollup process with this command:
|
|||||||
~~~ {.l-sub-section}
|
~~~ {.l-sub-section}
|
||||||
|
|
||||||
Windows users should surround the `rollup` command in double quotes:
|
Windows users should surround the `rollup` command in double quotes:
|
||||||
|
|
||||||
<code-example language="none" class="code-shell">
|
<code-example language="none" class="code-shell">
|
||||||
"node_modules/.bin/rollup" -c rollup-config.js
|
"node_modules/.bin/rollup" -c rollup-config.js
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -388,6 +404,7 @@ Remove the scripts that concern SystemJS.
|
|||||||
Instead, load the bundle file using a single `<script>` tag **_after_** the `</body>` tag:
|
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 path="cb-aot-compiler/src/index.html" region="bundle" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -400,6 +417,7 @@ Instead, load the bundle file using a single `<script>` tag **_after_** the `</b
|
|||||||
|
|
||||||
You'll need a web server to host the application.
|
You'll need a web server to host the application.
|
||||||
Use the same `lite-server` employed elsewhere in the documentation:
|
Use the same `lite-server` employed elsewhere in the documentation:
|
||||||
|
|
||||||
<code-example language="none" class="code-shell">
|
<code-example language="none" class="code-shell">
|
||||||
npm run lite
|
npm run lite
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -413,33 +431,40 @@ The server starts, launches a browser, and the app should appear.
|
|||||||
|
|
||||||
Here's the pertinent source code:
|
Here's the pertinent source code:
|
||||||
|
|
||||||
|
|
||||||
<code-tabs>
|
<code-tabs>
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="src/app/app.component.html" path="cb-aot-compiler/src/app/app.component.html">
|
<code-pane title="src/app/app.component.html" path="cb-aot-compiler/src/app/app.component.html">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="src/app/app.component.ts" path="cb-aot-compiler/src/app/app.component.ts">
|
<code-pane title="src/app/app.component.ts" path="cb-aot-compiler/src/app/app.component.ts">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="src/main.ts" path="cb-aot-compiler/src/main.ts">
|
<code-pane title="src/main.ts" path="cb-aot-compiler/src/main.ts">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="src/index.html" path="cb-aot-compiler/src/index.html">
|
<code-pane title="src/index.html" path="cb-aot-compiler/src/index.html">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="tsconfig-aot.json" path="cb-aot-compiler/tsconfig-aot.json">
|
<code-pane title="tsconfig-aot.json" path="cb-aot-compiler/tsconfig-aot.json">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="rollup-config.js" path="cb-aot-compiler/rollup-config.js">
|
<code-pane title="rollup-config.js" path="cb-aot-compiler/rollup-config.js">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
@ -457,6 +482,7 @@ You'll rebuild the AOT version of the application every time you make a change.
|
|||||||
Those _npm_ commands are long and difficult to remember.
|
Those _npm_ commands are long and difficult to remember.
|
||||||
|
|
||||||
Add the following _npm_ convenience script to the `package.json` so you can compile and rollup in one command.Open a terminal window and try it.
|
Add the following _npm_ convenience script to the `package.json` so you can compile and rollup in one command.Open a terminal window and try it.
|
||||||
|
|
||||||
<code-example language="none" class="code-shell">
|
<code-example language="none" class="code-shell">
|
||||||
npm run build:aot
|
npm run build:aot
|
||||||
|
|
||||||
@ -475,6 +501,7 @@ 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`
|
* Delete the script at the bottom of `index-jit.html` that loads `bundle.js`
|
||||||
* Restore the SystemJS scripts like this:
|
* Restore the SystemJS scripts like this:
|
||||||
|
|
||||||
|
|
||||||
<code-example path="cb-aot-compiler/src/index-jit.html" region="jit" linenums="false">
|
<code-example path="cb-aot-compiler/src/index-jit.html" region="jit" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -482,6 +509,7 @@ The same source code can be built both ways. Here's one way to do that.
|
|||||||
Notice the slight change to the `system.import` which now specifies `src/app/main-jit`.
|
Notice the slight change to the `system.import` which now specifies `src/app/main-jit`.
|
||||||
That's the JIT version of the bootstrap file that we preserved [above](guide/aot-compiler#bootstrap).
|
That's the JIT version of the bootstrap file that we preserved [above](guide/aot-compiler#bootstrap).
|
||||||
Open a _different_ terminal window and enter `npm start`.
|
Open a _different_ terminal window and enter `npm start`.
|
||||||
|
|
||||||
<code-example language="none" class="code-shell">
|
<code-example language="none" class="code-shell">
|
||||||
npm start
|
npm start
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -526,13 +554,16 @@ The JIT and AOT apps require their own `index.html` files because they setup and
|
|||||||
Here they are for comparison:
|
Here they are for comparison:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-tabs>
|
<code-tabs>
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="aot/index.html (AOT)" path="toh-6/aot/index.html">
|
<code-pane title="aot/index.html (AOT)" path="toh-6/aot/index.html">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="src/index.html (JIT)" path="toh-6/src/index.html">
|
<code-pane title="src/index.html (JIT)" path="toh-6/src/index.html">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
@ -553,13 +584,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:
|
are evident in these `main` files which can and should reside in the same folder:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-tabs>
|
<code-tabs>
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="main-aot.ts (AOT)" path="toh-6/src/main-aot.ts">
|
<code-pane title="main-aot.ts (AOT)" path="toh-6/src/main-aot.ts">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="main.ts (JIT)" path="toh-6/src/main.ts">
|
<code-pane title="main.ts (JIT)" path="toh-6/src/main.ts">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
@ -576,13 +610,16 @@ AOT requires its own TypeScript configuration settings as well.
|
|||||||
You'll need separate TypeScript configuration files such as these:
|
You'll need separate TypeScript configuration files such as these:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-tabs>
|
<code-tabs>
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="tsconfig-aot.json (AOT)" path="toh-6/tsconfig-aot.json">
|
<code-pane title="tsconfig-aot.json (AOT)" path="toh-6/tsconfig-aot.json">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="src/tsconfig.json (JIT)" path="toh-6/src/tsconfig.1.json">
|
<code-pane title="src/tsconfig.json (JIT)" path="toh-6/src/tsconfig.1.json">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
@ -595,6 +632,7 @@ You'll need separate TypeScript configuration files such as these:
|
|||||||
~~~ {.callout.is-helpful}
|
~~~ {.callout.is-helpful}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<header>
|
<header>
|
||||||
@Types and node modules
|
@Types and node modules
|
||||||
</header>
|
</header>
|
||||||
@ -617,6 +655,7 @@ Edit your `tsconfig-aot.json` to fit your project's file structure.
|
|||||||
Rollup does the tree shaking as before.
|
Rollup does the tree shaking as before.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="toh-6/rollup-config.js" linenums="false">
|
<code-example path="toh-6/rollup-config.js" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -643,23 +682,28 @@ 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.
|
Compiling with AOT presupposes certain supporting files, most of them discussed above.
|
||||||
|
|
||||||
|
|
||||||
<code-tabs>
|
<code-tabs>
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="src/index.html" path="toh-6/src/index.html">
|
<code-pane title="src/index.html" path="toh-6/src/index.html">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="copy-dist-files.js" path="toh-6/copy-dist-files.js">
|
<code-pane title="copy-dist-files.js" path="toh-6/copy-dist-files.js">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="rollup-config.js" path="toh-6/rollup-config.js">
|
<code-pane title="rollup-config.js" path="toh-6/rollup-config.js">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="tsconfig-aot.json" path="toh-6/tsconfig-aot.json">
|
<code-pane title="tsconfig-aot.json" path="toh-6/tsconfig-aot.json">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
@ -668,6 +712,7 @@ Compiling with AOT presupposes certain supporting files, most of them discussed
|
|||||||
</code-tabs>
|
</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:
|
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:
|
||||||
|
|
||||||
<code-example language="none" class="code-shell">
|
<code-example language="none" class="code-shell">
|
||||||
node copy-dist-files
|
node copy-dist-files
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -681,6 +726,7 @@ You won't do that again until there are updates to `zone.js` or the `core-js` sh
|
|||||||
~~~
|
~~~
|
||||||
|
|
||||||
Now AOT-compile the app and launch it with the `lite-server`:
|
Now AOT-compile the app and launch it with the `lite-server`:
|
||||||
|
|
||||||
<code-example language="none" class="code-shell">
|
<code-example language="none" class="code-shell">
|
||||||
npm run build:aot && npm run serve:aot
|
npm run build:aot && npm run serve:aot
|
||||||
|
|
||||||
@ -697,12 +743,14 @@ But the <a href="https://github.com/danvk/source-map-explorer/blob/master/README
|
|||||||
tool can be quite revealing.
|
tool can be quite revealing.
|
||||||
|
|
||||||
Install it:
|
Install it:
|
||||||
|
|
||||||
<code-example language="none" class="code-shell">
|
<code-example language="none" class="code-shell">
|
||||||
npm install source-map-explorer --save-dev
|
npm install source-map-explorer --save-dev
|
||||||
</code-example>
|
</code-example>
|
||||||
|
|
||||||
Run the following command to generate the map.
|
Run the following command to generate the map.
|
||||||
|
|
||||||
|
|
||||||
<code-example language="none" class="code-shell">
|
<code-example language="none" class="code-shell">
|
||||||
node_modules/.bin/source-map-explorer aot/dist/build.js
|
node_modules/.bin/source-map-explorer aot/dist/build.js
|
||||||
|
|
||||||
@ -713,6 +761,7 @@ showing exactly which application and Angular modules and classes are included i
|
|||||||
|
|
||||||
Here's the map for _Tour of Heroes_.
|
Here's the map for _Tour of Heroes_.
|
||||||
<a href="assets/images/cookbooks/aot-compiler/toh6-bundle.png" target="_blank" title="View larger image">
|
<a href="assets/images/cookbooks/aot-compiler/toh6-bundle.png" target="_blank" title="View larger image">
|
||||||
|
|
||||||
<figure class='image-display'>
|
<figure class='image-display'>
|
||||||
<img src="assets/images/cookbooks/aot-compiler/toh6-bundle.png" alt="TOH-6-bundle"> </img>
|
<img src="assets/images/cookbooks/aot-compiler/toh6-bundle.png" alt="TOH-6-bundle"> </img>
|
||||||
</figure>
|
</figure>
|
||||||
|
@ -14,6 +14,7 @@ The [setup](guide/setup) instructions produce a new project with the following m
|
|||||||
You'll evolve this module as your application grows.
|
You'll evolve this module as your application grows.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="setup/src/app/app.module.ts" linenums="false">
|
<code-example path="setup/src/app/app.module.ts" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -119,6 +120,7 @@ Which brings us to the _bootstrapping_ process itself.
|
|||||||
|
|
||||||
{@a main}
|
{@a main}
|
||||||
|
|
||||||
|
|
||||||
<l-main-section>
|
<l-main-section>
|
||||||
|
|
||||||
</l-main-section>
|
</l-main-section>
|
||||||
@ -134,6 +136,7 @@ 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
|
The recommended place to bootstrap a JIT-compiled browser application is in a separate file
|
||||||
in the `src` folder named `src/main.ts`
|
in the `src` folder named `src/main.ts`
|
||||||
|
|
||||||
|
|
||||||
<code-example path="setup/src/main.ts" linenums="false">
|
<code-example path="setup/src/main.ts" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -148,6 +151,7 @@ creates an instance of the component and inserts it within the element tag ident
|
|||||||
The `AppComponent` selector — here and in most documentation samples — is `my-app`
|
The `AppComponent` selector — here and in most documentation samples — is `my-app`
|
||||||
so Angular looks for a `<my-app>` tag in the `index.html` like this one ...
|
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 path="setup/src/index.html" region="my-app" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -156,6 +160,7 @@ so Angular looks for a `<my-app>` tag in the `index.html` like this one ...
|
|||||||
|
|
||||||
This file is very stable. Once you've set it up, you may never change it again.
|
This file is very stable. Once you've set it up, you may never change it again.
|
||||||
|
|
||||||
|
|
||||||
<l-main-section>
|
<l-main-section>
|
||||||
|
|
||||||
</l-main-section>
|
</l-main-section>
|
||||||
|
@ -22,6 +22,7 @@ responding to user interactions according to the instructions you've provided.
|
|||||||
Of course, there is more to it than this.
|
Of course, there is more to it than this.
|
||||||
You'll learn the details in the pages that follow. For now, focus on the big picture.
|
You'll learn the details in the pages that follow. For now, focus on the big picture.
|
||||||
|
|
||||||
|
|
||||||
<figure>
|
<figure>
|
||||||
<img src="assets/images/devguide/architecture/overview2.png" alt="overview" style="margin-left:-40px;" width="700"> </img>
|
<img src="assets/images/devguide/architecture/overview2.png" alt="overview" style="margin-left:-40px;" width="700"> </img>
|
||||||
</figure>
|
</figure>
|
||||||
@ -43,6 +44,7 @@ Learn these building blocks, and you're on your way.
|
|||||||
~~~ {.l-sub-section}
|
~~~ {.l-sub-section}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
The code referenced on this page is available as a <live-example></live-example>.
|
The code referenced on this page is available as a <live-example></live-example>.
|
||||||
</p>
|
</p>
|
||||||
@ -53,6 +55,7 @@ Learn these building blocks, and you're on your way.
|
|||||||
|
|
||||||
|
|
||||||
## Modules
|
## Modules
|
||||||
|
|
||||||
<figure>
|
<figure>
|
||||||
<img src="assets/images/devguide/architecture/module.png" alt="Component" align="left" style="width:240px; margin-left:-40px;margin-right:10px"> </img>
|
<img src="assets/images/devguide/architecture/module.png" alt="Component" align="left" style="width:240px; margin-left:-40px;margin-right:10px"> </img>
|
||||||
</figure>
|
</figure>
|
||||||
@ -98,6 +101,7 @@ that hosts all other app views. Only the _root module_ should set this `bootstra
|
|||||||
|
|
||||||
Here's a simple root module:
|
Here's a simple root module:
|
||||||
|
|
||||||
|
|
||||||
<code-example path="architecture/src/app/mini-app.ts" region="module" linenums="false">
|
<code-example path="architecture/src/app/mini-app.ts" region="module" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -114,6 +118,7 @@ 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.
|
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 path="architecture/src/main.ts" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -130,12 +135,14 @@ 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.
|
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 path="architecture/src/app/app.module.ts" region="imports" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="architecture/src/app/app.module.ts" region="export" linenums="false">
|
<code-example path="architecture/src/app/app.module.ts" region="export" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -151,6 +158,7 @@ Other JavaScript modules use *import statements* to access public objects from o
|
|||||||
These are two different and _complementary_ module systems. Use them both to write your apps.
|
These are two different and _complementary_ module systems. Use them both to write your apps.
|
||||||
### Angular libraries
|
### Angular libraries
|
||||||
|
|
||||||
|
|
||||||
<figure>
|
<figure>
|
||||||
<img src="assets/images/devguide/architecture/library-module.png" alt="Component" align="left" style="width:240px; margin-left:-40px;margin-right:10px"> </img>
|
<img src="assets/images/devguide/architecture/library-module.png" alt="Component" align="left" style="width:240px; margin-left:-40px;margin-right:10px"> </img>
|
||||||
</figure>
|
</figure>
|
||||||
@ -165,18 +173,21 @@ You install them with the **npm** package manager and import parts of them with
|
|||||||
|
|
||||||
For example, import Angular's `Component` decorator from the `@angular/core` library like this:
|
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 path="architecture/src/app/app.component.ts" region="import" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
|
|
||||||
You also import Angular _modules_ from Angular _libraries_ using JavaScript import statements:
|
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 path="architecture/src/app/mini-app.ts" region="import-browser-module" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</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.
|
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 path="architecture/src/app/mini-app.ts" region="ngmodule-imports" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -195,6 +206,7 @@ Learn more from the [Angular modules](guide/ngmodule) page.
|
|||||||
~~~
|
~~~
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<div class='l-hr'>
|
<div class='l-hr'>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
@ -202,6 +214,7 @@ Learn more from the [Angular modules](guide/ngmodule) page.
|
|||||||
|
|
||||||
## Components
|
## Components
|
||||||
|
|
||||||
|
|
||||||
<figure>
|
<figure>
|
||||||
<img src="assets/images/devguide/architecture/hero-component.png" alt="Component" align="left" style="width:200px; margin-left:-40px;margin-right:10px"> </img>
|
<img src="assets/images/devguide/architecture/hero-component.png" alt="Component" align="left" style="width:200px; margin-left:-40px;margin-right:10px"> </img>
|
||||||
</figure>
|
</figure>
|
||||||
@ -223,6 +236,7 @@ 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.
|
`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 path="architecture/src/app/hero-list.component.ts" linenums="false" title="src/app/hero-list.component.ts (class)" region="class">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -230,12 +244,14 @@ that it acquires from a service.
|
|||||||
Angular creates, updates, and destroys components as the user moves through the application.
|
Angular creates, updates, and destroys components as the user moves through the application.
|
||||||
Your app can take action at each moment in this lifecycle through optional [lifecycle hooks](guide/lifecycle-hooks), like `ngOnInit()` declared above.
|
Your app can take action at each moment in this lifecycle through optional [lifecycle hooks](guide/lifecycle-hooks), like `ngOnInit()` declared above.
|
||||||
|
|
||||||
|
|
||||||
<div class='l-hr'>
|
<div class='l-hr'>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
## Templates
|
## Templates
|
||||||
|
|
||||||
<figure>
|
<figure>
|
||||||
<img src="assets/images/devguide/architecture/template.png" alt="Template" align="left" style="width:200px; margin-left:-40px;margin-right:10px"> </img>
|
<img src="assets/images/devguide/architecture/template.png" alt="Template" align="left" style="width:200px; margin-left:-40px;margin-right:10px"> </img>
|
||||||
</figure>
|
</figure>
|
||||||
@ -247,6 +263,7 @@ A template looks like regular HTML, except for a few differences. Here is a
|
|||||||
template for our `HeroListComponent`:
|
template for our `HeroListComponent`:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="architecture/src/app/hero-list.component.html">
|
<code-example path="architecture/src/app/hero-list.component.html">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -261,18 +278,21 @@ The `HeroDetailComponent` (code not shown) presents facts about a particular her
|
|||||||
hero that the user selects from the list presented by the `HeroListComponent`.
|
hero that the user selects from the list presented by the `HeroListComponent`.
|
||||||
The `HeroDetailComponent` is a **child** of the `HeroListComponent`.
|
The `HeroDetailComponent` is a **child** of the `HeroListComponent`.
|
||||||
|
|
||||||
|
|
||||||
<figure>
|
<figure>
|
||||||
<img src="assets/images/devguide/architecture/component-tree.png" alt="Metadata" align="left" style="width:300px; margin-left:-40px;margin-right:10px"> </img>
|
<img src="assets/images/devguide/architecture/component-tree.png" alt="Metadata" align="left" style="width:300px; margin-left:-40px;margin-right:10px"> </img>
|
||||||
</figure>
|
</figure>
|
||||||
|
|
||||||
Notice how `<hero-detail>` rests comfortably among native HTML elements. Custom components mix seamlessly with native HTML in the same layouts.
|
Notice how `<hero-detail>` rests comfortably among native HTML elements. Custom components mix seamlessly with native HTML in the same layouts.
|
||||||
<br class="l-clear-both">
|
<br class="l-clear-both">
|
||||||
|
|
||||||
<div class='l-hr'>
|
<div class='l-hr'>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
## Metadata
|
## Metadata
|
||||||
|
|
||||||
<figure>
|
<figure>
|
||||||
<img src="assets/images/devguide/architecture/metadata.png" alt="Metadata" align="left" style="width:150px; margin-left:-40px;margin-right:10px"> </img>
|
<img src="assets/images/devguide/architecture/metadata.png" alt="Metadata" align="left" style="width:150px; margin-left:-40px;margin-right:10px"> </img>
|
||||||
</figure>
|
</figure>
|
||||||
@ -289,6 +309,7 @@ In !{_Lang}, you attach metadata by using !{_a} **!{_decorator}**.
|
|||||||
Here's some metadata for `HeroListComponent`:
|
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 path="architecture/src/app/hero-list.component.ts" linenums="false" title="src/app/hero-list.component.ts (metadata)" region="metadata">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -311,6 +332,7 @@ Angular inserts an instance of the `HeroListComponent` view between those tags.
|
|||||||
This is one way to tell Angular that the component's constructor requires a `HeroService`
|
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.
|
so it can get the list of heroes to display.
|
||||||
|
|
||||||
|
|
||||||
<figure>
|
<figure>
|
||||||
<img src="assets/images/devguide/architecture/template-metadata-component.png" alt="Metadata" align="left" style="height:200px; margin-left:-40px;margin-right:10px"> </img>
|
<img src="assets/images/devguide/architecture/template-metadata-component.png" alt="Metadata" align="left" style="height:200px; margin-left:-40px;margin-right:10px"> </img>
|
||||||
</figure>
|
</figure>
|
||||||
@ -323,6 +345,7 @@ Apply other metadata !{_decorator}s in a similar fashion to guide Angular behavi
|
|||||||
`@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
|
`@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
|
||||||
so that Angular knows what to do.
|
so that Angular knows what to do.
|
||||||
|
|
||||||
|
|
||||||
<div class='l-hr'>
|
<div class='l-hr'>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
@ -332,6 +355,7 @@ so that Angular knows what to do.
|
|||||||
Without a framework, you would be responsible for pushing data values into the HTML controls and turning user responses
|
Without a framework, you would be responsible for pushing data values into the HTML controls and turning user responses
|
||||||
into actions and value updates. Writing such push/pull logic by hand is tedious, error-prone, and a nightmare to
|
into actions and value updates. Writing such push/pull logic by hand is tedious, error-prone, and a nightmare to
|
||||||
read as any experienced jQuery programmer can attest.
|
read as any experienced jQuery programmer can attest.
|
||||||
|
|
||||||
<figure>
|
<figure>
|
||||||
<img src="assets/images/devguide/architecture/databinding.png" alt="Data Binding" style="width:220px; float:left; margin-left:-40px;margin-right:20px"> </img>
|
<img src="assets/images/devguide/architecture/databinding.png" alt="Data Binding" style="width:220px; float:left; margin-left:-40px;margin-right:20px"> </img>
|
||||||
</figure>
|
</figure>
|
||||||
@ -343,6 +367,7 @@ 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 — 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:
|
As the diagram shows, there are four forms of data binding syntax. Each form has a direction — 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 path="architecture/src/app/hero-list.component.1.html" linenums="false" title="src/app/hero-list.component.html (binding)" region="binding">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -360,6 +385,7 @@ that combines property and event binding in a single notation, using the `ngMode
|
|||||||
Here's an example from the `HeroDetailComponent` template:
|
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 path="architecture/src/app/hero-detail.component.html" linenums="false" title="src/app/hero-detail.component.html (ngModel)" region="ngModel">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -371,23 +397,27 @@ as with event binding.
|
|||||||
Angular processes *all* data bindings once per JavaScript event cycle,
|
Angular processes *all* data bindings once per JavaScript event cycle,
|
||||||
from the root of the application component tree through all child components.
|
from the root of the application component tree through all child components.
|
||||||
|
|
||||||
|
|
||||||
<figure>
|
<figure>
|
||||||
<img src="assets/images/devguide/architecture/component-databinding.png" alt="Data Binding" style="float:left; width:300px; margin-left:-40px;margin-right:10px"> </img>
|
<img src="assets/images/devguide/architecture/component-databinding.png" alt="Data Binding" style="float:left; width:300px; margin-left:-40px;margin-right:10px"> </img>
|
||||||
</figure>
|
</figure>
|
||||||
|
|
||||||
Data binding plays an important role in communication
|
Data binding plays an important role in communication
|
||||||
between a template and its component.<br class="l-clear-both">
|
between a template and its component.<br class="l-clear-both">
|
||||||
|
|
||||||
<figure>
|
<figure>
|
||||||
<img src="assets/images/devguide/architecture/parent-child-binding.png" alt="Parent/Child binding" style="float:left; width:300px; margin-left:-40px;margin-right:10px"> </img>
|
<img src="assets/images/devguide/architecture/parent-child-binding.png" alt="Parent/Child binding" style="float:left; width:300px; margin-left:-40px;margin-right:10px"> </img>
|
||||||
</figure>
|
</figure>
|
||||||
|
|
||||||
Data binding is also important for communication between parent and child components.<br class="l-clear-both">
|
Data binding is also important for communication between parent and child components.<br class="l-clear-both">
|
||||||
|
|
||||||
<div class='l-hr'>
|
<div class='l-hr'>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
## Directives
|
## Directives
|
||||||
|
|
||||||
<figure>
|
<figure>
|
||||||
<img src="assets/images/devguide/architecture/directive.png" alt="Parent child" style="float:left; width:150px; margin-left:-40px;margin-right:10px"> </img>
|
<img src="assets/images/devguide/architecture/directive.png" alt="Parent child" style="float:left; width:150px; margin-left:-40px;margin-right:10px"> </img>
|
||||||
</figure>
|
</figure>
|
||||||
@ -418,6 +448,7 @@ 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:
|
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 path="architecture/src/app/hero-list.component.1.html" linenums="false" title="src/app/hero-list.component.html (structural)" region="structural">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -434,6 +465,7 @@ an existing element (typically an `<input>`)
|
|||||||
by setting its display value property and responding to change events.
|
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 path="architecture/src/app/hero-detail.component.html" linenums="false" title="src/app/hero-detail.component.html (ngModel)" region="ngModel">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -447,12 +479,14 @@ Of course, you can also write your own directives. Components such as
|
|||||||
`HeroListComponent` are one kind of custom directive.
|
`HeroListComponent` are one kind of custom directive.
|
||||||
<!-- PENDING: link to where to learn more about other kinds! -->
|
<!-- PENDING: link to where to learn more about other kinds! -->
|
||||||
|
|
||||||
|
|
||||||
<div class='l-hr'>
|
<div class='l-hr'>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
## Services
|
## Services
|
||||||
|
|
||||||
<figure>
|
<figure>
|
||||||
<img src="assets/images/devguide/architecture/service.png" alt="Service" style="float:left; margin-left:-40px;margin-right:10px"> </img>
|
<img src="assets/images/devguide/architecture/service.png" alt="Service" style="float:left; margin-left:-40px;margin-right:10px"> </img>
|
||||||
</figure>
|
</figure>
|
||||||
@ -475,6 +509,7 @@ 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:
|
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 path="architecture/src/app/logger.service.ts" linenums="false" title="src/app/logger.service.ts (class)" region="class">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -483,6 +518,7 @@ Here's a `HeroService` that uses a !{_PromiseLinked} to fetch heroes.
|
|||||||
The `HeroService` depends on the `Logger` service and another `BackendService` that handles the server communication grunt work.
|
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 path="architecture/src/app/hero.service.ts" linenums="false" title="src/app/hero.service.ts (class)" region="class">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -504,12 +540,14 @@ It won't complain if you write a "kitchen sink" component with 3000 lines.
|
|||||||
Angular does help you *follow* these principles by making it easy to factor your
|
Angular does help you *follow* these principles by making it easy to factor your
|
||||||
application logic into services and make those services available to components through *dependency injection*.
|
application logic into services and make those services available to components through *dependency injection*.
|
||||||
|
|
||||||
|
|
||||||
<div class='l-hr'>
|
<div class='l-hr'>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
## Dependency injection
|
## Dependency injection
|
||||||
|
|
||||||
<figure>
|
<figure>
|
||||||
<img src="assets/images/devguide/architecture/dependency-injection.png" alt="Service" style="float:left; width:200px; margin-left:-40px;margin-right:10px"> </img>
|
<img src="assets/images/devguide/architecture/dependency-injection.png" alt="Service" style="float:left; width:200px; margin-left:-40px;margin-right:10px"> </img>
|
||||||
</figure>
|
</figure>
|
||||||
@ -520,6 +558,7 @@ Angular uses dependency injection to provide new components with the services th
|
|||||||
For example, the constructor of your `HeroListComponent` needs a `HeroService`:
|
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 path="architecture/src/app/hero-list.component.ts" linenums="false" title="src/app/hero-list.component.ts (constructor)" region="ctor">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -535,6 +574,7 @@ Angular can call the component's constructor with those services as arguments.
|
|||||||
This is *dependency injection*.
|
This is *dependency injection*.
|
||||||
|
|
||||||
The process of `HeroService` injection looks a bit like this:
|
The process of `HeroService` injection looks a bit like this:
|
||||||
|
|
||||||
<figure>
|
<figure>
|
||||||
<img src="assets/images/devguide/architecture/injector-injects.png" alt="Service"> </img>
|
<img src="assets/images/devguide/architecture/injector-injects.png" alt="Service"> </img>
|
||||||
</figure>
|
</figure>
|
||||||
@ -550,6 +590,7 @@ In general, add providers to the [root module](guide/architecture#module) so tha
|
|||||||
the same instance of a service is available everywhere.
|
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 path="architecture/src/app/app.module.ts" linenums="false" title="src/app/app.module.ts (module providers)" region="providers">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -557,6 +598,7 @@ the same instance of a service is available everywhere.
|
|||||||
Alternatively, register at a component level in the `providers` property of the `@Component` metadata:
|
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 path="architecture/src/app/hero-list.component.ts" linenums="false" title="src/app/hero-list.component.ts (component providers)" region="providers">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -579,6 +621,7 @@ Points to remember about dependency injection:
|
|||||||
|
|
||||||
* Register *providers* with injectors.
|
* Register *providers* with injectors.
|
||||||
|
|
||||||
|
|
||||||
<div class='l-hr'>
|
<div class='l-hr'>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
@ -51,6 +51,7 @@ directive to set an element's background color
|
|||||||
when the user hovers over that element. You can apply it like this:
|
when the user hovers over that element. You can apply it like this:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="attribute-directives/src/app/app.component.1.html" linenums="false" title="src/app/app.component.html (applied)" region="applied">
|
<code-example path="attribute-directives/src/app/app.component.1.html" linenums="false" title="src/app/app.component.html (applied)" region="applied">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -63,6 +64,7 @@ named <span ngio-ex>attribute-directives</span>.
|
|||||||
Create the following source file in the indicated folder:
|
Create the following source file in the indicated folder:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="attribute-directives/src/app/highlight.directive.1.ts">
|
<code-example path="attribute-directives/src/app/highlight.directive.1.ts">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -120,6 +122,7 @@ Put the template in its own <span ngio-ex>app.component.html</span>
|
|||||||
file that looks like this:
|
file that looks like this:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="attribute-directives/src/app/app.component.1.html">
|
<code-example path="attribute-directives/src/app/app.component.1.html">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -127,6 +130,7 @@ file that looks like this:
|
|||||||
Now reference this template in the `AppComponent`:
|
Now reference this template in the `AppComponent`:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="attribute-directives/src/app/app.component.ts">
|
<code-example path="attribute-directives/src/app/app.component.ts">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -136,12 +140,14 @@ add that class to the `declarations` NgModule metadata. This way Angular
|
|||||||
recognizes the directive when it encounters `myHighlight` in the template.
|
recognizes the directive when it encounters `myHighlight` in the template.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="attribute-directives/src/app/app.module.ts">
|
<code-example path="attribute-directives/src/app/app.module.ts">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
|
|
||||||
Now when the app runs, the `myHighlight` directive highlights the paragraph text.
|
Now when the app runs, the `myHighlight` directive highlights the paragraph text.
|
||||||
|
|
||||||
|
|
||||||
<figure class='image-display'>
|
<figure class='image-display'>
|
||||||
<img src="assets/images/devguide/attribute-directives/first-highlight.png" alt="First Highlight"> </img>
|
<img src="assets/images/devguide/attribute-directives/first-highlight.png" alt="First Highlight"> </img>
|
||||||
</figure>
|
</figure>
|
||||||
@ -156,6 +162,7 @@ Did you remember to add the directive to the `declarations` attribute of `@NgMod
|
|||||||
It is easy to forget!
|
It is easy to forget!
|
||||||
Open the console in the browser tools and look for an error like this:
|
Open the console in the browser tools and look for an error like this:
|
||||||
|
|
||||||
|
|
||||||
<code-example format="nocode">
|
<code-example format="nocode">
|
||||||
EXCEPTION: Template parse errors:
|
EXCEPTION: Template parse errors:
|
||||||
Can't bind to 'myHighlight' since it isn't a known property of 'p'.
|
Can't bind to 'myHighlight' since it isn't a known property of 'p'.
|
||||||
@ -186,6 +193,7 @@ Begin by adding `HostListener` to the list of imported symbols;
|
|||||||
add the `Input` symbol as well because you'll need it soon.
|
add the `Input` symbol as well because you'll need it soon.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="attribute-directives/src/app/highlight.directive.ts" linenums="false" title="src/app/highlight.directive.ts (imports)" region="imports">
|
<code-example path="attribute-directives/src/app/highlight.directive.ts" linenums="false" title="src/app/highlight.directive.ts (imports)" region="imports">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -194,6 +202,7 @@ Then add two eventhandlers that respond when the mouse enters or leaves,
|
|||||||
each adorned by the `HostListener` !{_decorator}.
|
each adorned by the `HostListener` !{_decorator}.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="attribute-directives/src/app/highlight.directive.2.ts" linenums="false" title="src/app/highlight.directive.ts (mouse-methods)" region="mouse-methods">
|
<code-example path="attribute-directives/src/app/highlight.directive.2.ts" linenums="false" title="src/app/highlight.directive.ts (mouse-methods)" region="mouse-methods">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -218,6 +227,7 @@ The handlers delegate to a helper method that sets the color on the DOM element,
|
|||||||
which you declare and initialize in the constructor.
|
which you declare and initialize in the constructor.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="attribute-directives/src/app/highlight.directive.2.ts" linenums="false" title="src/app/highlight.directive.ts (constructor)" region="ctor">
|
<code-example path="attribute-directives/src/app/highlight.directive.2.ts" linenums="false" title="src/app/highlight.directive.ts (constructor)" region="ctor">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -225,6 +235,7 @@ which you declare and initialize in the constructor.
|
|||||||
Here's the updated directive in full:
|
Here's the updated directive in full:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="attribute-directives/src/app/highlight.directive.2.ts">
|
<code-example path="attribute-directives/src/app/highlight.directive.2.ts">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -232,6 +243,7 @@ Here's the updated directive in full:
|
|||||||
Run the app and confirm that the background color appears when
|
Run the app and confirm that the background color appears when
|
||||||
the mouse hovers over the `p` and disappears as it moves out.
|
the mouse hovers over the `p` and disappears as it moves out.
|
||||||
|
|
||||||
|
|
||||||
<figure class='image-display'>
|
<figure class='image-display'>
|
||||||
<img src="assets/images/devguide/attribute-directives/highlight-directive-anim.gif" alt="Second Highlight"> </img>
|
<img src="assets/images/devguide/attribute-directives/highlight-directive-anim.gif" alt="Second Highlight"> </img>
|
||||||
</figure>
|
</figure>
|
||||||
@ -245,6 +257,7 @@ 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:
|
Start by adding a `highlightColor` property to the directive class like this:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="attribute-directives/src/app/highlight.directive.2.ts" linenums="false" title="src/app/highlight.directive.ts (highlightColor)" region="color">
|
<code-example path="attribute-directives/src/app/highlight.directive.2.ts" linenums="false" title="src/app/highlight.directive.ts (highlightColor)" region="color">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -262,6 +275,7 @@ Without that input metadata, Angular rejects the binding; see [below](guide/attr
|
|||||||
Try it by adding the following directive binding variations to the `AppComponent` template:
|
Try it by adding the following directive binding variations to the `AppComponent` template:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="attribute-directives/src/app/app.component.1.html" linenums="false" title="src/app/app.component.html (excerpt)" region="color-1">
|
<code-example path="attribute-directives/src/app/app.component.1.html" linenums="false" title="src/app/app.component.html (excerpt)" region="color-1">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -269,6 +283,7 @@ Try it by adding the following directive binding variations to the `AppComponent
|
|||||||
Add a `color` property to the `AppComponent`.
|
Add a `color` property to the `AppComponent`.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="attribute-directives/src/app/app.component.1.ts" linenums="false" title="src/app/app.component.ts (class)" region="class">
|
<code-example path="attribute-directives/src/app/app.component.1.ts" linenums="false" title="src/app/app.component.ts (class)" region="class">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -276,6 +291,7 @@ Add a `color` property to the `AppComponent`.
|
|||||||
Let it control the highlight color with a property binding.
|
Let it control the highlight color with a property binding.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="attribute-directives/src/app/app.component.1.html" linenums="false" title="src/app/app.component.html (excerpt)" region="color-2">
|
<code-example path="attribute-directives/src/app/app.component.1.html" linenums="false" title="src/app/app.component.html (excerpt)" region="color-2">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -283,6 +299,7 @@ Let it control the highlight color with a property binding.
|
|||||||
That's good, but it would be nice to _simultaneously_ apply the directive and set the color _in the same attribute_ like this.
|
That's good, but it would be nice to _simultaneously_ apply the directive and set the color _in the same attribute_ like this.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="attribute-directives/src/app/app.component.html" linenums="false" title="src/app/app.component.html (color)" region="color">
|
<code-example path="attribute-directives/src/app/app.component.html" linenums="false" title="src/app/app.component.html (color)" region="color">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -295,6 +312,7 @@ 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.
|
You'll have to rename the directive's `highlightColor` property to `myHighlight` because that's now the color property binding name.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="attribute-directives/src/app/highlight.directive.2.ts" linenums="false" title="src/app/highlight.directive.ts (renamed to match directive selector)" region="color-2">
|
<code-example path="attribute-directives/src/app/highlight.directive.2.ts" linenums="false" title="src/app/highlight.directive.ts (renamed to match directive selector)" region="color-2">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -310,6 +328,7 @@ Fortunately you can name the directive property whatever you want _and_ **_alias
|
|||||||
Restore the original property name and specify the selector as the alias in the argument to `@Input`.
|
Restore the original property name and specify the selector as the alias in the argument to `@Input`.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="attribute-directives/src/app/highlight.directive.ts" linenums="false" title="src/app/highlight.directive.ts (color property with alias)" region="color">
|
<code-example path="attribute-directives/src/app/highlight.directive.ts" linenums="false" title="src/app/highlight.directive.ts (color property with alias)" region="color">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -320,6 +339,7 @@ _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:
|
You get the best of both worlds: the property name you want and the binding syntax you want:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="attribute-directives/src/app/app.component.html" linenums="false" title="src/app/app.component.html (color)" region="color">
|
<code-example path="attribute-directives/src/app/app.component.html" linenums="false" title="src/app/app.component.html (color)" region="color">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -328,6 +348,7 @@ Now that you're binding to `highlightColor`, modify the `onMouseEnter()` method
|
|||||||
If someone neglects to bind to `highlightColor`, highlight in red:
|
If someone neglects to bind to `highlightColor`, highlight in red:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="attribute-directives/src/app/highlight.directive.3.ts" linenums="false" title="src/app/highlight.directive.ts (mouse enter)" region="mouse-enter">
|
<code-example path="attribute-directives/src/app/highlight.directive.3.ts" linenums="false" title="src/app/highlight.directive.ts (mouse enter)" region="mouse-enter">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -335,6 +356,7 @@ If someone neglects to bind to `highlightColor`, highlight in red:
|
|||||||
Here's the latest version of the directive class.
|
Here's the latest version of the directive class.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="attribute-directives/src/app/highlight.directive.3.ts" linenums="false" title="src/app/highlight.directive.ts (excerpt)">
|
<code-example path="attribute-directives/src/app/highlight.directive.3.ts" linenums="false" title="src/app/highlight.directive.ts (excerpt)">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -348,6 +370,7 @@ lets you pick the highlight color with a radio button and bind your color choice
|
|||||||
Update <span ngio-ex>app.component.html</span> as follows:
|
Update <span ngio-ex>app.component.html</span> as follows:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="attribute-directives/src/app/app.component.html" linenums="false" title="src/app/app.component.html (v2)" region="v2">
|
<code-example path="attribute-directives/src/app/app.component.html" linenums="false" title="src/app/app.component.html (v2)" region="v2">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -355,12 +378,14 @@ Update <span ngio-ex>app.component.html</span> as follows:
|
|||||||
Revise the `AppComponent.color` so that it has no initial value.
|
Revise the `AppComponent.color` so that it has no initial value.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="attribute-directives/src/app/app.component.ts" linenums="false" title="src/app/app.component.ts (class)" region="class">
|
<code-example path="attribute-directives/src/app/app.component.ts" linenums="false" title="src/app/app.component.ts (class)" region="class">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
|
|
||||||
Here are the harness and directive in action.
|
Here are the harness and directive in action.
|
||||||
|
|
||||||
|
|
||||||
<figure class='image-display'>
|
<figure class='image-display'>
|
||||||
<img src="assets/images/devguide/attribute-directives/highlight-directive-v2-anim.gif" alt="Highlight v.2"> </img>
|
<img src="assets/images/devguide/attribute-directives/highlight-directive-v2-anim.gif" alt="Highlight v.2"> </img>
|
||||||
</figure>
|
</figure>
|
||||||
@ -377,6 +402,7 @@ Let the template developer set the default color.
|
|||||||
Add a second **input** property to `HighlightDirective` called `defaultColor`:
|
Add a second **input** property to `HighlightDirective` called `defaultColor`:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="attribute-directives/src/app/highlight.directive.ts" linenums="false" title="src/app/highlight.directive.ts (defaultColor)" region="defaultColor">
|
<code-example path="attribute-directives/src/app/highlight.directive.ts" linenums="false" title="src/app/highlight.directive.ts (defaultColor)" region="defaultColor">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -385,6 +411,7 @@ Revise the directive's `onMouseEnter` so that it first tries to highlight with t
|
|||||||
then with the `defaultColor`, and falls back to "red" if both properties are undefined.
|
then with the `defaultColor`, and falls back to "red" if both properties are undefined.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="attribute-directives/src/app/highlight.directive.ts" linenums="false" title="src/app/highlight.directive.ts (mouse-enter)" region="mouse-enter">
|
<code-example path="attribute-directives/src/app/highlight.directive.ts" linenums="false" title="src/app/highlight.directive.ts (mouse-enter)" region="mouse-enter">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -396,6 +423,7 @@ The developer should be able to write the following template HTML to both bind t
|
|||||||
and fall back to "violet" as the default color.
|
and fall back to "violet" as the default color.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="attribute-directives/src/app/app.component.html" linenums="false" title="src/app/app.component.html (defaultColor)" region="defaultColor">
|
<code-example path="attribute-directives/src/app/app.component.html" linenums="false" title="src/app/app.component.html (defaultColor)" region="defaultColor">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -405,6 +433,7 @@ because you made it _public_ with the `@Input` !{_decorator}.
|
|||||||
|
|
||||||
Here's how the harness should work when you're done coding.
|
Here's how the harness should work when you're done coding.
|
||||||
|
|
||||||
|
|
||||||
<figure class='image-display'>
|
<figure class='image-display'>
|
||||||
<img src="assets/images/devguide/attribute-directives/highlight-directive-final-anim.gif" alt="Final Highlight"> </img>
|
<img src="assets/images/devguide/attribute-directives/highlight-directive-final-anim.gif" alt="Final Highlight"> </img>
|
||||||
</figure>
|
</figure>
|
||||||
@ -422,33 +451,40 @@ This page covered how to:
|
|||||||
The final source code follows:
|
The final source code follows:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-tabs>
|
<code-tabs>
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="app/app.component.ts" path="attribute-directives/src/app/app.component.ts">
|
<code-pane title="app/app.component.ts" path="attribute-directives/src/app/app.component.ts">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="app/app.component.html" path="attribute-directives/src/app/app.component.html">
|
<code-pane title="app/app.component.html" path="attribute-directives/src/app/app.component.html">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="app/highlight.directive.ts" path="attribute-directives/src/app/highlight.directive.ts">
|
<code-pane title="app/highlight.directive.ts" path="attribute-directives/src/app/highlight.directive.ts">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="app/app.module.ts" path="attribute-directives/src/app/app.module.ts">
|
<code-pane title="app/app.module.ts" path="attribute-directives/src/app/app.module.ts">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="main.ts" path="attribute-directives/src/main.ts">
|
<code-pane title="main.ts" path="attribute-directives/src/main.ts">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="index.html" path="attribute-directives/src/index.html">
|
<code-pane title="index.html" path="attribute-directives/src/index.html">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
@ -464,6 +500,7 @@ In this demo, the `hightlightColor` property is an ***input*** property of
|
|||||||
the `HighlightDirective`. You've seen it applied without an alias:
|
the `HighlightDirective`. You've seen it applied without an alias:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="attribute-directives/src/app/highlight.directive.2.ts" linenums="false" title="src/app/highlight.directive.ts (color)" region="color">
|
<code-example path="attribute-directives/src/app/highlight.directive.2.ts" linenums="false" title="src/app/highlight.directive.ts (color)" region="color">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -471,6 +508,7 @@ the `HighlightDirective`. You've seen it applied without an alias:
|
|||||||
You've seen it with an alias:
|
You've seen it with an alias:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="attribute-directives/src/app/highlight.directive.ts" linenums="false" title="src/app/highlight.directive.ts (color)" region="color">
|
<code-example path="attribute-directives/src/app/highlight.directive.ts" linenums="false" title="src/app/highlight.directive.ts (color)" region="color">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -506,6 +544,7 @@ You can tell if `@Input` is needed by the position of the property name in a bin
|
|||||||
Now apply that reasoning to the following example:
|
Now apply that reasoning to the following example:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="attribute-directives/src/app/app.component.html" linenums="false" title="src/app/app.component.html (color)" region="color">
|
<code-example path="attribute-directives/src/app/app.component.html" linenums="false" title="src/app/app.component.html (color)" region="color">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
|
@ -8,45 +8,55 @@ Browser support and polyfills guide.
|
|||||||
|
|
||||||
Angular supports most recent browsers. This includes the following specific versions:
|
Angular supports most recent browsers. This includes the following specific versions:
|
||||||
|
|
||||||
|
|
||||||
<table>
|
<table>
|
||||||
|
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
|
|
||||||
|
|
||||||
<th>
|
<th>
|
||||||
Chrome
|
Chrome
|
||||||
</th>
|
</th>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<th>
|
<th>
|
||||||
Firefox
|
Firefox
|
||||||
</th>
|
</th>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<th>
|
<th>
|
||||||
Edge
|
Edge
|
||||||
</th>
|
</th>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<th>
|
<th>
|
||||||
IE
|
IE
|
||||||
</th>
|
</th>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<th>
|
<th>
|
||||||
Safari
|
Safari
|
||||||
</th>
|
</th>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<th>
|
<th>
|
||||||
iOS
|
iOS
|
||||||
</th>
|
</th>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<th>
|
<th>
|
||||||
Android
|
Android
|
||||||
</th>
|
</th>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<th>
|
<th>
|
||||||
IE mobile
|
IE mobile
|
||||||
</th>
|
</th>
|
||||||
@ -55,43 +65,52 @@ Angular supports most recent browsers. This includes the following specific vers
|
|||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
latest
|
latest
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
latest
|
latest
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
14
|
14
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
11
|
11
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
10
|
10
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
10
|
10
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
Marshmallow (6.0)
|
Marshmallow (6.0)
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
11
|
11
|
||||||
</td>
|
</td>
|
||||||
@ -100,43 +119,52 @@ Angular supports most recent browsers. This includes the following specific vers
|
|||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
|
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
|
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
13
|
13
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
10
|
10
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
9
|
9
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
9
|
9
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
Lollipop<br>(5.0, 5.1)
|
Lollipop<br>(5.0, 5.1)
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
|
|
||||||
</td>
|
</td>
|
||||||
@ -145,43 +173,52 @@ Angular supports most recent browsers. This includes the following specific vers
|
|||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
|
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
|
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
|
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
9
|
9
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
8
|
8
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
8
|
8
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
KitKat<br>(4.4)
|
KitKat<br>(4.4)
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
|
|
||||||
</td>
|
</td>
|
||||||
@ -190,43 +227,52 @@ Angular supports most recent browsers. This includes the following specific vers
|
|||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
|
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
|
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
|
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
|
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
7
|
7
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
7
|
7
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
Jelly Bean<br>(4.1, 4.2, 4.3)
|
Jelly Bean<br>(4.1, 4.2, 4.3)
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
|
|
||||||
</td>
|
</td>
|
||||||
@ -255,6 +301,7 @@ Targeting such a wide range of browsers is challenging because they do not suppo
|
|||||||
You can 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.
|
that implement missing features in JavaScript.
|
||||||
|
|
||||||
|
|
||||||
<code-example path="quickstart/src/index.html" region="polyfills" linenums="false">
|
<code-example path="quickstart/src/index.html" region="polyfills" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -277,15 +324,19 @@ Note that polyfills cannot magically transform an old, slow browser into a moder
|
|||||||
### Mandatory polyfills ##
|
### Mandatory polyfills ##
|
||||||
These are the polyfills required to run an Angular application on each supported browser:
|
These are the polyfills required to run an Angular application on each supported browser:
|
||||||
|
|
||||||
|
|
||||||
<table>
|
<table>
|
||||||
|
|
||||||
|
|
||||||
<tr style="vertical-align: top">
|
<tr style="vertical-align: top">
|
||||||
|
|
||||||
|
|
||||||
<th>
|
<th>
|
||||||
Browsers (desktop & mobile)
|
Browsers (desktop & mobile)
|
||||||
</th>
|
</th>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<th>
|
<th>
|
||||||
Polyfills required
|
Polyfills required
|
||||||
</th>
|
</th>
|
||||||
@ -294,13 +345,16 @@ These are the polyfills required to run an Angular application on each supported
|
|||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<tr style="vertical-align: top">
|
<tr style="vertical-align: top">
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
Chrome, Firefox, Edge, Safari 9+
|
Chrome, Firefox, Edge, Safari 9+
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
None
|
None
|
||||||
</td>
|
</td>
|
||||||
@ -309,13 +363,16 @@ These are the polyfills required to run an Angular application on each supported
|
|||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<tr style="vertical-align: top">
|
<tr style="vertical-align: top">
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
Safari 7 & 8, IE10 & 11, Android 4.1+
|
Safari 7 & 8, IE10 & 11, Android 4.1+
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
[ES6](guide/browser-support#core-es6)
|
[ES6](guide/browser-support#core-es6)
|
||||||
</td>
|
</td>
|
||||||
@ -324,13 +381,16 @@ These are the polyfills required to run an Angular application on each supported
|
|||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<tr style="vertical-align: top">
|
<tr style="vertical-align: top">
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
IE9
|
IE9
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
[ES6<br>classList](guide/browser-support#classlist)
|
[ES6<br>classList](guide/browser-support#classlist)
|
||||||
|
|
||||||
@ -350,20 +410,25 @@ You'll need a polyfill to use animations in other browsers.
|
|||||||
|
|
||||||
Here are the features which may require additional polyfills:
|
Here are the features which may require additional polyfills:
|
||||||
|
|
||||||
|
|
||||||
<table>
|
<table>
|
||||||
|
|
||||||
|
|
||||||
<tr style="vertical-align: top">
|
<tr style="vertical-align: top">
|
||||||
|
|
||||||
|
|
||||||
<th>
|
<th>
|
||||||
Feature
|
Feature
|
||||||
</th>
|
</th>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<th>
|
<th>
|
||||||
Polyfill
|
Polyfill
|
||||||
</th>
|
</th>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<th style="width: 50%">
|
<th style="width: 50%">
|
||||||
Browsers (desktop & mobile)
|
Browsers (desktop & mobile)
|
||||||
</th>
|
</th>
|
||||||
@ -372,18 +437,22 @@ Here are the features which may require additional polyfills:
|
|||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<tr style="vertical-align: top">
|
<tr style="vertical-align: top">
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
<a href="./animations.html"> Animations </a>
|
<a href="./animations.html"> Animations </a>
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
[Web Animations](guide/browser-support#web-animations)
|
[Web Animations](guide/browser-support#web-animations)
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
All but Chrome and Firefox<br>Not supported in IE9
|
All but Chrome and Firefox<br>Not supported in IE9
|
||||||
</td>
|
</td>
|
||||||
@ -392,18 +461,22 @@ Here are the features which may require additional polyfills:
|
|||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<tr style="vertical-align: top">
|
<tr style="vertical-align: top">
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
<a href="../api/common/index/DatePipe-pipe.html" target="_blank"> Date </a> <span> , </span> <a href="../api/common/index/CurrencyPipe-pipe.html" target="_blank"> currency </a> <span> , </span> <a href="../api/common/index/DecimalPipe-pipe.html" target="_blank"> decimal </a> <span> and </span> <a href="../api/common/index/PercentPipe-pipe.html" target="_blank"> percent </a> <span> pipes </span>
|
<a href="../api/common/index/DatePipe-pipe.html" target="_blank"> Date </a> <span> , </span> <a href="../api/common/index/CurrencyPipe-pipe.html" target="_blank"> currency </a> <span> , </span> <a href="../api/common/index/DecimalPipe-pipe.html" target="_blank"> decimal </a> <span> and </span> <a href="../api/common/index/PercentPipe-pipe.html" target="_blank"> percent </a> <span> pipes </span>
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
[Intl API](guide/browser-support#intl)
|
[Intl API](guide/browser-support#intl)
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
All but Chrome, Firefox, Edge, IE11 and Safari 10
|
All but Chrome, Firefox, Edge, IE11 and Safari 10
|
||||||
</td>
|
</td>
|
||||||
@ -412,18 +485,22 @@ Here are the features which may require additional polyfills:
|
|||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<tr style="vertical-align: top">
|
<tr style="vertical-align: top">
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
<a href="../api/common/index/NgClass-directive.html" target="_blank"> NgClass </a> <span> on SVG elements </span>
|
<a href="../api/common/index/NgClass-directive.html" target="_blank"> NgClass </a> <span> on SVG elements </span>
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
[classList](guide/browser-support#classlist)
|
[classList](guide/browser-support#classlist)
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
IE10, IE11
|
IE10, IE11
|
||||||
</td>
|
</td>
|
||||||
@ -432,18 +509,22 @@ Here are the features which may require additional polyfills:
|
|||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<tr style="vertical-align: top">
|
<tr style="vertical-align: top">
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
<a href="./server-communication.html"> Http </a> <span> when sending and receiving binary data </span>
|
<a href="./server-communication.html"> Http </a> <span> when sending and receiving binary data </span>
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
[Typed Array](guide/browser-support#typedarray) <br>[Blob](guide/browser-support#blob)<br>[FormData](guide/browser-support#formdata)
|
[Typed Array](guide/browser-support#typedarray) <br>[Blob](guide/browser-support#blob)<br>[FormData](guide/browser-support#formdata)
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
IE 9
|
IE 9
|
||||||
</td>
|
</td>
|
||||||
@ -457,20 +538,25 @@ Here are the features which may require additional polyfills:
|
|||||||
### Suggested polyfills ##
|
### Suggested polyfills ##
|
||||||
Below are the polyfills which are used to test the framework itself. They are a good starting point for an application.
|
Below are the polyfills which are used to test the framework itself. They are a good starting point for an application.
|
||||||
|
|
||||||
|
|
||||||
<table>
|
<table>
|
||||||
|
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
|
|
||||||
|
|
||||||
<th>
|
<th>
|
||||||
Polyfill
|
Polyfill
|
||||||
</th>
|
</th>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<th>
|
<th>
|
||||||
License
|
License
|
||||||
</th>
|
</th>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<th>
|
<th>
|
||||||
Size*
|
Size*
|
||||||
</th>
|
</th>
|
||||||
@ -479,18 +565,22 @@ Below are the polyfills which are used to test the framework itself. They are a
|
|||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
<a id='core-es6' href="https://github.com/zloirock/core-js" target="_blank"> ES6 </a>
|
<a id='core-es6' href="https://github.com/zloirock/core-js" target="_blank"> ES6 </a>
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
MIT
|
MIT
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
27.4KB
|
27.4KB
|
||||||
</td>
|
</td>
|
||||||
@ -499,18 +589,22 @@ Below are the polyfills which are used to test the framework itself. They are a
|
|||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
<a id='classlist' href="https://github.com/eligrey/classList.js" target="_blank"> classList </a>
|
<a id='classlist' href="https://github.com/eligrey/classList.js" target="_blank"> classList </a>
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
Public domain
|
Public domain
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
1KB
|
1KB
|
||||||
</td>
|
</td>
|
||||||
@ -519,18 +613,22 @@ Below are the polyfills which are used to test the framework itself. They are a
|
|||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
<a id='intl' href="https://github.com/andyearnshaw/Intl.js" target="_blank"> Intl </a>
|
<a id='intl' href="https://github.com/andyearnshaw/Intl.js" target="_blank"> Intl </a>
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
MIT / Unicode license
|
MIT / Unicode license
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
13.5KB
|
13.5KB
|
||||||
</td>
|
</td>
|
||||||
@ -539,18 +637,22 @@ Below are the polyfills which are used to test the framework itself. They are a
|
|||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
<a id='web-animations' href="https://github.com/web-animations/web-animations-js" target="_blank"> Web Animations </a>
|
<a id='web-animations' href="https://github.com/web-animations/web-animations-js" target="_blank"> Web Animations </a>
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
Apache
|
Apache
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
14.8KB
|
14.8KB
|
||||||
</td>
|
</td>
|
||||||
@ -559,18 +661,22 @@ Below are the polyfills which are used to test the framework itself. They are a
|
|||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
<a id='typedarray' href="https://github.com/inexorabletash/polyfill/blob/master/typedarray.js" target="_blank"> Typed Array </a>
|
<a id='typedarray' href="https://github.com/inexorabletash/polyfill/blob/master/typedarray.js" target="_blank"> Typed Array </a>
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
MIT
|
MIT
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
4KB
|
4KB
|
||||||
</td>
|
</td>
|
||||||
@ -579,18 +685,22 @@ Below are the polyfills which are used to test the framework itself. They are a
|
|||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
<a id='blob' href="https://github.com/eligrey/Blob.js" target="_blank"> Blob </a>
|
<a id='blob' href="https://github.com/eligrey/Blob.js" target="_blank"> Blob </a>
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
MIT
|
MIT
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
1.3KB
|
1.3KB
|
||||||
</td>
|
</td>
|
||||||
@ -599,18 +709,22 @@ Below are the polyfills which are used to test the framework itself. They are a
|
|||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
<a id='formdata' href="https://github.com/francois2metz/html5-formdata" target="_blank"> FormData </a>
|
<a id='formdata' href="https://github.com/francois2metz/html5-formdata" target="_blank"> FormData </a>
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
MIT
|
MIT
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
0.4KB
|
0.4KB
|
||||||
</td>
|
</td>
|
||||||
|
@ -55,6 +55,7 @@ In the following example, we import and register several services
|
|||||||
in the `@Component` metadata `providers` array.
|
in the `@Component` metadata `providers` array.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="cb-dependency-injection/src/app/app.component.ts" region="import-services" linenums="false">
|
<code-example path="cb-dependency-injection/src/app/app.component.ts" region="import-services" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -74,12 +75,14 @@ Learn more about providers [below](guide/cb-dependency-injection#providers).
|
|||||||
Now that we've registered these services,
|
Now that we've registered these services,
|
||||||
Angular can inject them into the constructor of *any* component or service, *anywhere* in the application.
|
Angular can inject them into the constructor of *any* component or service, *anywhere* in the application.
|
||||||
|
|
||||||
|
|
||||||
<code-example path="cb-dependency-injection/src/app/hero-bios.component.ts" region="ctor" linenums="false">
|
<code-example path="cb-dependency-injection/src/app/hero-bios.component.ts" region="ctor" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="cb-dependency-injection/src/app/user-context.service.ts" region="ctor" linenums="false">
|
<code-example path="cb-dependency-injection/src/app/user-context.service.ts" region="ctor" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -96,6 +99,7 @@ We see an example of the second case here, where we configure the Component Rout
|
|||||||
in the `providers` list of the `AppModule`.
|
in the `providers` list of the `AppModule`.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="cb-dependency-injection/src/app/app.module.ts" region="providers" linenums="false">
|
<code-example path="cb-dependency-injection/src/app/app.module.ts" region="providers" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -118,6 +122,7 @@ At each step, the consumer of dependencies simply declares what it requires in i
|
|||||||
|
|
||||||
For example, we inject both the `LoggerService` and the `UserContext` in the `AppComponent`.
|
For example, we inject both the `LoggerService` and the `UserContext` in the `AppComponent`.
|
||||||
|
|
||||||
|
|
||||||
<code-example path="cb-dependency-injection/src/app/app.component.ts" region="ctor" linenums="false">
|
<code-example path="cb-dependency-injection/src/app/app.component.ts" region="ctor" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -126,6 +131,7 @@ The `UserContext` in turn has dependencies on both the `LoggerService` (again) a
|
|||||||
a `UserService` that gathers information about a particular user.
|
a `UserService` that gathers information about a particular user.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="cb-dependency-injection/src/app/user-context.service.ts" region="injectables" linenums="false">
|
<code-example path="cb-dependency-injection/src/app/user-context.service.ts" region="injectables" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -140,6 +146,7 @@ The author simply declared what was needed in the constructor (`LoggerService` a
|
|||||||
|
|
||||||
Once all the dependencies are in place, the `AppComponent` displays the user information:
|
Once all the dependencies are in place, the `AppComponent` displays the user information:
|
||||||
|
|
||||||
|
|
||||||
<figure class='image-display'>
|
<figure class='image-display'>
|
||||||
<img src="assets/images/cookbooks/dependency-injection/logged-in-user.png" alt="Logged In User"> </img>
|
<img src="assets/images/cookbooks/dependency-injection/logged-in-user.png" alt="Logged In User"> </img>
|
||||||
</figure>
|
</figure>
|
||||||
@ -147,6 +154,7 @@ Once all the dependencies are in place, the `AppComponent` displays the user inf
|
|||||||
### *@Injectable()*
|
### *@Injectable()*
|
||||||
Notice the `@Injectable()`decorator on the `UserContextService` class.
|
Notice the `@Injectable()`decorator on the `UserContextService` class.
|
||||||
|
|
||||||
|
|
||||||
<code-example path="cb-dependency-injection/src/app/user-context.service.ts" region="injectable" linenums="false">
|
<code-example path="cb-dependency-injection/src/app/user-context.service.ts" region="injectable" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -203,6 +211,7 @@ We can limit the scope of an injected service to a *branch* of the application h
|
|||||||
by providing that service *at the sub-root component for that branch*.
|
by providing that service *at the sub-root component for that branch*.
|
||||||
Here we provide the `HeroService` to the `HeroesBaseComponent` by listing it in the `providers` array:
|
Here we provide the `HeroService` to the `HeroesBaseComponent` by listing it in the `providers` array:
|
||||||
|
|
||||||
|
|
||||||
<code-example path="cb-dependency-injection/src/app/sorted-heroes.component.ts" region="injection">
|
<code-example path="cb-dependency-injection/src/app/sorted-heroes.component.ts" region="injection">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -247,6 +256,7 @@ We call this *sandboxing* because each service and component instance has its ow
|
|||||||
<a id="hero-bios-component"></a>
|
<a id="hero-bios-component"></a>
|
||||||
Imagine a `HeroBiosComponent` that presents three instances of the `HeroBioComponent`.
|
Imagine a `HeroBiosComponent` that presents three instances of the `HeroBioComponent`.
|
||||||
|
|
||||||
|
|
||||||
<code-example path="cb-dependency-injection/src/app/hero-bios.component.ts" region="simple">
|
<code-example path="cb-dependency-injection/src/app/hero-bios.component.ts" region="simple">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -254,6 +264,7 @@ Imagine a `HeroBiosComponent` that presents three instances of the `HeroBioCompo
|
|||||||
Each `HeroBioComponent` can edit a single hero's biography.
|
Each `HeroBioComponent` can edit a single hero's biography.
|
||||||
A `HeroBioComponent` relies on a `HeroCacheService` to fetch, cache, and perform other persistence operations on that hero.
|
A `HeroBioComponent` relies on a `HeroCacheService` to fetch, cache, and perform other persistence operations on that hero.
|
||||||
|
|
||||||
|
|
||||||
<code-example path="cb-dependency-injection/src/app/hero-cache.service.ts" region="service">
|
<code-example path="cb-dependency-injection/src/app/hero-cache.service.ts" region="service">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -264,6 +275,7 @@ They'd be competing with each other to determine which hero to cache.
|
|||||||
Each `HeroBioComponent` gets its *own* `HeroCacheService` instance
|
Each `HeroBioComponent` gets its *own* `HeroCacheService` instance
|
||||||
by listing the `HeroCacheService` in its metadata `providers` array.
|
by listing the `HeroCacheService` in its metadata `providers` array.
|
||||||
|
|
||||||
|
|
||||||
<code-example path="cb-dependency-injection/src/app/hero-bio.component.ts" region="component">
|
<code-example path="cb-dependency-injection/src/app/hero-bio.component.ts" region="component">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -275,6 +287,7 @@ And the template displays this data-bound property.
|
|||||||
|
|
||||||
Find this example in <live-example name="cb-dependency-injection">live code</live-example>
|
Find this example in <live-example name="cb-dependency-injection">live code</live-example>
|
||||||
and confirm that the three `HeroBioComponent` instances have their own cached hero data.
|
and confirm that the three `HeroBioComponent` instances have their own cached hero data.
|
||||||
|
|
||||||
<figure class='image-display'>
|
<figure class='image-display'>
|
||||||
<img src="assets/images/cookbooks/dependency-injection/hero-bios.png" alt="Bios"> </img>
|
<img src="assets/images/cookbooks/dependency-injection/hero-bios.png" alt="Bios"> </img>
|
||||||
</figure>
|
</figure>
|
||||||
@ -309,12 +322,14 @@ We look at this second, more interesting case in our next example.
|
|||||||
### Demonstration
|
### Demonstration
|
||||||
The `HeroBiosAndContactsComponent` is a revision of the `HeroBiosComponent` that we looked at [above](guide/cb-dependency-injection#hero-bios-component).
|
The `HeroBiosAndContactsComponent` is a revision of the `HeroBiosComponent` that we looked at [above](guide/cb-dependency-injection#hero-bios-component).
|
||||||
|
|
||||||
|
|
||||||
<code-example path="cb-dependency-injection/src/app/hero-bios.component.ts" region="hero-bios-and-contacts">
|
<code-example path="cb-dependency-injection/src/app/hero-bios.component.ts" region="hero-bios-and-contacts">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
|
|
||||||
Focus on the template:
|
Focus on the template:
|
||||||
|
|
||||||
|
|
||||||
<code-example path="cb-dependency-injection/src/app/hero-bios.component.ts" region="template" linenums="false">
|
<code-example path="cb-dependency-injection/src/app/hero-bios.component.ts" region="template" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -323,23 +338,27 @@ We've inserted a `<hero-contact>` element between the `<hero-bio>` tags.
|
|||||||
Angular *projects* (*transcludes*) the corresponding `HeroContactComponent` into the `HeroBioComponent` view,
|
Angular *projects* (*transcludes*) the corresponding `HeroContactComponent` into the `HeroBioComponent` view,
|
||||||
placing it in the `<ng-content>` slot of the `HeroBioComponent` template:
|
placing it in the `<ng-content>` slot of the `HeroBioComponent` template:
|
||||||
|
|
||||||
|
|
||||||
<code-example path="cb-dependency-injection/src/app/hero-bio.component.ts" region="template" linenums="false">
|
<code-example path="cb-dependency-injection/src/app/hero-bio.component.ts" region="template" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
|
|
||||||
It looks like this, with the hero's telephone number from `HeroContactComponent` projected above the hero description:
|
It looks like this, with the hero's telephone number from `HeroContactComponent` projected above the hero description:
|
||||||
|
|
||||||
<figure class='image-display'>
|
<figure class='image-display'>
|
||||||
<img src="assets/images/cookbooks/dependency-injection/hero-bio-and-content.png" alt="bio and contact"> </img>
|
<img src="assets/images/cookbooks/dependency-injection/hero-bio-and-content.png" alt="bio and contact"> </img>
|
||||||
</figure>
|
</figure>
|
||||||
|
|
||||||
Here's the `HeroContactComponent` which demonstrates the qualifying decorators that we're talking about in this section:
|
Here's the `HeroContactComponent` which demonstrates the qualifying decorators that we're talking about in this section:
|
||||||
|
|
||||||
|
|
||||||
<code-example path="cb-dependency-injection/src/app/hero-contact.component.ts" region="component">
|
<code-example path="cb-dependency-injection/src/app/hero-contact.component.ts" region="component">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
|
|
||||||
Focus on the constructor parameters
|
Focus on the constructor parameters
|
||||||
|
|
||||||
|
|
||||||
<code-example path="cb-dependency-injection/src/app/hero-contact.component.ts" region="ctor-params" linenums="false">
|
<code-example path="cb-dependency-injection/src/app/hero-contact.component.ts" region="ctor-params" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -363,6 +382,7 @@ We'll come back to the `elementRef` property shortly.
|
|||||||
~~~
|
~~~
|
||||||
|
|
||||||
Here's the `HeroBiosAndContactsComponent` in action.
|
Here's the `HeroBiosAndContactsComponent` in action.
|
||||||
|
|
||||||
<figure class='image-display'>
|
<figure class='image-display'>
|
||||||
<img src="assets/images/cookbooks/dependency-injection/hero-bios-and-contacts.png" alt="Bios with contact into"> </img>
|
<img src="assets/images/cookbooks/dependency-injection/hero-bios-and-contacts.png" alt="Bios with contact into"> </img>
|
||||||
</figure>
|
</figure>
|
||||||
@ -370,6 +390,7 @@ Here's the `HeroBiosAndContactsComponent` in action.
|
|||||||
If we comment out the `@Host()` decorator, Angular now walks up the injector ancestor tree
|
If we comment out the `@Host()` decorator, Angular now walks up the injector ancestor tree
|
||||||
until it finds the logger at the `AppComponent` level. The logger logic kicks in and the hero display updates
|
until it finds the logger at the `AppComponent` level. The logger logic kicks in and the hero display updates
|
||||||
with the gratuitous "!!!", indicating that the logger was found.
|
with the gratuitous "!!!", indicating that the logger was found.
|
||||||
|
|
||||||
<figure class='image-display'>
|
<figure class='image-display'>
|
||||||
<img src="assets/images/cookbooks/dependency-injection/hero-bio-contact-no-host.png" alt="Without @Host"> </img>
|
<img src="assets/images/cookbooks/dependency-injection/hero-bio-contact-no-host.png" alt="Without @Host"> </img>
|
||||||
</figure>
|
</figure>
|
||||||
@ -387,6 +408,7 @@ require DOM access.
|
|||||||
To illustrate, we've written a simplified version of the `HighlightDirective` from
|
To illustrate, we've written a simplified version of the `HighlightDirective` from
|
||||||
the [Attribute Directives](guide/attribute-directives) chapter.
|
the [Attribute Directives](guide/attribute-directives) chapter.
|
||||||
|
|
||||||
|
|
||||||
<code-example path="cb-dependency-injection/src/app/highlight.directive.ts">
|
<code-example path="cb-dependency-injection/src/app/highlight.directive.ts">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -401,11 +423,13 @@ Its `nativeElement` property exposes the DOM element for the directive to manipu
|
|||||||
The sample code applies the directive's `myHighlight` attribute to two `<div>` tags,
|
The sample code applies the directive's `myHighlight` attribute to two `<div>` tags,
|
||||||
first without a value (yielding the default color) and then with an assigned color value.
|
first without a value (yielding the default color) and then with an assigned color value.
|
||||||
|
|
||||||
|
|
||||||
<code-example path="cb-dependency-injection/src/app/app.component.html" region="highlight" linenums="false">
|
<code-example path="cb-dependency-injection/src/app/app.component.html" region="highlight" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
|
|
||||||
The following image shows the effect of mousing over the `<hero-bios-and-contacts>` tag.
|
The following image shows the effect of mousing over the `<hero-bios-and-contacts>` tag.
|
||||||
|
|
||||||
<figure class='image-display'>
|
<figure class='image-display'>
|
||||||
<img src="assets/images/cookbooks/dependency-injection/highlight.png" alt="Highlighted bios"> </img>
|
<img src="assets/images/cookbooks/dependency-injection/highlight.png" alt="Highlighted bios"> </img>
|
||||||
</figure>
|
</figure>
|
||||||
@ -424,6 +448,7 @@ Angular passes this token to the injector and assigns the result to the paramete
|
|||||||
Here's a typical example:
|
Here's a typical example:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="cb-dependency-injection/src/app/hero-bios.component.ts" region="ctor" linenums="false">
|
<code-example path="cb-dependency-injection/src/app/hero-bios.component.ts" region="ctor" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -451,6 +476,7 @@ Angular initializes the injectors it creates with some providers it cares about.
|
|||||||
We have to register our _own_ application providers manually,
|
We have to register our _own_ application providers manually,
|
||||||
usually in the `providers` array of the `Component` or `Directive` metadata:
|
usually in the `providers` array of the `Component` or `Directive` metadata:
|
||||||
|
|
||||||
|
|
||||||
<code-example path="cb-dependency-injection/src/app/app.component.ts" region="providers">
|
<code-example path="cb-dependency-injection/src/app/app.component.ts" region="providers">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -460,6 +486,7 @@ usually in the `providers` array of the `Component` or `Directive` metadata:
|
|||||||
The simple class provider is the most typical by far.
|
The simple class provider is the most typical by far.
|
||||||
We mention the class in the `providers` array and we're done.
|
We mention the class in the `providers` array and we're done.
|
||||||
|
|
||||||
|
|
||||||
<code-example path="cb-dependency-injection/src/app/hero-bios.component.ts" region="class-provider" linenums="false">
|
<code-example path="cb-dependency-injection/src/app/hero-bios.component.ts" region="class-provider" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -470,12 +497,14 @@ We need other ways to deliver dependency values and that means we need other way
|
|||||||
|
|
||||||
The `HeroOfTheMonthComponent` example demonstrates many of the alternatives and why we need them.
|
The `HeroOfTheMonthComponent` example demonstrates many of the alternatives and why we need them.
|
||||||
|
|
||||||
|
|
||||||
<figure class='image-display'>
|
<figure class='image-display'>
|
||||||
<img src="assets/images/cookbooks/dependency-injection/hero-of-month.png" alt="Hero of the month" width="300px"> </img>
|
<img src="assets/images/cookbooks/dependency-injection/hero-of-month.png" alt="Hero of the month" width="300px"> </img>
|
||||||
</figure>
|
</figure>
|
||||||
|
|
||||||
It's visually simple: a few properties and the output of a logger. The code behind it gives us plenty to talk about.
|
It's visually simple: a few properties and the output of a logger. The code behind it gives us plenty to talk about.
|
||||||
|
|
||||||
|
|
||||||
<code-example path="cb-dependency-injection/src/app/hero-of-the-month.component.ts" region="hero-of-the-month">
|
<code-example path="cb-dependency-injection/src/app/hero-of-the-month.component.ts" region="hero-of-the-month">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -506,6 +535,7 @@ The `HeroOfTheMonthComponent` example has two *value providers*.
|
|||||||
The first provides an instance of the `Hero` class;
|
The first provides an instance of the `Hero` class;
|
||||||
the second specifies a literal string resource:
|
the second specifies a literal string resource:
|
||||||
|
|
||||||
|
|
||||||
<code-example path="cb-dependency-injection/src/app/hero-of-the-month.component.ts" region="use-value" linenums="false">
|
<code-example path="cb-dependency-injection/src/app/hero-of-the-month.component.ts" region="use-value" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -521,6 +551,7 @@ The value of a *value provider* must be defined *now*. We can't create the value
|
|||||||
Obviously the title string literal is immediately available.
|
Obviously the title string literal is immediately available.
|
||||||
The `someHero` variable in this example was set earlier in the file:
|
The `someHero` variable in this example was set earlier in the file:
|
||||||
|
|
||||||
|
|
||||||
<code-example path="cb-dependency-injection/src/app/hero-of-the-month.component.ts" region="some-hero">
|
<code-example path="cb-dependency-injection/src/app/hero-of-the-month.component.ts" region="some-hero">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -540,6 +571,7 @@ or fake the behavior of the real class in a test case.
|
|||||||
|
|
||||||
We see two examples in the `HeroOfTheMonthComponent`:
|
We see two examples in the `HeroOfTheMonthComponent`:
|
||||||
|
|
||||||
|
|
||||||
<code-example path="cb-dependency-injection/src/app/hero-of-the-month.component.ts" region="use-class" linenums="false">
|
<code-example path="cb-dependency-injection/src/app/hero-of-the-month.component.ts" region="use-class" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -561,6 +593,7 @@ Components outside the tree continue to receive the original `LoggerService` ins
|
|||||||
|
|
||||||
The `DateLoggerService` inherits from `LoggerService`; it appends the current date/time to each message:
|
The `DateLoggerService` inherits from `LoggerService`; it appends the current date/time to each message:
|
||||||
|
|
||||||
|
|
||||||
<code-example path="cb-dependency-injection/src/app/date-logger.service.ts" region="date-logger-service" linenums="false">
|
<code-example path="cb-dependency-injection/src/app/date-logger.service.ts" region="date-logger-service" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -575,6 +608,7 @@ The `useExisting` provider maps one token to another.
|
|||||||
In effect, the first token is an ***alias*** for the service associated with second token,
|
In effect, the first token is an ***alias*** for the service associated with second token,
|
||||||
creating ***two ways to access the same service object***.
|
creating ***two ways to access the same service object***.
|
||||||
|
|
||||||
|
|
||||||
<code-example path="cb-dependency-injection/src/app/hero-of-the-month.component.ts" region="use-existing">
|
<code-example path="cb-dependency-injection/src/app/hero-of-the-month.component.ts" region="use-existing">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -585,11 +619,13 @@ Imagine that the `LoggerService` had a large API (it's actually only three metho
|
|||||||
We want to shrink that API surface to just the two members exposed by the `MinimalLogger` [*class-interface*](guide/cb-dependency-injection#class-interface):
|
We want to shrink that API surface to just the two members exposed by the `MinimalLogger` [*class-interface*](guide/cb-dependency-injection#class-interface):
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="cb-dependency-injection/src/app/date-logger.service.ts" region="minimal-logger" linenums="false">
|
<code-example path="cb-dependency-injection/src/app/date-logger.service.ts" region="minimal-logger" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
|
|
||||||
The constructor's `logger` parameter is typed as `MinimalLogger` so only its two members are visible in TypeScript:
|
The constructor's `logger` parameter is typed as `MinimalLogger` so only its two members are visible in TypeScript:
|
||||||
|
|
||||||
<figure class='image-display'>
|
<figure class='image-display'>
|
||||||
<img src="assets/images/cookbooks/dependency-injection/minimal-logger-intellisense.png" alt="MinimalLogger restricted API"> </img>
|
<img src="assets/images/cookbooks/dependency-injection/minimal-logger-intellisense.png" alt="MinimalLogger restricted API"> </img>
|
||||||
</figure>
|
</figure>
|
||||||
@ -597,6 +633,7 @@ The constructor's `logger` parameter is typed as `MinimalLogger` so only its two
|
|||||||
Angular actually sets the `logger` parameter to the injector's full version of the `LoggerService`
|
Angular actually sets the `logger` parameter to the injector's full version of the `LoggerService`
|
||||||
which happens to be the `DateLoggerService` thanks to the override provider registered previously via `useClass`.
|
which happens to be the `DateLoggerService` thanks to the override provider registered previously via `useClass`.
|
||||||
The following image, which displays the logging date, confirms the point:
|
The following image, which displays the logging date, confirms the point:
|
||||||
|
|
||||||
<figure class='image-display'>
|
<figure class='image-display'>
|
||||||
<img src="assets/images/cookbooks/dependency-injection/date-logger-entry.png" alt="DateLoggerService entry" width="300px"> </img>
|
<img src="assets/images/cookbooks/dependency-injection/date-logger-entry.png" alt="DateLoggerService entry" width="300px"> </img>
|
||||||
</figure>
|
</figure>
|
||||||
@ -610,6 +647,7 @@ The following image, which displays the logging date, confirms the point:
|
|||||||
The `useFactory` provider creates a dependency object by calling a factory function
|
The `useFactory` provider creates a dependency object by calling a factory function
|
||||||
as seen in this example.
|
as seen in this example.
|
||||||
|
|
||||||
|
|
||||||
<code-example path="cb-dependency-injection/src/app/hero-of-the-month.component.ts" region="use-factory">
|
<code-example path="cb-dependency-injection/src/app/hero-of-the-month.component.ts" region="use-factory">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -628,6 +666,7 @@ The `runnersUpFactory` itself isn't the provider factory function.
|
|||||||
The true provider factory function is the function that `runnersUpFactory` returns.
|
The true provider factory function is the function that `runnersUpFactory` returns.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="cb-dependency-injection/src/app/runners-up.ts" region="factory-synopsis" linenums="false">
|
<code-example path="cb-dependency-injection/src/app/runners-up.ts" region="factory-synopsis" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -671,12 +710,14 @@ That's the subject of our next section.
|
|||||||
In the previous *Hero of the Month* example, we used the `MinimalLogger` class
|
In the previous *Hero of the Month* example, we used the `MinimalLogger` class
|
||||||
as the token for a provider of a `LoggerService`.
|
as the token for a provider of a `LoggerService`.
|
||||||
|
|
||||||
|
|
||||||
<code-example path="cb-dependency-injection/src/app/hero-of-the-month.component.ts" region="use-existing">
|
<code-example path="cb-dependency-injection/src/app/hero-of-the-month.component.ts" region="use-existing">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
|
|
||||||
The `MinimalLogger` is an abstract class.
|
The `MinimalLogger` is an abstract class.
|
||||||
|
|
||||||
|
|
||||||
<code-example path="cb-dependency-injection/src/app/date-logger.service.ts" region="minimal-logger" linenums="false">
|
<code-example path="cb-dependency-injection/src/app/date-logger.service.ts" region="minimal-logger" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -687,6 +728,7 @@ Instead, we use it like an interface.
|
|||||||
|
|
||||||
Look again at the declaration for `DateLoggerService`
|
Look again at the declaration for `DateLoggerService`
|
||||||
|
|
||||||
|
|
||||||
<code-example path="cb-dependency-injection/src/app/date-logger.service.ts" region="date-logger-service-signature" linenums="false">
|
<code-example path="cb-dependency-injection/src/app/date-logger.service.ts" region="date-logger-service-signature" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -719,6 +761,7 @@ Using a class as an interface gives us the characteristics of an interface in a
|
|||||||
The minimize memory cost, the class should have *no implementation*.
|
The minimize memory cost, the class should have *no implementation*.
|
||||||
The `MinimalLogger` transpiles to this unoptimized, pre-minified JavaScript:
|
The `MinimalLogger` transpiles to this unoptimized, pre-minified JavaScript:
|
||||||
|
|
||||||
|
|
||||||
<code-example path="cb-dependency-injection/src/app/date-logger.service.ts" region="minimal-logger-transpiled" linenums="false">
|
<code-example path="cb-dependency-injection/src/app/date-logger.service.ts" region="minimal-logger-transpiled" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -745,12 +788,14 @@ The `OpaqueToken` has these characteristics.
|
|||||||
We encountered them twice in the *Hero of the Month* example,
|
We encountered them twice in the *Hero of the Month* example,
|
||||||
in the *title* value provider and in the *runnersUp* factory provider.
|
in the *title* value provider and in the *runnersUp* factory provider.
|
||||||
|
|
||||||
|
|
||||||
<code-example path="cb-dependency-injection/src/app/hero-of-the-month.component.ts" region="provide-opaque-token" linenums="false">
|
<code-example path="cb-dependency-injection/src/app/hero-of-the-month.component.ts" region="provide-opaque-token" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
|
|
||||||
We created the `TITLE` token like this:
|
We created the `TITLE` token like this:
|
||||||
|
|
||||||
|
|
||||||
<code-example path="cb-dependency-injection/src/app/hero-of-the-month.component.ts" region="opaque-token" linenums="false">
|
<code-example path="cb-dependency-injection/src/app/hero-of-the-month.component.ts" region="opaque-token" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -768,6 +813,7 @@ and then pass them down to the base class through the constructor.
|
|||||||
In this contrived example, `SortedHeroesComponent` inherits from `HeroesBaseComponent`
|
In this contrived example, `SortedHeroesComponent` inherits from `HeroesBaseComponent`
|
||||||
to display a *sorted* list of heroes.
|
to display a *sorted* list of heroes.
|
||||||
|
|
||||||
|
|
||||||
<figure class='image-display'>
|
<figure class='image-display'>
|
||||||
<img src="assets/images/cookbooks/dependency-injection/sorted-heroes.png" alt="Sorted Heroes"> </img>
|
<img src="assets/images/cookbooks/dependency-injection/sorted-heroes.png" alt="Sorted Heroes"> </img>
|
||||||
</figure>
|
</figure>
|
||||||
@ -777,6 +823,7 @@ It demands its own instance of the `HeroService` to get heroes
|
|||||||
and displays them in the order they arrive from the database.
|
and displays them in the order they arrive from the database.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="cb-dependency-injection/src/app/sorted-heroes.component.ts" region="heroes-base">
|
<code-example path="cb-dependency-injection/src/app/sorted-heroes.component.ts" region="heroes-base">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -804,6 +851,7 @@ We must provide the `HeroService` again for *this* component,
|
|||||||
then pass it down to the base class inside the constructor.
|
then pass it down to the base class inside the constructor.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="cb-dependency-injection/src/app/sorted-heroes.component.ts" region="sorted-heroes">
|
<code-example path="cb-dependency-injection/src/app/sorted-heroes.component.ts" region="sorted-heroes">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -850,6 +898,7 @@ In the following example, the parent `AlexComponent` has several children includ
|
|||||||
{@a alex}
|
{@a alex}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="cb-dependency-injection/src/app/parent-finder.component.ts" region="alex-1" linenums="false">
|
<code-example path="cb-dependency-injection/src/app/parent-finder.component.ts" region="alex-1" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -857,6 +906,7 @@ In the following example, the parent `AlexComponent` has several children includ
|
|||||||
*Cathy* reports whether or not she has access to *Alex*
|
*Cathy* reports whether or not she has access to *Alex*
|
||||||
after injecting an `AlexComponent` into her constructor:
|
after injecting an `AlexComponent` into her constructor:
|
||||||
|
|
||||||
|
|
||||||
<code-example path="cb-dependency-injection/src/app/parent-finder.component.ts" region="cathy" linenums="false">
|
<code-example path="cb-dependency-injection/src/app/parent-finder.component.ts" region="cathy" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -894,12 +944,14 @@ We are asking *can a component inject its parent via the parent's base class*?
|
|||||||
The sample's `CraigComponent` explores this question. [Looking back](guide/cb-dependency-injection#alex)
|
The sample's `CraigComponent` explores this question. [Looking back](guide/cb-dependency-injection#alex)
|
||||||
we see that the `Alex` component *extends* (*inherits*) from a class named `Base`.
|
we see that the `Alex` component *extends* (*inherits*) from a class named `Base`.
|
||||||
|
|
||||||
|
|
||||||
<code-example path="cb-dependency-injection/src/app/parent-finder.component.ts" region="alex-class-signature" linenums="false">
|
<code-example path="cb-dependency-injection/src/app/parent-finder.component.ts" region="alex-class-signature" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
|
|
||||||
The `CraigComponent` tries to inject `Base` into its `alex` constructor parameter and reports if it succeeded.
|
The `CraigComponent` tries to inject `Base` into its `alex` constructor parameter and reports if it succeeded.
|
||||||
|
|
||||||
|
|
||||||
<code-example path="cb-dependency-injection/src/app/parent-finder.component.ts" region="craig" linenums="false">
|
<code-example path="cb-dependency-injection/src/app/parent-finder.component.ts" region="craig" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -926,6 +978,7 @@ and add that provider to the `providers` array of the `@Component` metadata for
|
|||||||
{@a alex-providers}
|
{@a alex-providers}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="cb-dependency-injection/src/app/parent-finder.component.ts" region="alex-providers" linenums="false">
|
<code-example path="cb-dependency-injection/src/app/parent-finder.component.ts" region="alex-providers" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -935,11 +988,13 @@ The [*forwardRef*](guide/cb-dependency-injection#forwardref) breaks the circular
|
|||||||
|
|
||||||
*Carol*, the third of *Alex*'s child components, injects the parent into its `parent` parameter, the same way we've done it before:
|
*Carol*, the third of *Alex*'s child components, injects the parent into its `parent` parameter, the same way we've done it before:
|
||||||
|
|
||||||
|
|
||||||
<code-example path="cb-dependency-injection/src/app/parent-finder.component.ts" region="carol-class" linenums="false">
|
<code-example path="cb-dependency-injection/src/app/parent-finder.component.ts" region="carol-class" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
|
|
||||||
Here's *Alex* and family in action:
|
Here's *Alex* and family in action:
|
||||||
|
|
||||||
<figure class='image-display'>
|
<figure class='image-display'>
|
||||||
<img src="assets/images/cookbooks/dependency-injection/alex.png" alt="Alex in action"> </img>
|
<img src="assets/images/cookbooks/dependency-injection/alex.png" alt="Alex in action"> </img>
|
||||||
</figure>
|
</figure>
|
||||||
@ -958,6 +1013,7 @@ That means he must both *inject* the `Parent` *class-interface* to get *Alice* a
|
|||||||
|
|
||||||
Here's *Barry*:
|
Here's *Barry*:
|
||||||
|
|
||||||
|
|
||||||
<code-example path="cb-dependency-injection/src/app/parent-finder.component.ts" region="barry" linenums="false">
|
<code-example path="cb-dependency-injection/src/app/parent-finder.component.ts" region="barry" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -967,13 +1023,16 @@ If we're going to keep writing [*alias providers*](guide/cb-dependency-injection
|
|||||||
|
|
||||||
For now, focus on *Barry*'s constructor:
|
For now, focus on *Barry*'s constructor:
|
||||||
|
|
||||||
|
|
||||||
<code-tabs>
|
<code-tabs>
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="Barry's constructor" path="cb-dependency-injection/src/app/parent-finder.component.ts" region="barry-ctor">
|
<code-pane title="Barry's constructor" path="cb-dependency-injection/src/app/parent-finder.component.ts" region="barry-ctor">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="Carol's constructor" path="cb-dependency-injection/src/app/parent-finder.component.ts" region="carol-ctor">
|
<code-pane title="Carol's constructor" path="cb-dependency-injection/src/app/parent-finder.component.ts" region="carol-ctor">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
@ -994,6 +1053,7 @@ which *is* what parent means.
|
|||||||
|
|
||||||
Here's *Alice*, *Barry* and family in action:
|
Here's *Alice*, *Barry* and family in action:
|
||||||
|
|
||||||
|
|
||||||
<figure class='image-display'>
|
<figure class='image-display'>
|
||||||
<img src="assets/images/cookbooks/dependency-injection/alice.png" alt="Alice in action"> </img>
|
<img src="assets/images/cookbooks/dependency-injection/alice.png" alt="Alice in action"> </img>
|
||||||
</figure>
|
</figure>
|
||||||
@ -1006,6 +1066,7 @@ We [learned earlier](guide/cb-dependency-injection#class-interface) that a *clas
|
|||||||
|
|
||||||
Our example defines a `Parent` *class-interface* .
|
Our example defines a `Parent` *class-interface* .
|
||||||
|
|
||||||
|
|
||||||
<code-example path="cb-dependency-injection/src/app/parent-finder.component.ts" region="parent" linenums="false">
|
<code-example path="cb-dependency-injection/src/app/parent-finder.component.ts" region="parent" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -1016,6 +1077,7 @@ Such a narrowing interface helps decouple the child component class from its par
|
|||||||
|
|
||||||
A component that could serve as a parent *should* implement the *class-interface* as the `AliceComponent` does:
|
A component that could serve as a parent *should* implement the *class-interface* as the `AliceComponent` does:
|
||||||
|
|
||||||
|
|
||||||
<code-example path="cb-dependency-injection/src/app/parent-finder.component.ts" region="alice-class-signature" linenums="false">
|
<code-example path="cb-dependency-injection/src/app/parent-finder.component.ts" region="alice-class-signature" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -1024,6 +1086,7 @@ Doing so adds clarity to the code. But it's not technically necessary.
|
|||||||
Although the `AlexComponent` has a `name` property (as required by its `Base` class)
|
Although the `AlexComponent` has a `name` property (as required by its `Base` class)
|
||||||
its class signature doesn't mention `Parent`:
|
its class signature doesn't mention `Parent`:
|
||||||
|
|
||||||
|
|
||||||
<code-example path="cb-dependency-injection/src/app/parent-finder.component.ts" region="alex-class-signature" linenums="false">
|
<code-example path="cb-dependency-injection/src/app/parent-finder.component.ts" region="alex-class-signature" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -1046,18 +1109,21 @@ It doesn't in this example *only* to demonstrate that the code will compile and
|
|||||||
Writing variations of the same parent *alias provider* gets old quickly,
|
Writing variations of the same parent *alias provider* gets old quickly,
|
||||||
especially this awful mouthful with a [*forwardRef*](guide/cb-dependency-injection#forwardref):
|
especially this awful mouthful with a [*forwardRef*](guide/cb-dependency-injection#forwardref):
|
||||||
|
|
||||||
|
|
||||||
<code-example path="cb-dependency-injection/src/app/parent-finder.component.ts" region="alex-providers" linenums="false">
|
<code-example path="cb-dependency-injection/src/app/parent-finder.component.ts" region="alex-providers" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
|
|
||||||
We can extract that logic into a helper function like this:
|
We can extract that logic into a helper function like this:
|
||||||
|
|
||||||
|
|
||||||
<code-example path="cb-dependency-injection/src/app/parent-finder.component.ts" region="provide-the-parent" linenums="false">
|
<code-example path="cb-dependency-injection/src/app/parent-finder.component.ts" region="provide-the-parent" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
|
|
||||||
Now we can add a simpler, more meaningful parent provider to our components:
|
Now we can add a simpler, more meaningful parent provider to our components:
|
||||||
|
|
||||||
|
|
||||||
<code-example path="cb-dependency-injection/src/app/parent-finder.component.ts" region="alice-providers" linenums="false">
|
<code-example path="cb-dependency-injection/src/app/parent-finder.component.ts" region="alice-providers" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -1067,12 +1133,14 @@ Our application might have a variety of parent types, each with its own *class-i
|
|||||||
|
|
||||||
Here's a revised version that defaults to `parent` but also accepts an optional second parameter for a different parent *class-interface*.
|
Here's a revised version that defaults to `parent` but also accepts an optional second parameter for a different parent *class-interface*.
|
||||||
|
|
||||||
|
|
||||||
<code-example path="cb-dependency-injection/src/app/parent-finder.component.ts" region="provide-parent" linenums="false">
|
<code-example path="cb-dependency-injection/src/app/parent-finder.component.ts" region="provide-parent" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
|
|
||||||
And here's how we could use it with a different parent type:
|
And here's how we could use it with a different parent type:
|
||||||
|
|
||||||
|
|
||||||
<code-example path="cb-dependency-injection/src/app/parent-finder.component.ts" region="beth-providers" linenums="false">
|
<code-example path="cb-dependency-injection/src/app/parent-finder.component.ts" region="beth-providers" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -1101,6 +1169,7 @@ appear *above* the class definition.
|
|||||||
|
|
||||||
We break the circularity with `forwardRef`:
|
We break the circularity with `forwardRef`:
|
||||||
|
|
||||||
|
|
||||||
<code-example path="cb-dependency-injection/src/app/parent-finder.component.ts" region="alex-providers" linenums="false">
|
<code-example path="cb-dependency-injection/src/app/parent-finder.component.ts" region="alex-providers" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
|
@ -23,6 +23,7 @@ in which two or more components share information.
|
|||||||
typically adorned with [@Input decorations](guide/template-syntax).
|
typically adorned with [@Input decorations](guide/template-syntax).
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="cb-component-communication/src/app/hero-child.component.ts">
|
<code-example path="cb-component-communication/src/app/hero-child.component.ts">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -34,12 +35,14 @@ binding its `master` string property to the child's `master` alias,
|
|||||||
and each iteration's `hero` instance to the child's `hero` property.
|
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 path="cb-component-communication/src/app/hero-parent.component.ts">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
|
|
||||||
The running application displays three heroes:
|
The running application displays three heroes:
|
||||||
|
|
||||||
|
|
||||||
<figure class='image-display'>
|
<figure class='image-display'>
|
||||||
<img src="assets/images/cookbooks/component-communication/parent-to-child.png" alt="Parent-to-child"> </img>
|
<img src="assets/images/cookbooks/component-communication/parent-to-child.png" alt="Parent-to-child"> </img>
|
||||||
</figure>
|
</figure>
|
||||||
@ -49,6 +52,7 @@ The running application displays three heroes:
|
|||||||
E2E test that all children were instantiated and displayed as expected:
|
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 path="cb-component-communication/e2e-spec.ts" region="parent-to-child">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -63,6 +67,7 @@ The setter of the `name` input property in the child `NameChildComponent`
|
|||||||
trims the whitespace from a name and replaces an empty value with default text.
|
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 path="cb-component-communication/src/app/name-child.component.ts">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -70,11 +75,13 @@ 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:
|
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 path="cb-component-communication/src/app/name-parent.component.ts">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<figure class='image-display'>
|
<figure class='image-display'>
|
||||||
<img src="assets/images/cookbooks/component-communication/setter.png" alt="Parent-to-child-setter"> </img>
|
<img src="assets/images/cookbooks/component-communication/setter.png" alt="Parent-to-child-setter"> </img>
|
||||||
</figure>
|
</figure>
|
||||||
@ -84,6 +91,7 @@ Here's the `NameParentComponent` demonstrating name variations including a name
|
|||||||
E2E tests of input property setter with empty and non-empty names:
|
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 path="cb-component-communication/e2e-spec.ts" region="parent-to-child-setter">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -105,6 +113,7 @@ Learn about `ngOnChanges()` in the [LifeCycle Hooks](guide/lifecycle-hooks) chap
|
|||||||
This `VersionChildComponent` detects changes to the `major` and `minor` input properties and composes a log message reporting these changes:
|
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 path="cb-component-communication/src/app/version-child.component.ts">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -112,12 +121,14 @@ 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.
|
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 path="cb-component-communication/src/app/version-parent.component.ts">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
|
|
||||||
Here's the output of a button-pushing sequence:
|
Here's the output of a button-pushing sequence:
|
||||||
|
|
||||||
|
|
||||||
<figure class='image-display'>
|
<figure class='image-display'>
|
||||||
<img src="assets/images/cookbooks/component-communication/parent-to-child-on-changes.gif" alt="Parent-to-child-onchanges"> </img>
|
<img src="assets/images/cookbooks/component-communication/parent-to-child-on-changes.gif" alt="Parent-to-child-onchanges"> </img>
|
||||||
</figure>
|
</figure>
|
||||||
@ -128,6 +139,7 @@ Test that ***both*** input properties are set initially and that button clicks t
|
|||||||
the expected `ngOnChanges` calls and values:
|
the expected `ngOnChanges` calls and values:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="cb-component-communication/e2e-spec.ts" region="parent-to-child-onchanges">
|
<code-example path="cb-component-communication/e2e-spec.ts" region="parent-to-child-onchanges">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -144,6 +156,7 @@ The child's `EventEmitter` property is an ***output property***,
|
|||||||
as seen in this `VoterComponent`:
|
as seen in this `VoterComponent`:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="cb-component-communication/src/app/voter.component.ts">
|
<code-example path="cb-component-communication/src/app/voter.component.ts">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -154,6 +167,7 @@ The parent `VoteTakerComponent` binds an event handler called `onVoted()` that r
|
|||||||
payload `$event` and updates a counter.
|
payload `$event` and updates a counter.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="cb-component-communication/src/app/votetaker.component.ts">
|
<code-example path="cb-component-communication/src/app/votetaker.component.ts">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -161,6 +175,7 @@ payload `$event` and updates a counter.
|
|||||||
The framework passes the event argument—represented by `$event`—to the handler method,
|
The framework passes the event argument—represented by `$event`—to the handler method,
|
||||||
and the method processes it:
|
and the method processes it:
|
||||||
|
|
||||||
|
|
||||||
<figure class='image-display'>
|
<figure class='image-display'>
|
||||||
<img src="assets/images/cookbooks/component-communication/child-to-parent.gif" alt="Child-to-parent"> </img>
|
<img src="assets/images/cookbooks/component-communication/child-to-parent.gif" alt="Child-to-parent"> </img>
|
||||||
</figure>
|
</figure>
|
||||||
@ -170,6 +185,7 @@ and the method processes it:
|
|||||||
Test that clicking the *Agree* and *Disagree* buttons update the appropriate counters:
|
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 path="cb-component-communication/e2e-spec.ts" region="child-to-parent">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -189,6 +205,7 @@ The following is a child `CountdownTimerComponent` that repeatedly counts down t
|
|||||||
It has `start` and `stop` methods that control the clock and it displays a
|
It has `start` and `stop` methods that control the clock and it displays a
|
||||||
countdown status message in its own template.
|
countdown status message in its own template.
|
||||||
|
|
||||||
|
|
||||||
<code-example path="cb-component-communication/src/app/countdown-timer.component.ts">
|
<code-example path="cb-component-communication/src/app/countdown-timer.component.ts">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -196,6 +213,7 @@ countdown status message in its own template.
|
|||||||
The `CountdownLocalVarParentComponent` that hosts the timer component is as follows:
|
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 path="cb-component-communication/src/app/countdown-parent.component.ts" region="lv">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -212,6 +230,7 @@ uses interpolation to display the child's `seconds` property.
|
|||||||
|
|
||||||
Here we see the parent and child working together.
|
Here we see the parent and child working together.
|
||||||
|
|
||||||
|
|
||||||
<figure class='image-display'>
|
<figure class='image-display'>
|
||||||
<img src="assets/images/cookbooks/component-communication/countdown-timer-anim.gif" alt="countdown timer"> </img>
|
<img src="assets/images/cookbooks/component-communication/countdown-timer-anim.gif" alt="countdown timer"> </img>
|
||||||
</figure>
|
</figure>
|
||||||
@ -226,6 +245,7 @@ match the seconds displayed in the child's status message.
|
|||||||
Test also that clicking the *Stop* button pauses the countdown timer:
|
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 path="cb-component-communication/e2e-spec.ts" region="countdown-timer-tests">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -258,6 +278,7 @@ is solely for the purpose of demonstration.
|
|||||||
|
|
||||||
Here is the parent, `CountdownViewChildParentComponent`:
|
Here is the parent, `CountdownViewChildParentComponent`:
|
||||||
|
|
||||||
|
|
||||||
<code-example path="cb-component-communication/src/app/countdown-parent.component.ts" region="vc">
|
<code-example path="cb-component-communication/src/app/countdown-parent.component.ts" region="vc">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -301,6 +322,7 @@ Components outside this component subtree have no access to the service or their
|
|||||||
This `MissionService` connects the `MissionControlComponent` to multiple `AstronautComponent` children.
|
This `MissionService` connects the `MissionControlComponent` to multiple `AstronautComponent` children.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="cb-component-communication/src/app/mission.service.ts">
|
<code-example path="cb-component-communication/src/app/mission.service.ts">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -309,6 +331,7 @@ The `MissionControlComponent` both provides the instance of the service that it
|
|||||||
(through the `providers` metadata array) and injects that instance into itself through its constructor:
|
(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 path="cb-component-communication/src/app/missioncontrol.component.ts">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -317,6 +340,7 @@ The `AstronautComponent` also injects the service in its constructor.
|
|||||||
Each `AstronautComponent` is a child of the `MissionControlComponent` and therefore receives its parent's service instance:
|
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 path="cb-component-communication/src/app/astronaut.component.ts">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -339,6 +363,7 @@ The *History* log demonstrates that messages travel in both directions between
|
|||||||
the parent `MissionControlComponent` and the `AstronautComponent` children,
|
the parent `MissionControlComponent` and the `AstronautComponent` children,
|
||||||
facilitated by the service:
|
facilitated by the service:
|
||||||
|
|
||||||
|
|
||||||
<figure class='image-display'>
|
<figure class='image-display'>
|
||||||
<img src="assets/images/cookbooks/component-communication/bidirectional-service.gif" alt="bidirectional-service"> </img>
|
<img src="assets/images/cookbooks/component-communication/bidirectional-service.gif" alt="bidirectional-service"> </img>
|
||||||
</figure>
|
</figure>
|
||||||
@ -349,6 +374,7 @@ Tests click buttons of both the parent `MissionControlComponent` and the `Astron
|
|||||||
and verify that the history meets expectations:
|
and verify that the history meets expectations:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="cb-component-communication/e2e-spec.ts" region="bidirectional-service">
|
<code-example path="cb-component-communication/e2e-spec.ts" region="bidirectional-service">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
|
@ -37,6 +37,7 @@ The `styles` property takes #{_an} #{_array} of strings that contain CSS code.
|
|||||||
Usually you give it one string, as in the following example:
|
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 path="component-styles/src/app/hero-app.component.ts" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -73,6 +74,7 @@ Use the `:host` pseudo-class selector to target styles in the element that *host
|
|||||||
targeting elements *inside* the component's template).
|
targeting elements *inside* the component's template).
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="component-styles/src/app/hero-details.component.css" region="host" linenums="false">
|
<code-example path="component-styles/src/app/hero-details.component.css" region="host" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -87,6 +89,7 @@ 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.
|
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 path="component-styles/src/app/hero-details.component.css" region="hostfunction" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -105,6 +108,7 @@ The following example applies a `background-color` style to all `<h2>` elements
|
|||||||
if some ancestor element has the CSS class `theme-light`.
|
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 path="component-styles/src/app/hero-details.component.css" region="hostcontext" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -120,6 +124,7 @@ children and content children of the component.
|
|||||||
The following example targets all `<h3>` elements, from the host element down
|
The following example targets all `<h3>` elements, from the host element down
|
||||||
through this component to all of its child elements in the DOM.
|
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 path="component-styles/src/app/hero-details.component.css" region="deep" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -155,6 +160,7 @@ You can add a `styles` #{_array} property to the `@Component` #{_decorator}.
|
|||||||
Each string in the #{_array} (usually just one string) defines the CSS.
|
Each string in the #{_array} (usually just one string) defines the CSS.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="component-styles/src/app/hero-app.component.ts">
|
<code-example path="component-styles/src/app/hero-app.component.ts">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -165,6 +171,7 @@ 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">
|
<code-example path="component-styles/src/app/hero-details.component.ts" region="styleurls">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -208,6 +215,7 @@ You can embed styles directly into the HTML template by putting them
|
|||||||
inside `<style>` tags.
|
inside `<style>` tags.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="component-styles/src/app/hero-controls.component.ts" region="inlinestyles">
|
<code-example path="component-styles/src/app/hero-controls.component.ts" region="inlinestyles">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -220,6 +228,7 @@ As with `styleUrls`, the link tag's `href` URL is relative to the
|
|||||||
application root, not the component file.
|
application root, not the component file.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="component-styles/src/app/hero-team.component.ts" region="stylelink">
|
<code-example path="component-styles/src/app/hero-team.component.ts" region="stylelink">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -233,6 +242,7 @@ on the [MDN](https://developer.mozilla.org) site.
|
|||||||
In this case, the URL is relative to the CSS file into which you're importing.
|
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 path="component-styles/src/app/hero-details.component.css" region="import">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -266,6 +276,7 @@ Choose from the following modes:
|
|||||||
To set the components encapsulation mode, use the `encapsulation` property in the component metadata:
|
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 path="component-styles/src/app/quest-summary.component.ts" region="encapsulation.native" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -288,6 +299,7 @@ In the DOM of a running Angular application with emulated view
|
|||||||
encapsulation enabled, each DOM element has some extra attributes
|
encapsulation enabled, each DOM element has some extra attributes
|
||||||
attached to it:
|
attached to it:
|
||||||
|
|
||||||
|
|
||||||
<code-example format="">
|
<code-example format="">
|
||||||
<hero-details _nghost-pmm-5>
|
<hero-details _nghost-pmm-5>
|
||||||
<h2 _ngcontent-pmm-5>Mister Fantastic</h2>
|
<h2 _ngcontent-pmm-5>Mister Fantastic</h2>
|
||||||
@ -308,6 +320,7 @@ The exact values of these attributes aren't important. They are automatically
|
|||||||
generated and you never refer to them in application code. But they are targeted
|
generated and you never refer to them in application code. But they are targeted
|
||||||
by the generated component styles, which are in the `<head>` section of the DOM:
|
by the generated component styles, which are in the `<head>` section of the DOM:
|
||||||
|
|
||||||
|
|
||||||
<code-example format="">
|
<code-example format="">
|
||||||
[_nghost-pmm-5] {
|
[_nghost-pmm-5] {
|
||||||
display: block;
|
display: block;
|
||||||
@ -331,6 +344,7 @@ These extra selectors enable the scoping rules described in this page.
|
|||||||
## Appendix 2: Loading styles with relative URLs
|
## Appendix 2: Loading styles with relative URLs
|
||||||
|
|
||||||
It's common practice to split a component's code, HTML, and CSS into three separate files in the same directory:
|
It's common practice to split a component's code, HTML, and CSS into three separate files in the same directory:
|
||||||
|
|
||||||
<code-example format="nocode">
|
<code-example format="nocode">
|
||||||
quest-summary.component.ts
|
quest-summary.component.ts
|
||||||
quest-summary.component.html
|
quest-summary.component.html
|
||||||
@ -345,6 +359,7 @@ it would be nice to refer to them by name without also having to specify a path
|
|||||||
You can use a relative URL by prefixing your filenames with `./`:
|
You can use a relative URL by prefixing your filenames with `./`:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="component-styles/src/app/quest-summary.component.ts">
|
<code-example path="component-styles/src/app/quest-summary.component.ts">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
|
@ -48,6 +48,7 @@ To understand why dependency injection is so important, consider an example with
|
|||||||
Imagine writing the following code:
|
Imagine writing the following code:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="dependency-injection/src/app/car/car-no-di.ts" region="car">
|
<code-example path="dependency-injection/src/app/car/car-no-di.ts" region="car">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -98,13 +99,16 @@ How can you make `Car` more robust, flexible, and testable?
|
|||||||
That's super easy. Change the `Car` constructor to a version with DI:
|
That's super easy. Change the `Car` constructor to a version with DI:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-tabs>
|
<code-tabs>
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="src/app/car/car.ts (excerpt with DI)" path="dependency-injection/src/app/car/car.ts" region="car-ctor">
|
<code-pane title="src/app/car/car.ts (excerpt with DI)" path="dependency-injection/src/app/car/car.ts" region="car-ctor">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="src/app/car/car.ts (excerpt without DI)" path="dependency-injection/src/app/car/car-no-di.ts" region="car-ctor">
|
<code-pane title="src/app/car/car.ts (excerpt without DI)" path="dependency-injection/src/app/car/car-no-di.ts" region="car-ctor">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
@ -130,6 +134,7 @@ parameters and properties simultaneously.
|
|||||||
Now you can create a car by passing the engine and tires to the constructor.
|
Now you can create a car by passing the engine and tires to the constructor.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="dependency-injection/src/app/car/car-creations.ts" region="car-ctor-instantiation" linenums="false">
|
<code-example path="dependency-injection/src/app/car/car-creations.ts" region="car-ctor-instantiation" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -149,6 +154,7 @@ The _consumer_ of `Car` has the problem. The consumer must update the car creati
|
|||||||
something like this:
|
something like this:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="dependency-injection/src/app/car/car-creations.ts" region="car-ctor-instantiation-with-param" linenums="false">
|
<code-example path="dependency-injection/src/app/car/car-creations.ts" region="car-ctor-instantiation-with-param" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -165,6 +171,7 @@ You can pass mocks to the constructor that do exactly what you want them to do
|
|||||||
during each test:
|
during each test:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="dependency-injection/src/app/car/car-creations.ts" region="car-ctor-instantiation-with-mocks" linenums="false">
|
<code-example path="dependency-injection/src/app/car/car-creations.ts" region="car-ctor-instantiation-with-mocks" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -183,6 +190,7 @@ You need something that takes care of assembling these parts.
|
|||||||
You _could_ write a giant class to do that:
|
You _could_ write a giant class to do that:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="dependency-injection/src/app/car/car-factory.ts">
|
<code-example path="dependency-injection/src/app/car/car-factory.ts">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -202,6 +210,7 @@ You register some classes with this injector, and it figures out how to create t
|
|||||||
When you need a `Car`, you simply ask the injector to get it for you and you're good to go.
|
When you need a `Car`, you simply ask the injector to get it for you and you're good to go.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="dependency-injection/src/app/car/car-injector.ts" region="injector-call" linenums="false">
|
<code-example path="dependency-injection/src/app/car/car-injector.ts" region="injector-call" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -226,23 +235,28 @@ start with a simplified version of the `HeroesComponent`
|
|||||||
that from the [The Tour of Heroes](tutorial/).
|
that from the [The Tour of Heroes](tutorial/).
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-tabs>
|
<code-tabs>
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="src/app/heroes/heroes.component.ts" path="dependency-injection/src/app/heroes/heroes.component.1.ts" region="v1">
|
<code-pane title="src/app/heroes/heroes.component.ts" path="dependency-injection/src/app/heroes/heroes.component.1.ts" region="v1">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="src/app/heroes/hero-list.component.ts" path="dependency-injection/src/app/heroes/hero-list.component.1.ts">
|
<code-pane title="src/app/heroes/hero-list.component.ts" path="dependency-injection/src/app/heroes/hero-list.component.1.ts">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="src/app/heroes/hero.ts" path="dependency-injection/src/app/heroes/hero.ts">
|
<code-pane title="src/app/heroes/hero.ts" path="dependency-injection/src/app/heroes/hero.ts">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="src/app/heroes/mock-heroes.ts" path="dependency-injection/src/app/heroes/mock-heroes.ts">
|
<code-pane title="src/app/heroes/mock-heroes.ts" path="dependency-injection/src/app/heroes/mock-heroes.ts">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
@ -276,6 +290,7 @@ The following `HeroService` exposes a `getHeroes` method that returns
|
|||||||
the same mock data as before, but none of its consumers need to know that.
|
the same mock data as before, but none of its consumers need to know that.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="dependency-injection/src/app/heroes/hero.service.1.ts">
|
<code-example path="dependency-injection/src/app/heroes/hero.service.1.ts">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -306,6 +321,7 @@ This is important in general, but not in this example.
|
|||||||
A service is nothing more than a class in Angular.
|
A service is nothing more than a class in Angular.
|
||||||
It remains nothing more than a class until you register it with an Angular injector.
|
It remains nothing more than a class until you register it with an Angular injector.
|
||||||
|
|
||||||
|
|
||||||
<div id='bootstrap'>
|
<div id='bootstrap'>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
@ -319,6 +335,7 @@ You don't have to create an Angular injector.
|
|||||||
Angular creates an application-wide injector for you during the bootstrap process.
|
Angular creates an application-wide injector for you during the bootstrap process.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="dependency-injection/src/main.ts" linenums="false" title="src/main.ts (bootstrap)" region="bootstrap">
|
<code-example path="dependency-injection/src/main.ts" linenums="false" title="src/main.ts (bootstrap)" region="bootstrap">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -336,6 +353,7 @@ Here's the `AppModule` that registers two providers, `UserService` and an `APP_C
|
|||||||
in its `providers` !{_array}.
|
in its `providers` !{_array}.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="dependency-injection/app_module_ts + ' (excerpt)'" linenums="false" title="app_module_ts + ' (excerpt)' (ngmodule)" region="ngmodule">
|
<code-example path="dependency-injection/app_module_ts + ' (excerpt)'" linenums="false" title="app_module_ts + ' (excerpt)' (ngmodule)" region="ngmodule">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -351,6 +369,7 @@ place to register it.
|
|||||||
Here's a revised `HeroesComponent` that registers the `HeroService` in its `providers` !{_array}.
|
Here's a revised `HeroesComponent` that registers the `HeroService` in its `providers` !{_array}.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="dependency-injection/src/app/heroes/heroes.component.1.ts" region="full" linenums="false">
|
<code-example path="dependency-injection/src/app/heroes/heroes.component.1.ts" region="full" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -393,13 +412,16 @@ constructor, [as discussed earlier](guide/dependency-injection#ctor-injection).
|
|||||||
It's a small change:
|
It's a small change:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-tabs>
|
<code-tabs>
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="src/app/heroes/hero-list.component (with DI)" path="dependency-injection/src/app/heroes/hero-list.component.2.ts">
|
<code-pane title="src/app/heroes/hero-list.component (with DI)" path="dependency-injection/src/app/heroes/hero-list.component.2.ts">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="src/app/heroes/hero-list.component (without DI)" path="dependency-injection/src/app/heroes/hero-list.component.1.ts">
|
<code-pane title="src/app/heroes/hero-list.component (without DI)" path="dependency-injection/src/app/heroes/hero-list.component.1.ts">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
@ -416,6 +438,7 @@ It's a small change:
|
|||||||
Adding a parameter to the constructor isn't all that's happening here.
|
Adding a parameter to the constructor isn't all that's happening here.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="dependency-injection/src/app/heroes/hero-list.component.2.ts" region="ctor" linenums="false">
|
<code-example path="dependency-injection/src/app/heroes/hero-list.component.2.ts" region="ctor" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -445,6 +468,7 @@ You _could_ create such an injector
|
|||||||
explicitly:
|
explicitly:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="dependency-injection/src/app/car/car-injector.ts" region="injector-create-and-call" linenums="false">
|
<code-example path="dependency-injection/src/app/car/car-injector.ts" region="injector-create-and-call" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -481,6 +505,7 @@ For example, you can create a new `HeroListComponent` with a mock service that y
|
|||||||
under test:
|
under test:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="dependency-injection/src/app/test.component.ts" region="spec" linenums="false">
|
<code-example path="dependency-injection/src/app/test.component.ts" region="spec" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -509,13 +534,16 @@ adding a constructor that takes a `Logger` parameter.
|
|||||||
Here is the revision compared to the original.
|
Here is the revision compared to the original.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-tabs>
|
<code-tabs>
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="src/app/heroes/hero.service (v2)" path="dependency-injection/src/app/heroes/hero.service.2.ts">
|
<code-pane title="src/app/heroes/hero.service (v2)" path="dependency-injection/src/app/heroes/hero.service.2.ts">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="src/app/heroes/hero.service (v1)" path="dependency-injection/src/app/heroes/hero.service.1.ts">
|
<code-pane title="src/app/heroes/hero.service (v1)" path="dependency-injection/src/app/heroes/hero.service.1.ts">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
@ -553,6 +581,7 @@ in order to inject a `Logger`.
|
|||||||
~~~ {.callout.is-helpful}
|
~~~ {.callout.is-helpful}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<header>
|
<header>
|
||||||
Suggestion: add @Injectable() to every service class
|
Suggestion: add @Injectable() to every service class
|
||||||
</header>
|
</header>
|
||||||
@ -560,13 +589,16 @@ in order to inject a `Logger`.
|
|||||||
Consider adding `@Injectable()` to every service class, even those that don't have dependencies
|
Consider adding `@Injectable()` to every service class, even those that don't have dependencies
|
||||||
and, therefore, do not technically require it. Here's why:
|
and, therefore, do not technically require it. Here's why:
|
||||||
|
|
||||||
|
|
||||||
<ul style="font-size:inherit">
|
<ul style="font-size:inherit">
|
||||||
|
|
||||||
|
|
||||||
<li>
|
<li>
|
||||||
<b>Future proofing:</b> No need to remember <code>@Injectable()</code> when you add a dependency later.
|
<b>Future proofing:</b> No need to remember <code>@Injectable()</code> when you add a dependency later.
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<li>
|
<li>
|
||||||
<b>Consistency:</b> All services follow the same rules, and you don't have to wonder why is missing.
|
<b>Consistency:</b> All services follow the same rules, and you don't have to wonder why is missing.
|
||||||
</li>
|
</li>
|
||||||
@ -593,6 +625,7 @@ identify a class as a target for instantiation by an injector.
|
|||||||
~~~ {.callout.is-critical}
|
~~~ {.callout.is-critical}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<header>
|
<header>
|
||||||
Always include the parentheses
|
Always include the parentheses
|
||||||
</header>
|
</header>
|
||||||
@ -614,6 +647,7 @@ Inject a logger into `HeroService` in two steps:
|
|||||||
The logger service is quite simple:
|
The logger service is quite simple:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="dependency-injection/src/app/logger.service.ts">
|
<code-example path="dependency-injection/src/app/logger.service.ts">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -624,11 +658,13 @@ so put it in the project's `#{_appDir}` folder and
|
|||||||
register it in the `providers` #{_array} of the application !{_moduleVsComp}, `!{_AppModuleVsAppComp}`.
|
register it in the `providers` #{_array} of the application !{_moduleVsComp}, `!{_AppModuleVsAppComp}`.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="dependency-injection/src/app/providers.component.ts" linenums="false" title="src/app/providers.component.ts (excerpt)" region="providers-logger">
|
<code-example path="dependency-injection/src/app/providers.component.ts" linenums="false" title="src/app/providers.component.ts (excerpt)" region="providers-logger">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
|
|
||||||
If you forget to register the logger, Angular throws an exception when it first looks for the logger:
|
If you forget to register the logger, Angular throws an exception when it first looks for the logger:
|
||||||
|
|
||||||
<code-example format="nocode">
|
<code-example format="nocode">
|
||||||
EXCEPTION: No provider for Logger! (HeroListComponent -> HeroService -> Logger)
|
EXCEPTION: No provider for Logger! (HeroListComponent -> HeroService -> Logger)
|
||||||
|
|
||||||
@ -652,6 +688,7 @@ You must register a service *provider* with the injector, or it won't know how t
|
|||||||
Earlier you registered the `Logger` service in the `providers` #{_array} of the metadata for the `AppModule` like this:
|
Earlier you registered the `Logger` service in the `providers` #{_array} of the metadata for the `AppModule` like this:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="dependency-injection/src/app/providers.component.ts" region="providers-logger">
|
<code-example path="dependency-injection/src/app/providers.component.ts" region="providers-logger">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -667,6 +704,7 @@ Any of these approaches might be a good choice under the right circumstances.
|
|||||||
|
|
||||||
What matters is that the injector has a provider to go to when it needs a `Logger`.
|
What matters is that the injector has a provider to go to when it needs a `Logger`.
|
||||||
|
|
||||||
|
|
||||||
<div id='provide'>
|
<div id='provide'>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
@ -675,6 +713,7 @@ What matters is that the injector has a provider to go to when it needs a `Logge
|
|||||||
You wrote the `providers` #{_array} like this:
|
You wrote the `providers` #{_array} like this:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="dependency-injection/src/app/providers.component.ts" region="providers-1">
|
<code-example path="dependency-injection/src/app/providers.component.ts" region="providers-1">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -684,6 +723,7 @@ This is actually a shorthand expression for a provider registration
|
|||||||
using a _provider_ object literal with two properties:
|
using a _provider_ object literal with two properties:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="dependency-injection/src/app/providers.component.ts" region="providers-3">
|
<code-example path="dependency-injection/src/app/providers.component.ts" region="providers-3">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -696,6 +736,7 @@ The second is a !{_secondParam},
|
|||||||
which you can think of as a *recipe* for creating the dependency value.
|
which you can think of as a *recipe* for creating the dependency value.
|
||||||
There are many ways to create dependency values just as there are many ways to write a recipe.
|
There are many ways to create dependency values just as there are many ways to write a recipe.
|
||||||
|
|
||||||
|
|
||||||
<div id='class-provider'>
|
<div id='class-provider'>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
@ -707,6 +748,7 @@ The following code tells the injector
|
|||||||
to return a `BetterLogger` when something asks for the `Logger`.
|
to return a `BetterLogger` when something asks for the `Logger`.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="dependency-injection/src/app/providers.component.ts" region="providers-4">
|
<code-example path="dependency-injection/src/app/providers.component.ts" region="providers-4">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -721,6 +763,7 @@ This logger gets the user from the injected `UserService`,
|
|||||||
which is also injected at the application level.
|
which is also injected at the application level.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="dependency-injection/src/app/providers.component.ts" region="EvenBetterLogger" linenums="false">
|
<code-example path="dependency-injection/src/app/providers.component.ts" region="EvenBetterLogger" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -728,6 +771,7 @@ which is also injected at the application level.
|
|||||||
Configure it like `BetterLogger`.
|
Configure it like `BetterLogger`.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="dependency-injection/src/app/providers.component.ts" region="providers-5" linenums="false">
|
<code-example path="dependency-injection/src/app/providers.component.ts" region="providers-5" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -752,6 +796,7 @@ You certainly do not want two different `NewLogger` instances in your app.
|
|||||||
Unfortunately, that's what you get if you try to alias `OldLogger` to `NewLogger` with `useClass`.
|
Unfortunately, that's what you get if you try to alias `OldLogger` to `NewLogger` with `useClass`.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="dependency-injection/src/app/providers.component.ts" region="providers-6a" linenums="false">
|
<code-example path="dependency-injection/src/app/providers.component.ts" region="providers-6a" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -759,6 +804,7 @@ Unfortunately, that's what you get if you try to alias `OldLogger` to `NewLogger
|
|||||||
The solution: alias with the `useExisting` option.
|
The solution: alias with the `useExisting` option.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="dependency-injection/src/app/providers.component.ts" region="providers-6b" linenums="false">
|
<code-example path="dependency-injection/src/app/providers.component.ts" region="providers-6b" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -771,6 +817,7 @@ Sometimes it's easier to provide a ready-made object rather than ask the injecto
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="dependency-injection/src/app/providers.component.ts" region="silent-logger" linenums="false">
|
<code-example path="dependency-injection/src/app/providers.component.ts" region="silent-logger" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -779,6 +826,7 @@ Then you register a provider with the `useValue` option,
|
|||||||
which makes this object play the logger role.
|
which makes this object play the logger role.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="dependency-injection/src/app/providers.component.ts" region="providers-7" linenums="false">
|
<code-example path="dependency-injection/src/app/providers.component.ts" region="providers-7" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -787,6 +835,7 @@ See more `useValue` examples in the
|
|||||||
[Non-class dependencies](guide/dependency-injection#non-class-dependencies) and
|
[Non-class dependencies](guide/dependency-injection#non-class-dependencies) and
|
||||||
[OpaqueToken](guide/dependency-injection#opaquetoken) sections.
|
[OpaqueToken](guide/dependency-injection#opaquetoken) sections.
|
||||||
|
|
||||||
|
|
||||||
<div id='factory-provider'>
|
<div id='factory-provider'>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
@ -816,6 +865,7 @@ who is authorized and who is not.
|
|||||||
Instead, the `HeroService` constructor takes a boolean flag to control display of secret heroes.
|
Instead, the `HeroService` constructor takes a boolean flag to control display of secret heroes.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="dependency-injection/src/app/heroes/hero.service.ts" region="internals" linenums="false">
|
<code-example path="dependency-injection/src/app/heroes/hero.service.ts" region="internals" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -826,6 +876,7 @@ You'll have to take over the creation of new instances of this `HeroService` wit
|
|||||||
A factory provider needs a factory function:
|
A factory provider needs a factory function:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="dependency-injection/src/app/heroes/hero.service.provider.ts" region="factory" linenums="false">
|
<code-example path="dependency-injection/src/app/heroes/hero.service.provider.ts" region="factory" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -836,6 +887,7 @@ You inject both the `Logger` and the `UserService` into the factory provider
|
|||||||
and let the injector pass them along to the factory function:
|
and let the injector pass them along to the factory function:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="dependency-injection/src/app/heroes/hero.service.provider.ts" region="provider" linenums="false">
|
<code-example path="dependency-injection/src/app/heroes/hero.service.provider.ts" region="provider" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -863,13 +915,16 @@ where it replaces the previous `HeroService` registration in the metadata `provi
|
|||||||
Here you see the new and the old implementation side-by-side:
|
Here you see the new and the old implementation side-by-side:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-tabs>
|
<code-tabs>
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="src/app/heroes/heroes.component (v3)" path="dependency-injection/src/app/heroes/heroes.component.ts">
|
<code-pane title="src/app/heroes/heroes.component (v3)" path="dependency-injection/src/app/heroes/heroes.component.ts">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="src/app/heroes/heroes.component (v2)" path="dependency-injection/src/app/heroes/heroes.component.1.ts" region="full">
|
<code-pane title="src/app/heroes/heroes.component (v2)" path="dependency-injection/src/app/heroes/heroes.component.1.ts" region="full">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
@ -889,6 +944,7 @@ the class *type* served as its own lookup key.
|
|||||||
Here you get a `HeroService` directly from the injector by supplying the `HeroService` type as the token:
|
Here you get a `HeroService` directly from the injector by supplying the `HeroService` type as the token:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="dependency-injection/src/app/injector.component.ts" region="get-hero-service" linenums="false">
|
<code-example path="dependency-injection/src/app/injector.component.ts" region="get-hero-service" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -899,6 +955,7 @@ Angular knows to inject the
|
|||||||
service associated with that `HeroService` class token:
|
service associated with that `HeroService` class token:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="dependency-injection/src/app/heroes/hero-list.component.ts" region="ctor-signature">
|
<code-example path="dependency-injection/src/app/heroes/hero-list.component.ts" region="ctor-signature">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -908,12 +965,14 @@ This is especially convenient when you consider that most dependency values are
|
|||||||
|
|
||||||
{@a non-class-dependencies}
|
{@a non-class-dependencies}
|
||||||
### Non-class dependencies
|
### Non-class dependencies
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
What if the dependency value isn't a class? Sometimes the thing you want to inject is a
|
What if the dependency value isn't a class? Sometimes the thing you want to inject is a
|
||||||
span string, function, or object.
|
span string, function, or object.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
Applications often define configuration objects with lots of small facts
|
Applications often define configuration objects with lots of small facts
|
||||||
(like the title of the application or the address of a web API endpoint)
|
(like the title of the application or the address of a web API endpoint)
|
||||||
@ -923,6 +982,7 @@ This is especially convenient when you consider that most dependency values are
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="dependency-injection/src/app/app.config.ts" region="config" linenums="false">
|
<code-example path="dependency-injection/src/app/app.config.ts" region="config" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -942,12 +1002,14 @@ There is no `AppConfig` class.
|
|||||||
The `HERO_DI_CONFIG` constant has an interface, `AppConfig`. Unfortunately, you
|
The `HERO_DI_CONFIG` constant has an interface, `AppConfig`. Unfortunately, you
|
||||||
cannot use a TypeScript interface as a token:
|
cannot use a TypeScript interface as a token:
|
||||||
|
|
||||||
|
|
||||||
<code-example path="dependency-injection/src/app/providers.component.ts" region="providers-9-interface" linenums="false">
|
<code-example path="dependency-injection/src/app/providers.component.ts" region="providers-9-interface" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="dependency-injection/src/app/providers.component.ts" region="provider-9-ctor-interface" linenums="false">
|
<code-example path="dependency-injection/src/app/providers.component.ts" region="provider-9-ctor-interface" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -972,6 +1034,7 @@ to define and use an !{opaquetoken}.
|
|||||||
The definition looks like this:
|
The definition looks like this:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="dependency-injection/src/app/app.config.ts" region="token" linenums="false">
|
<code-example path="dependency-injection/src/app/app.config.ts" region="token" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -979,6 +1042,7 @@ The definition looks like this:
|
|||||||
Register the dependency provider using the `OpaqueToken` object:
|
Register the dependency provider using the `OpaqueToken` object:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="dependency-injection/src/app/providers.component.ts" region="providers-9" linenums="false">
|
<code-example path="dependency-injection/src/app/providers.component.ts" region="providers-9" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -987,6 +1051,7 @@ Now you can inject the configuration object into any constructor that needs it,
|
|||||||
the help of an `@Inject` #{_decorator}:
|
the help of an `@Inject` #{_decorator}:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="dependency-injection/src/app/app.component.2.ts" region="ctor" linenums="false">
|
<code-example path="dependency-injection/src/app/app.component.2.ts" region="ctor" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -1005,11 +1070,13 @@ it supports typing of the configuration object within the class.
|
|||||||
Aternatively, you can provide and inject the configuration object in an ngModule like `AppModule`.
|
Aternatively, you can provide and inject the configuration object in an ngModule like `AppModule`.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="dependency-injection/src/app/app.module.ts" linenums="false" title="src/app/app.module.ts (ngmodule-providers)" region="ngmodule-providers">
|
<code-example path="dependency-injection/src/app/app.module.ts" linenums="false" title="src/app/app.module.ts (ngmodule-providers)" region="ngmodule-providers">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<div id='optional'>
|
<div id='optional'>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
@ -1022,6 +1089,7 @@ You can tell Angular that the dependency is optional by annotating the
|
|||||||
constructor argument with `@Optional()`:
|
constructor argument with `@Optional()`:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="dependency-injection/src/app/providers.component.ts" region="provider-10-ctor" linenums="false">
|
<code-example path="dependency-injection/src/app/providers.component.ts" region="provider-10-ctor" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -1048,6 +1116,7 @@ Developers rarely work directly with an injector, but
|
|||||||
here's an `InjectorComponent` that does.
|
here's an `InjectorComponent` that does.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="dependency-injection/src/app/injector.component.ts" region="injector">
|
<code-example path="dependency-injection/src/app/injector.component.ts" region="injector">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
|
@ -108,6 +108,7 @@ Load the few files you need from the web instead.
|
|||||||
with versions that load from the web. It might look like this.
|
with versions that load from the web. It might look like this.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="deployment/src/index.html" region="node-module-scripts" linenums="false">
|
<code-example path="deployment/src/index.html" region="node-module-scripts" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -115,6 +116,7 @@ with versions that load from the web. It might look like this.
|
|||||||
(2) Replace the `systemjs.config.js` script with a script that
|
(2) Replace the `systemjs.config.js` script with a script that
|
||||||
loads `systemjs.config.server.js`.
|
loads `systemjs.config.server.js`.
|
||||||
|
|
||||||
|
|
||||||
<code-example path="deployment/src/index.html" region="systemjs-config" linenums="false">
|
<code-example path="deployment/src/index.html" region="systemjs-config" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -129,6 +131,7 @@ you make to `systemjs.config.js`.
|
|||||||
Notice the `paths` key:
|
Notice the `paths` key:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="deployment/src/systemjs.config.server.js" region="paths" linenums="false">
|
<code-example path="deployment/src/systemjs.config.server.js" region="paths" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -150,38 +153,46 @@ Then change the config's `'npm'` path to point to that folder.
|
|||||||
The following trivial router sample app shows these changes.
|
The following trivial router sample app shows these changes.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-tabs>
|
<code-tabs>
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="index.html" path="deployment/src/index.html">
|
<code-pane title="index.html" path="deployment/src/index.html">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="systemjs.config.server.js" path="deployment/src/systemjs.config.server.js">
|
<code-pane title="systemjs.config.server.js" path="deployment/src/systemjs.config.server.js">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="main.ts" path="deployment/src/main.ts">
|
<code-pane title="main.ts" path="deployment/src/main.ts">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="app/app.module.ts" path="deployment/src/app/app.module.ts">
|
<code-pane title="app/app.module.ts" path="deployment/src/app/app.module.ts">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="app/app.component.ts" path="deployment/src/app/app.component.ts">
|
<code-pane title="app/app.component.ts" path="deployment/src/app/app.component.ts">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="app/crisis-list.component.ts" path="deployment/src/app/crisis-list.component.ts">
|
<code-pane title="app/crisis-list.component.ts" path="deployment/src/app/crisis-list.component.ts">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="app/hero-list.component.ts" path="deployment/src/app/hero-list.component.ts">
|
<code-pane title="app/hero-list.component.ts" path="deployment/src/app/hero-list.component.ts">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
@ -369,6 +380,7 @@ for the missing files. Look at where it _tried_ to find those files and adjust t
|
|||||||
Angular apps run in development mode by default, as you can see by the following message on the browser
|
Angular apps run in development mode by default, as you can see by the following message on the browser
|
||||||
console:
|
console:
|
||||||
|
|
||||||
|
|
||||||
<code-example format="nocode">
|
<code-example format="nocode">
|
||||||
Angular 2 is running in the development mode. Call enableProdMode() to enable the production mode.
|
Angular 2 is running in the development mode. Call enableProdMode() to enable the production mode.
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -378,6 +390,7 @@ Switching to production mode can make it run faster by disabling development spe
|
|||||||
To enable [production mode](api/core/index/enableProdMode-function) when running remotely, add the following code to the `main.ts`.
|
To enable [production mode](api/core/index/enableProdMode-function) when running remotely, add the following code to the `main.ts`.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="deployment/src/main.ts" region="enableProdMode" linenums="false">
|
<code-example path="deployment/src/main.ts" region="enableProdMode" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -464,6 +477,7 @@ The list is by no means exhaustive, but should provide you with a good starting
|
|||||||
- [Webpack-Dev-Server](https://github.com/webpack/webpack-dev-server): setup the
|
- [Webpack-Dev-Server](https://github.com/webpack/webpack-dev-server): setup the
|
||||||
`historyApiFallback` entry in the dev server options as follows:
|
`historyApiFallback` entry in the dev server options as follows:
|
||||||
|
|
||||||
|
|
||||||
<code-example>
|
<code-example>
|
||||||
historyApiFallback: {
|
historyApiFallback: {
|
||||||
disableDotRule: true,
|
disableDotRule: true,
|
||||||
@ -478,6 +492,7 @@ The list is by no means exhaustive, but should provide you with a good starting
|
|||||||
[rewrite rule](http://httpd.apache.org/docs/current/mod/mod_rewrite.html)
|
[rewrite rule](http://httpd.apache.org/docs/current/mod/mod_rewrite.html)
|
||||||
to the `.htaccess` file as show
|
to the `.htaccess` file as show
|
||||||
[here](https://ngmilk.rocks/2015/03/09/angularjs-html5-mode-or-pretty-urls-on-apache-using-htaccess/):
|
[here](https://ngmilk.rocks/2015/03/09/angularjs-html5-mode-or-pretty-urls-on-apache-using-htaccess/):
|
||||||
|
|
||||||
<code-example format=".">
|
<code-example format=".">
|
||||||
RewriteEngine On
|
RewriteEngine On
|
||||||
# If an existing asset or directory is requested go to it as it is
|
# If an existing asset or directory is requested go to it as it is
|
||||||
@ -494,6 +509,7 @@ to the `.htaccess` file as show
|
|||||||
[Front Controller Pattern Web Apps](https://www.nginx.com/resources/wiki/start/topics/tutorials/config_pitfalls/#front-controller-pattern-web-apps),
|
[Front Controller Pattern Web Apps](https://www.nginx.com/resources/wiki/start/topics/tutorials/config_pitfalls/#front-controller-pattern-web-apps),
|
||||||
modified to serve `index.html`:
|
modified to serve `index.html`:
|
||||||
|
|
||||||
|
|
||||||
<code-example format=".">
|
<code-example format=".">
|
||||||
try_files $uri $uri/ /index.html;
|
try_files $uri $uri/ /index.html;
|
||||||
|
|
||||||
@ -501,6 +517,7 @@ modified to serve `index.html`:
|
|||||||
|
|
||||||
- [IIS](https://www.iis.net/): add a rewrite rule to `web.config`, similar to the one shown
|
- [IIS](https://www.iis.net/): add a rewrite rule to `web.config`, similar to the one shown
|
||||||
[here](http://stackoverflow.com/a/26152011/2116927):
|
[here](http://stackoverflow.com/a/26152011/2116927):
|
||||||
|
|
||||||
<code-example format="." escape="html">
|
<code-example format="." escape="html">
|
||||||
<system.webServer>
|
<system.webServer>
|
||||||
<rewrite>
|
<rewrite>
|
||||||
@ -532,6 +549,7 @@ and to
|
|||||||
- [Firebase hosting](https://firebase.google.com/docs/hosting/): add a
|
- [Firebase hosting](https://firebase.google.com/docs/hosting/): add a
|
||||||
[rewrite rule](https://firebase.google.com/docs/hosting/url-redirects-rewrites#section-rewrites).
|
[rewrite rule](https://firebase.google.com/docs/hosting/url-redirects-rewrites#section-rewrites).
|
||||||
|
|
||||||
|
|
||||||
<code-example format=".">
|
<code-example format=".">
|
||||||
"rewrites": [ {
|
"rewrites": [ {
|
||||||
"source": "**",
|
"source": "**",
|
||||||
|
@ -14,6 +14,7 @@ conditionally show a message below the list.
|
|||||||
|
|
||||||
The final UI looks like this:
|
The final UI looks like this:
|
||||||
|
|
||||||
|
|
||||||
<figure class='image-display'>
|
<figure class='image-display'>
|
||||||
<img src="assets/images/devguide/displaying-data/final.png" alt="Final UI"> </img>
|
<img src="assets/images/devguide/displaying-data/final.png" alt="Final UI"> </img>
|
||||||
</figure>
|
</figure>
|
||||||
@ -48,6 +49,7 @@ changing the template and the body of the component.
|
|||||||
When you're done, it should look like this:
|
When you're done, it should look like this:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="displaying-data/src/app/app.component.1.ts">
|
<code-example path="displaying-data/src/app/app.component.1.ts">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -58,6 +60,7 @@ The revised template displays the two component properties using double curly br
|
|||||||
interpolation:
|
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 path="displaying-data/src/app/app.component.1.ts" linenums="false" title="src/app/app.component.ts (template)" region="template">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -82,6 +85,7 @@ The CSS `selector` in the `@Component` !{_decorator} specifies an element named
|
|||||||
That element is a placeholder in the body of your `index.html` file:
|
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 path="displaying-data/src/index.html" linenums="false" title="src/index.html (body)" region="body">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -91,6 +95,7 @@ in the `index.html`, finds it, instantiates an instance of `AppComponent`, and r
|
|||||||
inside the `<my-app>` tag.
|
inside the `<my-app>` tag.
|
||||||
|
|
||||||
Now run the app. It should display the title and hero name:
|
Now run the app. It should display the title and hero name:
|
||||||
|
|
||||||
<figure class='image-display'>
|
<figure class='image-display'>
|
||||||
<img src="assets/images/devguide/displaying-data/title-and-hero.png" alt="Title and Hero"> </img>
|
<img src="assets/images/devguide/displaying-data/title-and-hero.png" alt="Title and Hero"> </img>
|
||||||
</figure>
|
</figure>
|
||||||
@ -114,6 +119,7 @@ In either style, the template data bindings have the same access to the componen
|
|||||||
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}.
|
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">
|
<code-example path="displaying-data/src/app/app.component.2.ts" linenums="false" title="src/app/app.component.ts (class)" region="class">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -122,6 +128,7 @@ Now use the Angular `ngFor` directive in the template to display
|
|||||||
each item in the `heroes` list.
|
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 path="displaying-data/src/app/app.component.2.ts" linenums="false" title="src/app/app.component.ts (template)" region="template">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -131,6 +138,7 @@ in the `<li>` element is the Angular "repeater" directive.
|
|||||||
It marks that `<li>` element (and its children) as the "repeater template":
|
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 path="displaying-data/src/app/app.component.2.ts" linenums="false" title="src/app/app.component.ts (li)" region="li">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -164,6 +172,7 @@ repeat items for any [iterable](guide/!{_iterableUrl}) object.
|
|||||||
|
|
||||||
Now the heroes appear in an unordered list.
|
Now the heroes appear in an unordered list.
|
||||||
|
|
||||||
|
|
||||||
<figure class='image-display'>
|
<figure class='image-display'>
|
||||||
<img src="assets/images/devguide/displaying-data/hero-names-list.png" alt="After ngfor"> </img>
|
<img src="assets/images/devguide/displaying-data/hero-names-list.png" alt="After ngfor"> </img>
|
||||||
</figure>
|
</figure>
|
||||||
@ -183,6 +192,7 @@ of hero names into !{_an} !{_array} of `Hero` objects. For that you'll need a `H
|
|||||||
Create a new file in the `!{_appDir}` folder called <ngio-ex path="hero.ts"></ngio-ex> with the following code:
|
Create a new file in the `!{_appDir}` folder called <ngio-ex path="hero.ts"></ngio-ex> with the following code:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="displaying-data/src/app/hero.ts" linenums="false" title="src/app/hero.ts (excerpt)">
|
<code-example path="displaying-data/src/app/hero.ts" linenums="false" title="src/app/hero.ts (excerpt)">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -196,6 +206,7 @@ The declaration of the constructor parameters takes advantage of a TypeScript sh
|
|||||||
Consider the first parameter:
|
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 path="displaying-data/src/app/hero.ts" linenums="false" title="src/app/hero.ts (id)" region="id">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -211,6 +222,7 @@ After importing the `Hero` class, the `AppComponent.heroes` property can return
|
|||||||
of `Hero` objects:
|
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 path="displaying-data/src/app/app.component.3.ts" linenums="false" title="src/app/app.component.ts (heroes)" region="heroes">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -220,6 +232,7 @@ At the moment it displays the hero's `id` and `name`.
|
|||||||
Fix that to display only the hero's `name` property.
|
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 path="displaying-data/src/app/app.component.3.ts" linenums="false" title="src/app/app.component.ts (template)" region="template">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -236,6 +249,7 @@ The Angular `ngIf` directive inserts or removes an element based on a !{_boolean
|
|||||||
To see it in action, add the following paragraph at the bottom of the template:
|
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 path="displaying-data/src/app/app.component.ts" linenums="false" title="src/app/app.component.ts (message)" region="message">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -282,23 +296,28 @@ Here's the final code:
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-tabs>
|
<code-tabs>
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="src/app/app.component.ts" path="displaying-data/src/app/app.component.ts" region="final">
|
<code-pane title="src/app/app.component.ts" path="displaying-data/src/app/app.component.ts" region="final">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="src/app/hero.ts" path="displaying-data/src/app/hero.ts">
|
<code-pane title="src/app/hero.ts" path="displaying-data/src/app/hero.ts">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="src/app/app.module.ts" path="displaying-data/src/app/app.module.ts">
|
<code-pane title="src/app/app.module.ts" path="displaying-data/src/app/app.module.ts">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="main.ts" path="displaying-data/src/main.ts">
|
<code-pane title="main.ts" path="displaying-data/src/main.ts">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
|
@ -37,6 +37,7 @@ 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.
|
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 path="cb-dynamic-component-loader/src/app/ad.directive.ts" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -50,28 +51,34 @@ 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.
|
We start by adding a `template` element with the `AdDirective` directive applied.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-tabs>
|
<code-tabs>
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="ad-banner.component.ts" path="cb-dynamic-component-loader/src/app/ad-banner.component.ts">
|
<code-pane title="ad-banner.component.ts" path="cb-dynamic-component-loader/src/app/ad-banner.component.ts">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="ad.service.ts" path="cb-dynamic-component-loader/src/app/ad.service.ts">
|
<code-pane title="ad.service.ts" path="cb-dynamic-component-loader/src/app/ad.service.ts">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="ad-item.ts" path="cb-dynamic-component-loader/src/app/ad-item.ts">
|
<code-pane title="ad-item.ts" path="cb-dynamic-component-loader/src/app/ad-item.ts">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="app.module.ts" path="cb-dynamic-component-loader/src/app/app.module.ts">
|
<code-pane title="app.module.ts" path="cb-dynamic-component-loader/src/app/app.module.ts">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="app.component" path="cb-dynamic-component-loader/src/app/app.component.ts">
|
<code-pane title="app.component" path="cb-dynamic-component-loader/src/app/app.component.ts">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
@ -84,6 +91,7 @@ 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.
|
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 path="cb-dynamic-component-loader/src/app/ad-banner.component.ts" region="ad-host" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -107,6 +115,7 @@ 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.
|
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 path="cb-dynamic-component-loader/src/app/app.module.ts" region="entry-components" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -120,18 +129,22 @@ In the Ad banner, all components implement a common `AdComponent` interface to s
|
|||||||
Two sample components and the `AdComponent` interface are shown below:
|
Two sample components and the `AdComponent` interface are shown below:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-tabs>
|
<code-tabs>
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="hero-job-ad.component.ts" path="cb-dynamic-component-loader/src/app/hero-job-ad.component.ts">
|
<code-pane title="hero-job-ad.component.ts" path="cb-dynamic-component-loader/src/app/hero-job-ad.component.ts">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="hero-profile.component.ts" path="cb-dynamic-component-loader/src/app/hero-profile.component.ts">
|
<code-pane title="hero-profile.component.ts" path="cb-dynamic-component-loader/src/app/hero-profile.component.ts">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="ad.component.ts" path="cb-dynamic-component-loader/src/app/ad.component.ts">
|
<code-pane title="ad.component.ts" path="cb-dynamic-component-loader/src/app/ad.component.ts">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
@ -140,6 +153,7 @@ Two sample components and the `AdComponent` interface are shown below:
|
|||||||
</code-tabs>
|
</code-tabs>
|
||||||
|
|
||||||
The final ad banner looks like this:
|
The final ad banner looks like this:
|
||||||
|
|
||||||
<figure class='image-display'>
|
<figure class='image-display'>
|
||||||
<img src="assets/images/cookbooks/dynamic-component-loader/ads.gif" alt="Ads"> </img>
|
<img src="assets/images/cookbooks/dynamic-component-loader/ads.gif" alt="Ads"> </img>
|
||||||
</figure>
|
</figure>
|
||||||
|
@ -43,13 +43,16 @@ Reactive Forms belongs to a different `NgModule` called `ReactiveFormsModule`, s
|
|||||||
We bootstrap our `AppModule` in main.ts.
|
We bootstrap our `AppModule` in main.ts.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-tabs>
|
<code-tabs>
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="app.module.ts" path="cb-dynamic-form/src/app/app.module.ts">
|
<code-pane title="app.module.ts" path="cb-dynamic-form/src/app/app.module.ts">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="main.ts" path="cb-dynamic-form/src/main.ts">
|
<code-pane title="main.ts" path="cb-dynamic-form/src/main.ts">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
@ -67,6 +70,7 @@ The "question" is the most fundamental object in the model.
|
|||||||
We have created `QuestionBase` as the most fundamental question class.
|
We have created `QuestionBase` as the most fundamental question class.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="cb-dynamic-form/src/app/question-base.ts">
|
<code-example path="cb-dynamic-form/src/app/question-base.ts">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -77,6 +81,7 @@ 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.
|
`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 path="cb-dynamic-form/src/app/question-textbox.ts" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -84,6 +89,7 @@ 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.
|
`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 path="cb-dynamic-form/src/app/question-dropdown.ts" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -92,6 +98,7 @@ 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.
|
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 path="cb-dynamic-form/src/app/question-control.service.ts" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -100,13 +107,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.
|
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.
|
`DynamicFormComponent` is the entry point and the main container for the form.
|
||||||
|
|
||||||
|
|
||||||
<code-tabs>
|
<code-tabs>
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="dynamic-form.component.html" path="cb-dynamic-form/src/app/dynamic-form.component.html">
|
<code-pane title="dynamic-form.component.html" path="cb-dynamic-form/src/app/dynamic-form.component.html">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="dynamic-form.component.ts" path="cb-dynamic-form/src/app/dynamic-form.component.ts">
|
<code-pane title="dynamic-form.component.ts" path="cb-dynamic-form/src/app/dynamic-form.component.ts">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
@ -119,13 +129,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.
|
the component responsible for rendering the details of each _individual_ question based on values in the data-bound question object.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-tabs>
|
<code-tabs>
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="dynamic-form-question.component.html" path="cb-dynamic-form/src/app/dynamic-form-question.component.html">
|
<code-pane title="dynamic-form-question.component.html" path="cb-dynamic-form/src/app/dynamic-form-question.component.html">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="dynamic-form-question.component.ts" path="cb-dynamic-form/src/app/dynamic-form-question.component.ts">
|
<code-pane title="dynamic-form-question.component.ts" path="cb-dynamic-form/src/app/dynamic-form-question.component.ts">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
@ -150,6 +163,7 @@ 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.
|
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 path="cb-dynamic-form/src/app/question.service.ts">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -157,6 +171,7 @@ underlying control objects, populated from the question model with display and v
|
|||||||
Finally, we display an instance of the form in the `AppComponent` shell.
|
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 path="cb-dynamic-form/src/app/app.component.ts">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -176,6 +191,7 @@ When the form is valid, we can click *Save* and the app renders the current form
|
|||||||
This proves that any user input is bound back to the data model.
|
This proves that any user input is bound back to the data model.
|
||||||
Saving and retrieving the data is an exercise for another time.
|
Saving and retrieving the data is an exercise for another time.
|
||||||
The final form looks like this:
|
The final form looks like this:
|
||||||
|
|
||||||
<figure class='image-display'>
|
<figure class='image-display'>
|
||||||
<img src="assets/images/cookbooks/dynamic-form/dynamic-form.png" alt="Dynamic-Form"> </img>
|
<img src="assets/images/cookbooks/dynamic-form/dynamic-form.png" alt="Dynamic-Form"> </img>
|
||||||
</figure>
|
</figure>
|
||||||
|
@ -44,6 +44,7 @@ and the [Reactive Forms](guide/reactive-forms) guides.
|
|||||||
|
|
||||||
{@a live-example}
|
{@a live-example}
|
||||||
**Try the live example to see and download the full cookbook source code.**
|
**Try the live example to see and download the full cookbook source code.**
|
||||||
|
|
||||||
<live-example name="cb-form-validation" embedded=true img="cookbooks/form-validation/plunker.png">
|
<live-example name="cb-form-validation" embedded=true img="cookbooks/form-validation/plunker.png">
|
||||||
|
|
||||||
</live-example>
|
</live-example>
|
||||||
@ -71,6 +72,7 @@ In this first template validation example,
|
|||||||
notice the HTML that reads the control state and updates the display appropriately.
|
notice the HTML that reads the control state and updates the display appropriately.
|
||||||
Here's an excerpt from the template HTML for a single input control bound to the hero name:
|
Here's an excerpt from the template HTML for a single input control bound to the hero name:
|
||||||
|
|
||||||
|
|
||||||
<code-example path="cb-form-validation/src/app/template/hero-form-template1.component.html" region="name-with-error-msg" linenums="false">
|
<code-example path="cb-form-validation/src/app/template/hero-form-template1.component.html" region="name-with-error-msg" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -114,6 +116,7 @@ The component class manages the hero model used in the data binding
|
|||||||
as well as other code to support the view.
|
as well as other code to support the view.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="cb-form-validation/src/app/template/hero-form-template1.component.ts" region="class">
|
<code-example path="cb-form-validation/src/app/template/hero-form-template1.component.ts" region="class">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -123,13 +126,16 @@ Use this template-driven validation technique when working with static forms wit
|
|||||||
Here are the complete files for the first version of `HeroFormTemplateCompononent` in the template-driven approach:
|
Here are the complete files for the first version of `HeroFormTemplateCompononent` in the template-driven approach:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-tabs>
|
<code-tabs>
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="template/hero-form-template1.component.html" path="cb-form-validation/src/app/template/hero-form-template1.component.html">
|
<code-pane title="template/hero-form-template1.component.html" path="cb-form-validation/src/app/template/hero-form-template1.component.html">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="template/hero-form-template1.component.ts" path="cb-form-validation/src/app/template/hero-form-template1.component.ts">
|
<code-pane title="template/hero-form-template1.component.ts" path="cb-form-validation/src/app/template/hero-form-template1.component.ts">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
@ -160,13 +166,16 @@ the template and component.
|
|||||||
Here's the hero name again, excerpted from the revised template
|
Here's the hero name again, excerpted from the revised template
|
||||||
(Template 2), next to the original version:
|
(Template 2), next to the original version:
|
||||||
|
|
||||||
|
|
||||||
<code-tabs>
|
<code-tabs>
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="hero-form-template2.component.html (name #2)" path="cb-form-validation/src/app/template/hero-form-template2.component.html" region="name-with-error-msg">
|
<code-pane title="hero-form-template2.component.html (name #2)" path="cb-form-validation/src/app/template/hero-form-template2.component.html" region="name-with-error-msg">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="hero-form-template1.component.html (name #1)" path="cb-form-validation/src/app/template/hero-form-template1.component.html" region="name-with-error-msg">
|
<code-pane title="hero-form-template1.component.html (name #1)" path="cb-form-validation/src/app/template/hero-form-template1.component.html" region="name-with-error-msg">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
@ -199,6 +208,7 @@ The first step is to acquire the form control that Angular created from the temp
|
|||||||
Look back at the top of the component template at the
|
Look back at the top of the component template at the
|
||||||
`#heroForm` template variable in the `<form>` element:
|
`#heroForm` template variable in the `<form>` element:
|
||||||
|
|
||||||
|
|
||||||
<code-example path="cb-form-validation/src/app/template/hero-form-template1.component.html" region="form-tag" linenums="false">
|
<code-example path="cb-form-validation/src/app/template/hero-form-template1.component.html" region="form-tag" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -206,6 +216,7 @@ Look back at the top of the component template at the
|
|||||||
The `heroForm` variable is a reference to the control model that Angular derived from the template.
|
The `heroForm` variable is a reference to the control model that Angular derived from the template.
|
||||||
Tell Angular to inject that model into the component class's `currentForm` property using a `@ViewChild` query:
|
Tell Angular to inject that model into the component class's `currentForm` property using a `@ViewChild` query:
|
||||||
|
|
||||||
|
|
||||||
<code-example path="cb-form-validation/src/app/template/hero-form-template2.component.ts" region="view-child" linenums="false">
|
<code-example path="cb-form-validation/src/app/template/hero-form-template2.component.ts" region="view-child" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -225,6 +236,7 @@ That's the right time to see if there's a new `heroForm` object.
|
|||||||
- When there _is_ a new `heroForm` model, `formChanged()` subscribes to its `valueChanges` _Observable_ property.
|
- When there _is_ a new `heroForm` model, `formChanged()` subscribes to its `valueChanges` _Observable_ property.
|
||||||
The `onValueChanged` handler looks for validation errors after every keystroke.
|
The `onValueChanged` handler looks for validation errors after every keystroke.
|
||||||
|
|
||||||
|
|
||||||
<code-example path="cb-form-validation/src/app/template/hero-form-template2.component.ts" region="handler" linenums="false">
|
<code-example path="cb-form-validation/src/app/template/hero-form-template2.component.ts" region="handler" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -246,6 +258,7 @@ For each field, the `onValueChanged` handler does the following:
|
|||||||
Next, the component needs some error messages of course—a set for each validated property with
|
Next, the component needs some error messages of course—a set for each validated property with
|
||||||
one message per validation rule:
|
one message per validation rule:
|
||||||
|
|
||||||
|
|
||||||
<code-example path="cb-form-validation/src/app/template/hero-form-template2.component.ts" region="messages" linenums="false">
|
<code-example path="cb-form-validation/src/app/template/hero-form-template2.component.ts" region="messages" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -290,6 +303,7 @@ You've been reviewing the "Template-driven" approach which requires the `FormsMo
|
|||||||
Here's how you imported it in the `HeroFormTemplateModule`.
|
Here's how you imported it in the `HeroFormTemplateModule`.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="cb-form-validation/src/app/template/hero-form-template.module.ts" linenums="false">
|
<code-example path="cb-form-validation/src/app/template/hero-form-template.module.ts" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -336,6 +350,7 @@ The following cookbook sample re-writes the hero form in _reactive forms_ style.
|
|||||||
The reactive forms classes and directives come from the Angular `ReactiveFormsModule`, not the `FormsModule`.
|
The reactive forms classes and directives come from the Angular `ReactiveFormsModule`, not the `FormsModule`.
|
||||||
The application module for the reactive forms feature in this sample looks like this:
|
The application module for the reactive forms feature in this sample looks like this:
|
||||||
|
|
||||||
|
|
||||||
<code-example path="cb-form-validation/src/app/reactive/hero-form-reactive.module.ts" linenums="false">
|
<code-example path="cb-form-validation/src/app/reactive/hero-form-reactive.module.ts" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -352,6 +367,7 @@ to the `heroForm` property in the component class.
|
|||||||
The `heroForm` is the control model that the component class builds and maintains.
|
The `heroForm` is the control model that the component class builds and maintains.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="cb-form-validation/src/app/reactive/hero-form-reactive.component.html" region="form-tag" linenums="false">
|
<code-example path="cb-form-validation/src/app/reactive/hero-form-reactive.component.html" region="form-tag" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -359,13 +375,16 @@ The `heroForm` is the control model that the component class builds and maintain
|
|||||||
Next, modify the template HTML elements to match the _reactive forms_ style.
|
Next, modify the template HTML elements to match the _reactive forms_ style.
|
||||||
Here is the "name" portion of the template again, revised for reactive forms and compared with the template-driven version:
|
Here is the "name" portion of the template again, revised for reactive forms and compared with the template-driven version:
|
||||||
|
|
||||||
|
|
||||||
<code-tabs>
|
<code-tabs>
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="hero-form-reactive.component.html (name #3)" path="cb-form-validation/src/app/reactive/hero-form-reactive.component.html" region="name-with-error-msg">
|
<code-pane title="hero-form-reactive.component.html (name #3)" path="cb-form-validation/src/app/reactive/hero-form-reactive.component.html" region="name-with-error-msg">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="hero-form-template1.component.html (name #2)" path="cb-form-validation/src/app/template/hero-form-template2.component.html" region="name-with-error-msg">
|
<code-pane title="hero-form-template1.component.html (name #2)" path="cb-form-validation/src/app/template/hero-form-template2.component.html" region="name-with-error-msg">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
@ -419,13 +438,16 @@ the help of the `FormBuilder` class.
|
|||||||
|
|
||||||
Here's the section of code devoted to that process, paired with the template-driven code it replaces:
|
Here's the section of code devoted to that process, paired with the template-driven code it replaces:
|
||||||
|
|
||||||
|
|
||||||
<code-tabs>
|
<code-tabs>
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="reactive/hero-form-reactive.component.ts (FormBuilder)" path="cb-form-validation/src/app/reactive/hero-form-reactive.component.ts" region="form-builder">
|
<code-pane title="reactive/hero-form-reactive.component.ts (FormBuilder)" path="cb-form-validation/src/app/reactive/hero-form-reactive.component.ts" region="form-builder">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="template/hero-form-template2.component.ts (ViewChild)" path="cb-form-validation/src/app/template/hero-form-template2.component.ts" region="view-child">
|
<code-pane title="template/hero-form-template2.component.ts (ViewChild)" path="cb-form-validation/src/app/template/hero-form-template2.component.ts" region="view-child">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
@ -487,6 +509,7 @@ This sample updates the model twice:
|
|||||||
|
|
||||||
The `onSubmit()` method simply replaces the `hero` object with the combined values of the form:
|
The `onSubmit()` method simply replaces the `hero` object with the combined values of the form:
|
||||||
|
|
||||||
|
|
||||||
<code-example path="cb-form-validation/src/app/reactive/hero-form-reactive.component.ts" region="on-submit" linenums="false">
|
<code-example path="cb-form-validation/src/app/reactive/hero-form-reactive.component.ts" region="on-submit" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -502,6 +525,7 @@ correspond _exactly_ to the hero data object properties.
|
|||||||
|
|
||||||
The `addHero()` method discards pending changes and creates a brand new `hero` model object.
|
The `addHero()` method discards pending changes and creates a brand new `hero` model object.
|
||||||
|
|
||||||
|
|
||||||
<code-example path="cb-form-validation/src/app/reactive/hero-form-reactive.component.ts" region="add-hero" linenums="false">
|
<code-example path="cb-form-validation/src/app/reactive/hero-form-reactive.component.ts" region="add-hero" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -511,18 +535,22 @@ The `<form>` tag's `[formGroup]` binding refreshes the page with the new control
|
|||||||
|
|
||||||
Here's the complete reactive component file, compared to the two template-driven component files.
|
Here's the complete reactive component file, compared to the two template-driven component files.
|
||||||
|
|
||||||
|
|
||||||
<code-tabs>
|
<code-tabs>
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="reactive/hero-form-reactive.component.ts (#3)" path="cb-form-validation/src/app/reactive/hero-form-reactive.component.ts">
|
<code-pane title="reactive/hero-form-reactive.component.ts (#3)" path="cb-form-validation/src/app/reactive/hero-form-reactive.component.ts">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="template/hero-form-template2.component.ts (#2)" path="cb-form-validation/src/app/template/hero-form-template2.component.ts">
|
<code-pane title="template/hero-form-template2.component.ts (#2)" path="cb-form-validation/src/app/template/hero-form-template2.component.ts">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="template/hero-form-template1.component.ts (#1)" path="cb-form-validation/src/app/template/hero-form-template1.component.ts">
|
<code-pane title="template/hero-form-template1.component.ts (#1)" path="cb-form-validation/src/app/template/hero-form-template1.component.ts">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
@ -551,6 +579,7 @@ and declared in the `SharedModule`.
|
|||||||
|
|
||||||
Here's the `forbiddenNamevalidator()` function:
|
Here's the `forbiddenNamevalidator()` function:
|
||||||
|
|
||||||
|
|
||||||
<code-example path="cb-form-validation/src/app/shared/forbidden-name.directive.ts" region="custom-validator" linenums="false">
|
<code-example path="cb-form-validation/src/app/shared/forbidden-name.directive.ts" region="custom-validator" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -574,6 +603,7 @@ and whose value is an arbitrary dictionary of values that you could insert into
|
|||||||
In the reactive forms component, the `'name'` control's validator function list
|
In the reactive forms component, the `'name'` control's validator function list
|
||||||
has a `forbiddenNameValidator` at the bottom.
|
has a `forbiddenNameValidator` at the bottom.
|
||||||
|
|
||||||
|
|
||||||
<code-example path="cb-form-validation/src/app/reactive/hero-form-reactive.component.ts" region="name-validators" linenums="false">
|
<code-example path="cb-form-validation/src/app/reactive/hero-form-reactive.component.ts" region="name-validators" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -581,6 +611,7 @@ has a `forbiddenNameValidator` at the bottom.
|
|||||||
In the _template-driven_ example, the `<input>` has the selector (`forbiddenName`)
|
In the _template-driven_ example, the `<input>` has the selector (`forbiddenName`)
|
||||||
of a custom _attribute directive_, which rejects "bob".
|
of a custom _attribute directive_, which rejects "bob".
|
||||||
|
|
||||||
|
|
||||||
<code-example path="cb-form-validation/src/app/template/hero-form-template2.component.html" region="name-input" linenums="false">
|
<code-example path="cb-form-validation/src/app/template/hero-form-template2.component.html" region="name-input" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -590,12 +621,14 @@ The corresponding `ForbiddenValidatorDirective` is a wrapper around the `forbidd
|
|||||||
Angular `forms` recognizes the directive's role in the validation process because the directive registers itself
|
Angular `forms` recognizes the directive's role in the validation process because the directive registers itself
|
||||||
with the `NG_VALIDATORS` provider, a provider with an extensible collection of validation directives.
|
with the `NG_VALIDATORS` provider, a provider with an extensible collection of validation directives.
|
||||||
|
|
||||||
|
|
||||||
<code-example path="cb-form-validation/src/app/shared/forbidden-name.directive.ts" region="directive-providers" linenums="false">
|
<code-example path="cb-form-validation/src/app/shared/forbidden-name.directive.ts" region="directive-providers" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
|
|
||||||
Here is the rest of the directive to help you get an idea of how it all comes together:
|
Here is the rest of the directive to help you get an idea of how it all comes together:
|
||||||
|
|
||||||
|
|
||||||
<code-example path="cb-form-validation/src/app/shared/forbidden-name.directive.ts" region="directive">
|
<code-example path="cb-form-validation/src/app/shared/forbidden-name.directive.ts" region="directive">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
|
@ -50,6 +50,7 @@ otherwise wrestle with yourself.
|
|||||||
|
|
||||||
You'll learn to build a template-driven form that looks like this:
|
You'll learn to build a template-driven form that looks like this:
|
||||||
|
|
||||||
|
|
||||||
<figure class='image-display'>
|
<figure class='image-display'>
|
||||||
<img src="assets/images/devguide/forms/hero-form-1.png" width="400px" alt="Clean Form"> </img>
|
<img src="assets/images/devguide/forms/hero-form-1.png" width="400px" alt="Clean Form"> </img>
|
||||||
</figure>
|
</figure>
|
||||||
@ -61,6 +62,7 @@ Two of the three fields on this form are required. Required fields have a green
|
|||||||
|
|
||||||
If you delete the hero name, the form displays a validation error in an attention-grabbing style:
|
If you delete the hero name, the form displays a validation error in an attention-grabbing style:
|
||||||
|
|
||||||
|
|
||||||
<figure class='image-display'>
|
<figure class='image-display'>
|
||||||
<img src="assets/images/devguide/forms/hero-form-2.png" width="400px" alt="Invalid, Name Required"> </img>
|
<img src="assets/images/devguide/forms/hero-form-2.png" width="400px" alt="Invalid, Name Required"> </img>
|
||||||
</figure>
|
</figure>
|
||||||
@ -103,6 +105,7 @@ and one optional field (`alterEgo`).
|
|||||||
In the `!{_appDir}` directory, create the following file with the given content:
|
In the `!{_appDir}` directory, create the following file with the given content:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="forms/src/app/hero.ts">
|
<code-example path="forms/src/app/hero.ts">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -117,6 +120,7 @@ The `alterEgo` is optional, so the constructor lets you omit it; note the questi
|
|||||||
You can create a new hero like this:
|
You can create a new hero like this:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="forms/src/app/hero-form.component.ts" linenums="false" title="src/app/hero-form.component.ts (SkyDog)" region="SkyDog">
|
<code-example path="forms/src/app/hero-form.component.ts" linenums="false" title="src/app/hero-form.component.ts (SkyDog)" region="SkyDog">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -131,6 +135,7 @@ Begin with the class because it states, in brief, what the hero editor can do.
|
|||||||
Create the following file with the given content:
|
Create the following file with the given content:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="forms/src/app/hero-form.component.ts" linenums="false" title="src/app/hero-form.component.ts (v1)" region="v1">
|
<code-example path="forms/src/app/hero-form.component.ts" linenums="false" title="src/app/hero-form.component.ts (v1)" region="v1">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -175,6 +180,7 @@ Because template-driven forms are in their own module, you need to add the `Form
|
|||||||
|
|
||||||
Replace the contents of the "QuickStart" version with the following:
|
Replace the contents of the "QuickStart" version with the following:
|
||||||
|
|
||||||
|
|
||||||
<code-example path="forms/src/app/app.module.ts">
|
<code-example path="forms/src/app/app.module.ts">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -214,6 +220,7 @@ If you wrote it and it should belong to this module, _do_ declare it in th
|
|||||||
Replace the contents of the "QuickStart" version with the following:
|
Replace the contents of the "QuickStart" version with the following:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="forms/src/app/app.component.ts">
|
<code-example path="forms/src/app/app.component.ts">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -236,6 +243,7 @@ You've also dropped the `name` field from the class body.
|
|||||||
Create the template file with the following contents:
|
Create the template file with the following contents:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="forms/src/app/hero-form.component.html" region="start">
|
<code-example path="forms/src/app/hero-form.component.html" region="start">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -258,6 +266,7 @@ Bootstrap gives the form a little style.
|
|||||||
~~~ {.callout.is-important}
|
~~~ {.callout.is-important}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<header>
|
<header>
|
||||||
Angular forms don't require a style library
|
Angular forms don't require a style library
|
||||||
</header>
|
</header>
|
||||||
@ -271,6 +280,7 @@ the styles of any external library. Angular apps can use any CSS library or none
|
|||||||
To add the stylesheet, open `index.html` and add the following link to the `<head>`:
|
To add the stylesheet, open `index.html` and add the following link to the `<head>`:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="forms/src/index.html" linenums="false" title="src/index.html (bootstrap)" region="bootstrap">
|
<code-example path="forms/src/index.html" linenums="false" title="src/index.html (bootstrap)" region="bootstrap">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -288,6 +298,7 @@ a technique seen previously in the [Displaying Data](guide/displaying-data) page
|
|||||||
Add the following HTML *immediately below* the *Alter Ego* group:
|
Add the following HTML *immediately below* the *Alter Ego* group:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="forms/src/app/hero-form.component.html" linenums="false" title="src/app/hero-form.component.html (powers)" region="powers">
|
<code-example path="forms/src/app/hero-form.component.html" linenums="false" title="src/app/hero-form.component.html (powers)" region="powers">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -300,6 +311,7 @@ you display its name using the interpolation syntax.
|
|||||||
|
|
||||||
Running the app right now would be disappointing.
|
Running the app right now would be disappointing.
|
||||||
|
|
||||||
|
|
||||||
<figure class='image-display'>
|
<figure class='image-display'>
|
||||||
<img src="assets/images/devguide/forms/hero-form-3.png" width="400px" alt="Early form with no binding"> </img>
|
<img src="assets/images/devguide/forms/hero-form-3.png" width="400px" alt="Early form with no binding"> </img>
|
||||||
</figure>
|
</figure>
|
||||||
@ -319,6 +331,7 @@ makes binding the form to the model easy.
|
|||||||
Find the `<input>` tag for *Name* and update it like this:
|
Find the `<input>` tag for *Name* and update it like this:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="forms/src/app/hero-form.component.html" linenums="false" title="src/app/hero-form.component.html (excerpt)" region="ngModelName-1">
|
<code-example path="forms/src/app/hero-form.component.html" linenums="false" title="src/app/hero-form.component.html (excerpt)" region="ngModelName-1">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -341,6 +354,7 @@ adding and deleting characters, you'd see them appear and disappear
|
|||||||
from the interpolated text.
|
from the interpolated text.
|
||||||
At some point it might look like this:
|
At some point it might look like this:
|
||||||
|
|
||||||
|
|
||||||
<figure class='image-display'>
|
<figure class='image-display'>
|
||||||
<img src="assets/images/devguide/forms/ng-model-in-action.png" width="400px" alt="ngModel in action"> </img>
|
<img src="assets/images/devguide/forms/ng-model-in-action.png" width="400px" alt="ngModel in action"> </img>
|
||||||
</figure>
|
</figure>
|
||||||
@ -382,6 +396,7 @@ Then you can confirm that two-way data binding works *for the entire hero model*
|
|||||||
After revision, the core of the form should look like this:
|
After revision, the core of the form should look like this:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="forms/src/app/hero-form.component.html" linenums="false" title="src/app/hero-form.component.html (excerpt)" region="ngModel-2">
|
<code-example path="forms/src/app/hero-form.component.html" linenums="false" title="src/app/hero-form.component.html (excerpt)" region="ngModel-2">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -399,6 +414,7 @@ to match the label to its input control.
|
|||||||
|
|
||||||
If you run the app now and change every hero model property, the form might display like this:
|
If you run the app now and change every hero model property, the form might display like this:
|
||||||
|
|
||||||
|
|
||||||
<figure class='image-display'>
|
<figure class='image-display'>
|
||||||
<img src="assets/images/devguide/forms/ng-model-in-action-2.png" width="400px" alt="ngModel in action"> </img>
|
<img src="assets/images/devguide/forms/ng-model-in-action-2.png" width="400px" alt="ngModel in action"> </img>
|
||||||
</figure>
|
</figure>
|
||||||
@ -416,20 +432,25 @@ you if the user touched the control, if the value changed, or if the value becam
|
|||||||
The *NgModel* directive doesn't just track state; it updates the control with special Angular CSS classes that reflect the state.
|
The *NgModel* directive doesn't just track state; it updates the control with special Angular CSS classes that reflect the state.
|
||||||
You can leverage those class names to change the appearance of the control.
|
You can leverage those class names to change the appearance of the control.
|
||||||
|
|
||||||
|
|
||||||
<table>
|
<table>
|
||||||
|
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
|
|
||||||
|
|
||||||
<th>
|
<th>
|
||||||
State
|
State
|
||||||
</th>
|
</th>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<th>
|
<th>
|
||||||
Class if true
|
Class if true
|
||||||
</th>
|
</th>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<th>
|
<th>
|
||||||
Class if false
|
Class if false
|
||||||
</th>
|
</th>
|
||||||
@ -438,18 +459,22 @@ You can leverage those class names to change the appearance of the control.
|
|||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
The control has been visited.
|
The control has been visited.
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
<code>ng-touched</code>
|
<code>ng-touched</code>
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
<code>ng-untouched</code>
|
<code>ng-untouched</code>
|
||||||
</td>
|
</td>
|
||||||
@ -458,18 +483,22 @@ You can leverage those class names to change the appearance of the control.
|
|||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
The control's value has changed.
|
The control's value has changed.
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
<code>ng-dirty</code>
|
<code>ng-dirty</code>
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
<code>ng-pristine</code>
|
<code>ng-pristine</code>
|
||||||
</td>
|
</td>
|
||||||
@ -478,18 +507,22 @@ You can leverage those class names to change the appearance of the control.
|
|||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
The control's value is valid.
|
The control's value is valid.
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
<code>ng-valid</code>
|
<code>ng-valid</code>
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
<code>ng-invalid</code>
|
<code>ng-invalid</code>
|
||||||
</td>
|
</td>
|
||||||
@ -504,6 +537,7 @@ Temporarily add a [template reference variable](guide/template-syntax) named `sp
|
|||||||
to the _Name_ `<input>` tag and use it to display the input's CSS classes.
|
to the _Name_ `<input>` tag and use it to display the input's CSS classes.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="forms/src/app/hero-form.component.html" linenums="false" title="src/app/hero-form.component.html (excerpt)" region="ngModelName-2">
|
<code-example path="forms/src/app/hero-form.component.html" linenums="false" title="src/app/hero-form.component.html (excerpt)" region="ngModelName-2">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -518,12 +552,14 @@ Follow these steps *precisely*:
|
|||||||
|
|
||||||
The actions and effects are as follows:
|
The actions and effects are as follows:
|
||||||
|
|
||||||
|
|
||||||
<figure class='image-display'>
|
<figure class='image-display'>
|
||||||
<img src="assets/images/devguide/forms/control-state-transitions-anim.gif" alt="Control State Transition"> </img>
|
<img src="assets/images/devguide/forms/control-state-transitions-anim.gif" alt="Control State Transition"> </img>
|
||||||
</figure>
|
</figure>
|
||||||
|
|
||||||
You should see the following transitions and class names:
|
You should see the following transitions and class names:
|
||||||
|
|
||||||
|
|
||||||
<figure class='image-display'>
|
<figure class='image-display'>
|
||||||
<img src="assets/images/devguide/forms/ng-control-class-changes.png" width="500px" alt="Control state transitions"> </img>
|
<img src="assets/images/devguide/forms/ng-control-class-changes.png" width="500px" alt="Control state transitions"> </img>
|
||||||
</figure>
|
</figure>
|
||||||
@ -539,6 +575,7 @@ To create such visual feedback, add definitions for the `ng-*` CSS classes.
|
|||||||
You can mark required fields and invalid data at the same time with a colored bar
|
You can mark required fields and invalid data at the same time with a colored bar
|
||||||
on the left of the input box:
|
on the left of the input box:
|
||||||
|
|
||||||
|
|
||||||
<figure class='image-display'>
|
<figure class='image-display'>
|
||||||
<img src="assets/images/devguide/forms/validity-required-indicator.png" width="400px" alt="Invalid Form"> </img>
|
<img src="assets/images/devguide/forms/validity-required-indicator.png" width="400px" alt="Invalid Form"> </img>
|
||||||
</figure>
|
</figure>
|
||||||
@ -547,6 +584,7 @@ You achieve this effect by adding these class definitions to a new `forms.css` f
|
|||||||
that you add to the project as a sibling to `index.html`:
|
that you add to the project as a sibling to `index.html`:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="forms/src/forms.css">
|
<code-example path="forms/src/forms.css">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -554,6 +592,7 @@ that you add to the project as a sibling to `index.html`:
|
|||||||
Update the `<head>` of `index.html` to include this style sheet:
|
Update the `<head>` of `index.html` to include this style sheet:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="forms/src/index.html" linenums="false" title="src/index.html (styles)" region="styles">
|
<code-example path="forms/src/index.html" linenums="false" title="src/index.html (styles)" region="styles">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -566,6 +605,7 @@ Leverage the control's state to reveal a helpful message.
|
|||||||
|
|
||||||
When the user deletes the name, the form should look like this:
|
When the user deletes the name, the form should look like this:
|
||||||
|
|
||||||
|
|
||||||
<figure class='image-display'>
|
<figure class='image-display'>
|
||||||
<img src="assets/images/devguide/forms/name-required-error.png" width="400px" alt="Name required"> </img>
|
<img src="assets/images/devguide/forms/name-required-error.png" width="400px" alt="Name required"> </img>
|
||||||
</figure>
|
</figure>
|
||||||
@ -577,6 +617,7 @@ To achieve this effect, extend the `<input>` tag with the following:
|
|||||||
Here's an example of an error message added to the _name_ input box:
|
Here's an example of an error message added to the _name_ input box:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="forms/src/app/hero-form.component.html" linenums="false" title="src/app/hero-form.component.html (excerpt)" region="name-with-error-msg">
|
<code-example path="forms/src/app/hero-form.component.html" linenums="false" title="src/app/hero-form.component.html (excerpt)" region="name-with-error-msg">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -599,6 +640,7 @@ You control visibility of the name error message by binding properties of the `n
|
|||||||
control to the message `<div>` element's `hidden` property.
|
control to the message `<div>` element's `hidden` property.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="forms/src/app/hero-form.component.html" linenums="false" title="src/app/hero-form.component.html (hidden-error-msg)" region="hidden-error-msg">
|
<code-example path="forms/src/app/hero-form.component.html" linenums="false" title="src/app/hero-form.component.html (hidden-error-msg)" region="hidden-error-msg">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -626,12 +668,14 @@ Now you'll add a new hero in this form.
|
|||||||
Place a *New Hero* button at the bottom of the form and bind its click event to a `newHero` component method.
|
Place a *New Hero* button at the bottom of the form and bind its click event to a `newHero` component method.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="forms/src/app/hero-form.component.html" region="new-hero-button-no-reset">
|
<code-example path="forms/src/app/hero-form.component.html" region="new-hero-button-no-reset">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="forms/src/app/hero-form.component.ts" region="new-hero" linenums="false">
|
<code-example path="forms/src/app/hero-form.component.ts" region="new-hero" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -654,6 +698,7 @@ You have to clear all of the flags imperatively, which you can do
|
|||||||
by calling the form's `reset()` method after calling the `newHero()` method.
|
by calling the form's `reset()` method after calling the `newHero()` method.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="forms/src/app/hero-form.component.html" region="new-hero-button-form-reset">
|
<code-example path="forms/src/app/hero-form.component.html" region="new-hero-button-form-reset">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -672,6 +717,7 @@ To make it useful, bind the form's `ngSubmit` event property
|
|||||||
to the hero form component's `onSubmit()` method:
|
to the hero form component's `onSubmit()` method:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="forms/src/app/hero-form.component.html" linenums="false" title="forms/ts/src/app/hero-form.component.html (ngSubmit)" region="ngSubmit">
|
<code-example path="forms/src/app/hero-form.component.html" linenums="false" title="forms/ts/src/app/hero-form.component.html (ngSubmit)" region="ngSubmit">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -705,6 +751,7 @@ the `heroForm` variable to the button's `disabled` property
|
|||||||
using an event binding. Here's the code:
|
using an event binding. Here's the code:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="forms/src/app/hero-form.component.html" linenums="false" title="src/app/hero-form.component.html (submit-button)" region="submit-button">
|
<code-example path="forms/src/app/hero-form.component.html" linenums="false" title="src/app/hero-form.component.html (submit-button)" region="submit-button">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -747,6 +794,7 @@ Wrap the form in a `<div>` and bind
|
|||||||
its `hidden` property to the `HeroFormComponent.submitted` property.
|
its `hidden` property to the `HeroFormComponent.submitted` property.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="forms/src/app/hero-form.component.html" linenums="false" title="src/app/hero-form.component.html (excerpt)" region="edit-div">
|
<code-example path="forms/src/app/hero-form.component.html" linenums="false" title="src/app/hero-form.component.html (excerpt)" region="edit-div">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -756,6 +804,7 @@ The main form is visible from the start because the
|
|||||||
as this fragment from the `HeroFormComponent` shows:
|
as this fragment from the `HeroFormComponent` shows:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="forms/src/app/hero-form.component.ts" linenums="false" title="src/app/hero-form.component.ts (submitted)" region="submitted">
|
<code-example path="forms/src/app/hero-form.component.ts" linenums="false" title="src/app/hero-form.component.ts (submitted)" region="submitted">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -767,6 +816,7 @@ Now the app needs to show something else while the form is in the submitted stat
|
|||||||
Add the following HTML below the `<div>` wrapper you just wrote:
|
Add the following HTML below the `<div>` wrapper you just wrote:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="forms/src/app/hero-form.component.html" linenums="false" title="src/app/hero-form.component.html (excerpt)" region="submitted">
|
<code-example path="forms/src/app/hero-form.component.html" linenums="false" title="src/app/hero-form.component.html (excerpt)" region="submitted">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -796,34 +846,43 @@ framework features to provide support for data modification, validation, and mor
|
|||||||
|
|
||||||
The final project folder structure should look like this:
|
The final project folder structure should look like this:
|
||||||
|
|
||||||
|
|
||||||
<aio-filetree>
|
<aio-filetree>
|
||||||
|
|
||||||
|
|
||||||
<aio-folder>
|
<aio-folder>
|
||||||
angular-forms
|
angular-forms
|
||||||
|
|
||||||
<aio-folder>
|
<aio-folder>
|
||||||
src
|
src
|
||||||
|
|
||||||
<aio-folder>
|
<aio-folder>
|
||||||
app
|
app
|
||||||
|
|
||||||
<aio-file>
|
<aio-file>
|
||||||
app.component.ts
|
app.component.ts
|
||||||
</aio-file>
|
</aio-file>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<aio-file>
|
<aio-file>
|
||||||
app.module.ts
|
app.module.ts
|
||||||
</aio-file>
|
</aio-file>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<aio-file>
|
<aio-file>
|
||||||
hero.ts
|
hero.ts
|
||||||
</aio-file>
|
</aio-file>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<aio-file>
|
<aio-file>
|
||||||
hero-form.component.html
|
hero-form.component.html
|
||||||
</aio-file>
|
</aio-file>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<aio-file>
|
<aio-file>
|
||||||
hero-form.component.ts
|
hero-form.component.ts
|
||||||
</aio-file>
|
</aio-file>
|
||||||
@ -832,16 +891,19 @@ The final project folder structure should look like this:
|
|||||||
</aio-folder>
|
</aio-folder>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<aio-file>
|
<aio-file>
|
||||||
main.ts
|
main.ts
|
||||||
</aio-file>
|
</aio-file>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<aio-file>
|
<aio-file>
|
||||||
tsconfig.json
|
tsconfig.json
|
||||||
</aio-file>
|
</aio-file>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<aio-file>
|
<aio-file>
|
||||||
index.html
|
index.html
|
||||||
</aio-file>
|
</aio-file>
|
||||||
@ -850,11 +912,13 @@ The final project folder structure should look like this:
|
|||||||
</aio-folder>
|
</aio-folder>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<aio-file>
|
<aio-file>
|
||||||
node_modules ...
|
node_modules ...
|
||||||
</aio-file>
|
</aio-file>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<aio-file>
|
<aio-file>
|
||||||
package.json
|
package.json
|
||||||
</aio-file>
|
</aio-file>
|
||||||
@ -868,43 +932,52 @@ The final project folder structure should look like this:
|
|||||||
Here’s the code for the final version of the application:
|
Here’s the code for the final version of the application:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-tabs>
|
<code-tabs>
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="hero-form.component.ts" path="forms/src/app/hero-form.component.ts" region="final">
|
<code-pane title="hero-form.component.ts" path="forms/src/app/hero-form.component.ts" region="final">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="hero-form.component.html" path="forms/src/app/hero-form.component.html" region="final">
|
<code-pane title="hero-form.component.html" path="forms/src/app/hero-form.component.html" region="final">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="hero.ts" path="forms/src/app/hero.ts">
|
<code-pane title="hero.ts" path="forms/src/app/hero.ts">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="app.module.ts" path="forms/src/app/app.module.ts">
|
<code-pane title="app.module.ts" path="forms/src/app/app.module.ts">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="app.component.ts" path="forms/src/app/app.component.ts">
|
<code-pane title="app.component.ts" path="forms/src/app/app.component.ts">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="main.ts" path="forms/src/main.ts">
|
<code-pane title="main.ts" path="forms/src/main.ts">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="index.html" path="forms/src/index.html">
|
<code-pane title="index.html" path="forms/src/index.html">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="forms.css" path="forms/src/forms.css">
|
<code-pane title="forms.css" path="forms/src/forms.css">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
|
@ -45,6 +45,7 @@ The `HeroesListComponent` holds and manages multiple instances of the `HeroTaxRe
|
|||||||
The following diagram represents the state of the this guide's three-level component tree when there are three instances of `HeroTaxReturnComponent`
|
The following diagram represents the state of the this guide's three-level component tree when there are three instances of `HeroTaxReturnComponent`
|
||||||
open simultaneously.
|
open simultaneously.
|
||||||
|
|
||||||
|
|
||||||
<figure class='image-display'>
|
<figure class='image-display'>
|
||||||
<img src="assets/images/devguide/dependency-injection/component-hierarchy.png" alt="injector tree" width="600"> </img>
|
<img src="assets/images/devguide/dependency-injection/component-hierarchy.png" alt="injector tree" width="600"> </img>
|
||||||
</figure>
|
</figure>
|
||||||
@ -100,6 +101,7 @@ 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:
|
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 path="hierarchical-dependency-injection/src/app/villains-list.component.ts" linenums="false" title="src/app/villains-list.component.ts (metadata)" region="metadata">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -128,6 +130,7 @@ Each tax return component has the following characteristics:
|
|||||||
* Can change a tax return without affecting a return in another component.
|
* 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.
|
* Has the ability to save the changes to its tax return or cancel them.
|
||||||
|
|
||||||
|
|
||||||
<figure class='image-display'>
|
<figure class='image-display'>
|
||||||
<img src="assets/images/devguide/dependency-injection/hid-heroes-anim.gif" width="400" alt="Heroes in action"> </img>
|
<img src="assets/images/devguide/dependency-injection/hid-heroes-anim.gif" width="400" alt="Heroes in action"> </img>
|
||||||
</figure>
|
</figure>
|
||||||
@ -142,6 +145,7 @@ 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.
|
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 path="hierarchical-dependency-injection/src/app/hero-tax-return.service.ts">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -149,6 +153,7 @@ It also delegates to the application-wide singleton `HeroService`, which it gets
|
|||||||
Here is the `HeroTaxReturnComponent` that makes use of it.
|
Here is the `HeroTaxReturnComponent` that makes use of it.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="hierarchical-dependency-injection/src/app/hero-tax-return.component.ts">
|
<code-example path="hierarchical-dependency-injection/src/app/hero-tax-return.component.ts">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -166,6 +171,7 @@ What a mess!
|
|||||||
Look closely at the metadata for the `HeroTaxReturnComponent`. Notice the `providers` property.
|
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 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>
|
</code-example>
|
||||||
@ -200,6 +206,7 @@ that have special capabilites suitable for whatever is going on in component (B)
|
|||||||
|
|
||||||
Component (B) is the parent of another component (C) that defines its own, even _more specialized_ provider for `CarService`.
|
Component (B) is the parent of another component (C) that defines its own, even _more specialized_ provider for `CarService`.
|
||||||
|
|
||||||
|
|
||||||
<figure class='image-display'>
|
<figure class='image-display'>
|
||||||
<img src="assets/images/devguide/dependency-injection/car-components.png" alt="car components" width="220"> </img>
|
<img src="assets/images/devguide/dependency-injection/car-components.png" alt="car components" width="220"> </img>
|
||||||
</figure>
|
</figure>
|
||||||
@ -210,6 +217,7 @@ When you resolve an instance of `Car` at the deepest component (C),
|
|||||||
its injector produces an instance of `Car` resolved by injector (C) with an `Engine` resolved by injector (B) and
|
its injector produces an instance of `Car` resolved by injector (C) with an `Engine` resolved by injector (B) and
|
||||||
`Tires` resolved by the root injector (A).
|
`Tires` resolved by the root injector (A).
|
||||||
|
|
||||||
|
|
||||||
<figure class='image-display'>
|
<figure class='image-display'>
|
||||||
<img src="assets/images/devguide/dependency-injection/injector-tree.png" alt="car injector tree" width="600"> </img>
|
<img src="assets/images/devguide/dependency-injection/injector-tree.png" alt="car injector tree" width="600"> </img>
|
||||||
</figure>
|
</figure>
|
||||||
|
@ -85,6 +85,7 @@ After translation, the compiler removes it.
|
|||||||
In the accompanying sample, an `<h1>` tag displays a simple English language greeting
|
In the accompanying sample, an `<h1>` tag displays a simple English language greeting
|
||||||
that you translate into Spanish:
|
that you translate into Spanish:
|
||||||
|
|
||||||
|
|
||||||
<code-example path="cb-i18n/src/app/app.component.1.html" region="greeting" linenums="false">
|
<code-example path="cb-i18n/src/app/app.component.1.html" region="greeting" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -92,6 +93,7 @@ that you translate into Spanish:
|
|||||||
Add the `i18n` attribute to the tag to mark it for translation.
|
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 path="cb-i18n/src/app/app.component.1.html" region="i18n-attribute" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -103,6 +105,7 @@ need a description of the message.
|
|||||||
Assign a description to the i18n attribute:
|
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 path="cb-i18n/src/app/app.component.1.html" region="i18n-attribute-desc" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -114,6 +117,7 @@ In front of the description, add some contextual meaning to the assigned string,
|
|||||||
separating it from the description with the `|` character (`<meaning>|<description>`):
|
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 path="cb-i18n/src/app/app.component.html" region="i18n-attribute-meaning" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -134,6 +138,7 @@ Here are two techniques to try.
|
|||||||
(1) Wrap the text in an `<ng-container>` element. The `<ng-container>` is never renderered:
|
(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 path="cb-i18n/src/app/app.component.html" region="i18n-ng-container" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -141,6 +146,7 @@ Here are two techniques to try.
|
|||||||
(2) Wrap the text in a pair of HTML comments:
|
(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 path="cb-i18n/src/app/app.component.html" region="i18n-with-comment" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -153,6 +159,7 @@ 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:
|
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 path="cb-i18n/src/app/app.component.1.html" region="i18n-title" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -164,6 +171,7 @@ name of the attribute to translate.
|
|||||||
To translate the `title` on the `img` tag from the previous example, write:
|
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 path="cb-i18n/src/app/app.component.html" region="i18n-title-translate" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -184,6 +192,7 @@ 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:
|
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 path="cb-i18n/src/app/app.component.html" region="i18n-plural" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -240,6 +249,7 @@ property, which outputs either an "m" or an "f".
|
|||||||
The message maps those values to the appropriate translation:
|
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 path="cb-i18n/src/app/app.component.html" region="i18n-select" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -256,6 +266,7 @@ into a translation source file in an industry standard format.
|
|||||||
This is an Angular CLI tool in the `@angular/compiler-cli` npm package.
|
This is an Angular CLI tool in the `@angular/compiler-cli` npm package.
|
||||||
If you haven't already installed the CLI and its `platform-server` peer dependency, do so now:
|
If you haven't already installed the CLI and its `platform-server` peer dependency, do so now:
|
||||||
|
|
||||||
|
|
||||||
<code-example language="sh" class="code-shell">
|
<code-example language="sh" class="code-shell">
|
||||||
npm install @angular/compiler-cli @angular/platform-server --save
|
npm install @angular/compiler-cli @angular/platform-server --save
|
||||||
|
|
||||||
@ -263,6 +274,7 @@ If you haven't already installed the CLI and its `platform-server` peer dependen
|
|||||||
|
|
||||||
Open a terminal window at the root of the application project and enter the `ng-xi18n` command:
|
Open a terminal window at the root of the application project and enter the `ng-xi18n` command:
|
||||||
|
|
||||||
|
|
||||||
<code-example language="sh" class="code-shell">
|
<code-example language="sh" class="code-shell">
|
||||||
./node_modules/.bin/ng-xi18n
|
./node_modules/.bin/ng-xi18n
|
||||||
|
|
||||||
@ -288,6 +300,7 @@ You can generate a file named **`messages.xmb`** in the
|
|||||||
<a href="http://cldr.unicode.org/development/development-process/design-proposals/xmb" target="_blank">XML Message Bundle (XMB)</a> format
|
<a href="http://cldr.unicode.org/development/development-process/design-proposals/xmb" target="_blank">XML Message Bundle (XMB)</a> format
|
||||||
by adding the `--i18nFormat=xmb` flag.
|
by adding the `--i18nFormat=xmb` flag.
|
||||||
|
|
||||||
|
|
||||||
<code-example language="sh" class="code-shell">
|
<code-example language="sh" class="code-shell">
|
||||||
./node_modules/.bin/ng-xi18n --i18nFormat=xmb
|
./node_modules/.bin/ng-xi18n --i18nFormat=xmb
|
||||||
|
|
||||||
@ -302,6 +315,7 @@ You may have to specify additional options.
|
|||||||
For example, if the `tsconfig.json` TypeScript configuration
|
For example, if the `tsconfig.json` TypeScript configuration
|
||||||
file is located somewhere other than in the root folder,
|
file is located somewhere other than in the root folder,
|
||||||
you must identify the path to it with the `-p` option:
|
you must identify the path to it with the `-p` option:
|
||||||
|
|
||||||
<code-example language="sh" class="code-shell">
|
<code-example language="sh" class="code-shell">
|
||||||
./node_modules/.bin/ng-xi18n -p path/to/tsconfig.json
|
./node_modules/.bin/ng-xi18n -p path/to/tsconfig.json
|
||||||
./node_modules/.bin/ng-xi18n --i18nFormat=xmb -p path/to/tsconfig.json
|
./node_modules/.bin/ng-xi18n --i18nFormat=xmb -p path/to/tsconfig.json
|
||||||
@ -316,6 +330,7 @@ you must identify the path to it with the `-p` option:
|
|||||||
|
|
||||||
Consider adding a convenience shortcut to the `scripts` section of the `package.json`
|
Consider adding a convenience shortcut to the `scripts` section of the `package.json`
|
||||||
to make the command easier to remember and run:
|
to make the command easier to remember and run:
|
||||||
|
|
||||||
<code-example format='.' language='sh'>
|
<code-example format='.' language='sh'>
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"i18n": "ng-xi18n",
|
"i18n": "ng-xi18n",
|
||||||
@ -324,6 +339,7 @@ to make the command easier to remember and run:
|
|||||||
</code-example>
|
</code-example>
|
||||||
|
|
||||||
Now you can issue command variations such as these:
|
Now you can issue command variations such as these:
|
||||||
|
|
||||||
<code-example language="sh" class="code-shell">
|
<code-example language="sh" class="code-shell">
|
||||||
npm run i18n
|
npm run i18n
|
||||||
npm run i18n -- -p path/to/tsconfig.json
|
npm run i18n -- -p path/to/tsconfig.json
|
||||||
@ -378,6 +394,7 @@ 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:
|
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 path="cb-i18n/src/locale/messages.es.xlf.html" region="translated-hello" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -387,6 +404,7 @@ This XML element represents the translation of the `<h1>` greeting tag you marke
|
|||||||
Using the _source_, _description_, and _meaning_ elements to guide your translation,
|
Using the _source_, _description_, and _meaning_ elements to guide your translation,
|
||||||
replace the `<target/>` tag with the Spanish greeting:
|
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 path="cb-i18n/src/locale/messages.es.xlf.html" region="translated-hello" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -406,6 +424,7 @@ See the **[translation file maintenance discussion](guide/i18n#maintenance)**.
|
|||||||
Translate the other text nodes the same way:
|
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 path="cb-i18n/src/locale/messages.es.xlf.html" region="translated-other-nodes" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -427,6 +446,7 @@ 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:
|
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 path="cb-i18n/src/locale/messages.es.xlf.html" region="translated-plural" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -435,6 +455,7 @@ 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:
|
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 path="cb-i18n/src/app/app.component.html" region="i18n-select" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -446,6 +467,7 @@ In place of the `select` is a placeholder, `<x id="ICU">`, that represents the `
|
|||||||
Translate the text and leave the placeholder where it is.
|
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 path="cb-i18n/src/locale/messages.es.xlf.html" region="translate-select-1" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -453,6 +475,7 @@ 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.
|
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 path="cb-i18n/src/locale/messages.es.xlf.html" region="translate-select-2" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -460,11 +483,13 @@ The second translation unit, immediately below the first one, contains the `sele
|
|||||||
Here they are together, after translation:
|
Here they are together, after translation:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="cb-i18n/src/locale/messages.es.xlf.html" region="translated-select" linenums="false">
|
<code-example path="cb-i18n/src/locale/messages.es.xlf.html" region="translated-select" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<div class='l-main-content'>
|
<div class='l-main-content'>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
@ -472,6 +497,7 @@ Here they are together, after translation:
|
|||||||
The entire template translation is complete. It's
|
The entire template translation is complete. It's
|
||||||
time to incorporate that translation into the application.
|
time to incorporate that translation into the application.
|
||||||
|
|
||||||
|
|
||||||
<div id='app-pre-translation'>
|
<div id='app-pre-translation'>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
@ -481,28 +507,34 @@ time to incorporate that translation into the application.
|
|||||||
When the previous steps finish, the sample app _and_ its translation file are as follows:
|
When the previous steps finish, the sample app _and_ its translation file are as follows:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-tabs>
|
<code-tabs>
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="src/app/app.component.html" path="cb-i18n/src/app/app.component.html">
|
<code-pane title="src/app/app.component.html" path="cb-i18n/src/app/app.component.html">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="src/app/app.component.ts" path="cb-i18n/src/app/app.component.ts">
|
<code-pane title="src/app/app.component.ts" path="cb-i18n/src/app/app.component.ts">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="src/app/app.module.ts" path="cb-i18n/src/app/app.module.ts">
|
<code-pane title="src/app/app.module.ts" path="cb-i18n/src/app/app.module.ts">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="src/main.ts" path="cb-i18n/src/main.1.ts">
|
<code-pane title="src/main.ts" path="cb-i18n/src/main.1.ts">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="src/locale/messages.es.xlf" path="cb-i18n/src/locale/messages.es.xlf.html">
|
<code-pane title="src/locale/messages.es.xlf" path="cb-i18n/src/locale/messages.es.xlf.html">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
@ -548,6 +580,7 @@ Translation with the JIT compiler is a dynamic process of:
|
|||||||
|
|
||||||
Open `index.html` and revise the launch script as follows:
|
Open `index.html` and revise the launch script as follows:
|
||||||
|
|
||||||
|
|
||||||
<code-example path="cb-i18n/src/index.html" region="i18n" linenums="false">
|
<code-example path="cb-i18n/src/index.html" region="i18n" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -567,6 +600,7 @@ 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.
|
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:
|
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 path="cb-i18n/src/systemjs-text-plugin.js" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -584,6 +618,7 @@ The `getTranslationProviders` function in the following `src/app/i18n-providers.
|
|||||||
creates those providers based on the user's _locale_
|
creates those providers based on the user's _locale_
|
||||||
and the corresponding translation file:
|
and the corresponding translation file:
|
||||||
|
|
||||||
|
|
||||||
<code-example path="cb-i18n/src/app/i18n-providers.ts">
|
<code-example path="cb-i18n/src/app/i18n-providers.ts">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -613,6 +648,7 @@ You'll create an _options_ object with the translation providers from `getTransl
|
|||||||
and pass it to `bootstrapModule`.
|
and pass it to `bootstrapModule`.
|
||||||
Open the `src/main.ts` and modify the bootstrap code as follows:
|
Open the `src/main.ts` and modify the bootstrap code as follows:
|
||||||
|
|
||||||
|
|
||||||
<code-example path="cb-i18n/src/main.ts" linenums="false">
|
<code-example path="cb-i18n/src/main.ts" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -659,6 +695,7 @@ Tell AOT how to translate by adding three options to the `ngc` command:
|
|||||||
* `--i18nFormat`: the format of the localization file
|
* `--i18nFormat`: the format of the localization file
|
||||||
|
|
||||||
For this sample, the Spanish language command would be
|
For this sample, the Spanish language command would be
|
||||||
|
|
||||||
<code-example language="sh" class="code-shell">
|
<code-example language="sh" class="code-shell">
|
||||||
./node_modules/.bin/ngc --i18nFile=./locale/messages.es.xlf --locale=es --i18nFormat=xlf
|
./node_modules/.bin/ngc --i18nFile=./locale/messages.es.xlf --locale=es --i18nFormat=xlf
|
||||||
|
|
||||||
@ -669,6 +706,7 @@ For this sample, the Spanish language command would be
|
|||||||
~~~ {.l-sub-section}
|
~~~ {.l-sub-section}
|
||||||
|
|
||||||
Windows users may have to quote the command:
|
Windows users may have to quote the command:
|
||||||
|
|
||||||
<code-example language="sh" class="code-shell">
|
<code-example language="sh" class="code-shell">
|
||||||
"./node_modules/.bin/ngc" --i18nFile=./locale/messages.es.xlf --locale=es --i18nFormat=xlf
|
"./node_modules/.bin/ngc" --i18nFile=./locale/messages.es.xlf --locale=es --i18nFormat=xlf
|
||||||
|
|
||||||
|
@ -15,25 +15,31 @@ The documentation is divided into major thematic sections, each
|
|||||||
a collection of pages devoted to that theme.
|
a collection of pages devoted to that theme.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<table width="100%">
|
<table width="100%">
|
||||||
|
|
||||||
|
|
||||||
<col width="15%">
|
<col width="15%">
|
||||||
|
|
||||||
</col>
|
</col>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<col>
|
<col>
|
||||||
|
|
||||||
</col>
|
</col>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<tr style=top>
|
<tr style=top>
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
<b><a href="../quickstart.html">QuickStart</a></b>
|
<b><a href="../quickstart.html">QuickStart</a></b>
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
A first taste of Angular<span if-docs="ts"> with zero installation.
|
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>.
|
Run "Hello World" in an online code editor and start playing with live code</span>.
|
||||||
@ -43,13 +49,16 @@ a collection of pages devoted to that theme.
|
|||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<tr style=top>
|
<tr style=top>
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
<b>Guide</b>
|
<b>Guide</b>
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
Learn the Angular basics (you're already here!) like the setup for local development,
|
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,
|
displaying data and accepting user input, injecting application services into components,
|
||||||
@ -60,13 +69,16 @@ a collection of pages devoted to that theme.
|
|||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<tr style=top>
|
<tr style=top>
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
<b><a href="../api/">API Reference</a></b>
|
<b><a href="../api/">API Reference</a></b>
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
Authoritative details about each of the Angular libraries.
|
Authoritative details about each of the Angular libraries.
|
||||||
</td>
|
</td>
|
||||||
@ -75,13 +87,16 @@ a collection of pages devoted to that theme.
|
|||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<tr style=top>
|
<tr style=top>
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
<b><a href="../tutorial/">Tutorial</a></b>
|
<b><a href="../tutorial/">Tutorial</a></b>
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
A step-by-step, immersive approach to learning Angular that
|
A step-by-step, immersive approach to learning Angular that
|
||||||
introduces the major features of Angular in an application context.
|
introduces the major features of Angular in an application context.
|
||||||
@ -91,13 +106,16 @@ a collection of pages devoted to that theme.
|
|||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<tr style=top>
|
<tr style=top>
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
<b><a href=" ">Advanced</a></b>
|
<b><a href=" ">Advanced</a></b>
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
In-depth analysis of Angular features and development practices.
|
In-depth analysis of Angular features and development practices.
|
||||||
</td>
|
</td>
|
||||||
@ -106,13 +124,16 @@ a collection of pages devoted to that theme.
|
|||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<tr style=top if-docs="ts">
|
<tr style=top if-docs="ts">
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
<b><a href="../cookbook/">Cookbook</a></b>
|
<b><a href="../cookbook/">Cookbook</a></b>
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
Recipes for specific application challenges, mostly code snippets with a minimum of exposition.
|
Recipes for specific application challenges, mostly code snippets with a minimum of exposition.
|
||||||
|
|
||||||
|
@ -7,6 +7,7 @@ A suggested path through the documentation for Angular newcomers.
|
|||||||
@description
|
@description
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<figure>
|
<figure>
|
||||||
<img src="assets/images/devguide/intro/people.png" width="200px" height="152px" alt="Us" align="left" style="margin-left:-40px;margin-right:10px"> </img>
|
<img src="assets/images/devguide/intro/people.png" width="200px" height="152px" alt="Us" align="left" style="margin-left:-40px;margin-right:10px"> </img>
|
||||||
</figure>
|
</figure>
|
||||||
|
@ -7,6 +7,7 @@ Angular calls lifecycle hook methods on directives and components as it creates,
|
|||||||
@description
|
@description
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<figure>
|
<figure>
|
||||||
<img src="assets/images/devguide/lifecycle-hooks/hooks-in-sequence.png" alt="Us" align="left" style="width:200px; margin-left:-40px;margin-right:30px"> </img>
|
<img src="assets/images/devguide/lifecycle-hooks/hooks-in-sequence.png" alt="Us" align="left" style="width:200px; margin-left:-40px;margin-right:30px"> </img>
|
||||||
</figure>
|
</figure>
|
||||||
@ -35,6 +36,7 @@ Each interface has a single hook method whose name is the interface name prefixe
|
|||||||
For example, the `OnInit` interface has a hook method named `ngOnInit()`
|
For example, the `OnInit` interface has a hook method named `ngOnInit()`
|
||||||
that Angular calls shortly after creating the component:
|
that Angular calls shortly after creating the component:
|
||||||
|
|
||||||
|
|
||||||
<code-example path="lifecycle-hooks/src/app/peek-a-boo.component.ts" region="ngOnInit" linenums="false">
|
<code-example path="lifecycle-hooks/src/app/peek-a-boo.component.ts" region="ngOnInit" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -48,25 +50,31 @@ Angular only calls a directive/component hook method *if it is defined*.
|
|||||||
## Lifecycle sequence
|
## Lifecycle sequence
|
||||||
*After* creating a component/directive by calling its constructor, Angular
|
*After* creating a component/directive by calling its constructor, Angular
|
||||||
calls the lifecycle hook methods in the following sequence at specific moments:
|
calls the lifecycle hook methods in the following sequence at specific moments:
|
||||||
|
|
||||||
<table width="100%">
|
<table width="100%">
|
||||||
|
|
||||||
|
|
||||||
<col width="20%">
|
<col width="20%">
|
||||||
|
|
||||||
</col>
|
</col>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<col width="80%">
|
<col width="80%">
|
||||||
|
|
||||||
</col>
|
</col>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
|
|
||||||
|
|
||||||
<th>
|
<th>
|
||||||
Hook
|
Hook
|
||||||
</th>
|
</th>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<th>
|
<th>
|
||||||
Purpose and Timing
|
Purpose and Timing
|
||||||
</th>
|
</th>
|
||||||
@ -75,13 +83,16 @@ calls the lifecycle hook methods in the following sequence at specific moments:
|
|||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<tr style=top>
|
<tr style=top>
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
<code>ngOnChanges()</code>
|
<code>ngOnChanges()</code>
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
Respond when Angular (re)sets data-bound input properties.
|
Respond when Angular (re)sets data-bound input properties.
|
||||||
The method receives a `SimpleChanges` object of current and previous property values.
|
The method receives a `SimpleChanges` object of current and previous property values.
|
||||||
@ -94,13 +105,16 @@ calls the lifecycle hook methods in the following sequence at specific moments:
|
|||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<tr style=top>
|
<tr style=top>
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
<code>ngOnInit()</code>
|
<code>ngOnInit()</code>
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
Initialize the directive/component after Angular first displays the data-bound properties
|
Initialize the directive/component after Angular first displays the data-bound properties
|
||||||
and sets the directive/component's input properties.
|
and sets the directive/component's input properties.
|
||||||
@ -113,13 +127,16 @@ calls the lifecycle hook methods in the following sequence at specific moments:
|
|||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<tr style=top>
|
<tr style=top>
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
<code>ngDoCheck()</code>
|
<code>ngDoCheck()</code>
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
Detect and act upon changes that Angular can't or won't detect on its own.
|
Detect and act upon changes that Angular can't or won't detect on its own.
|
||||||
|
|
||||||
@ -131,13 +148,16 @@ calls the lifecycle hook methods in the following sequence at specific moments:
|
|||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<tr style=top>
|
<tr style=top>
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
<code>ngAfterContentInit()</code>
|
<code>ngAfterContentInit()</code>
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
Respond after Angular projects external content into the component's view.
|
Respond after Angular projects external content into the component's view.
|
||||||
|
|
||||||
@ -151,13 +171,16 @@ calls the lifecycle hook methods in the following sequence at specific moments:
|
|||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<tr style=top>
|
<tr style=top>
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
<code>ngAfterContentChecked()</code>
|
<code>ngAfterContentChecked()</code>
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
Respond after Angular checks the content projected into the component.
|
Respond after Angular checks the content projected into the component.
|
||||||
|
|
||||||
@ -171,13 +194,16 @@ calls the lifecycle hook methods in the following sequence at specific moments:
|
|||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<tr style=top>
|
<tr style=top>
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
<code>ngAfterViewInit()</code>
|
<code>ngAfterViewInit()</code>
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
Respond after Angular initializes the component's views and child views.
|
Respond after Angular initializes the component's views and child views.
|
||||||
|
|
||||||
@ -191,13 +217,16 @@ calls the lifecycle hook methods in the following sequence at specific moments:
|
|||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<tr style=top>
|
<tr style=top>
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
<code>ngAfterViewChecked()</code>
|
<code>ngAfterViewChecked()</code>
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
Respond after Angular checks the component's views and child views.
|
Respond after Angular checks the component's views and child views.
|
||||||
|
|
||||||
@ -211,13 +240,16 @@ calls the lifecycle hook methods in the following sequence at specific moments:
|
|||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<tr style=top>
|
<tr style=top>
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
<code>ngOnDestroy</code>
|
<code>ngOnDestroy</code>
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
Cleanup just before Angular destroys the directive/component.
|
Cleanup just before Angular destroys the directive/component.
|
||||||
Unsubscribe Observables and detach event handlers to avoid memory leaks.
|
Unsubscribe Observables and detach event handlers to avoid memory leaks.
|
||||||
@ -254,25 +286,31 @@ a *child* component that illustrates one or more of the lifecycle hook methods.
|
|||||||
|
|
||||||
Here's a brief description of each exercise:
|
Here's a brief description of each exercise:
|
||||||
|
|
||||||
|
|
||||||
<table width="100%">
|
<table width="100%">
|
||||||
|
|
||||||
|
|
||||||
<col width="20%">
|
<col width="20%">
|
||||||
|
|
||||||
</col>
|
</col>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<col width="80%">
|
<col width="80%">
|
||||||
|
|
||||||
</col>
|
</col>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
|
|
||||||
|
|
||||||
<th>
|
<th>
|
||||||
Component
|
Component
|
||||||
</th>
|
</th>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<th>
|
<th>
|
||||||
Description
|
Description
|
||||||
</th>
|
</th>
|
||||||
@ -281,13 +319,16 @@ Here's a brief description of each exercise:
|
|||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<tr style=top>
|
<tr style=top>
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
<a href="#peek-a-boo">Peek-a-boo</a>
|
<a href="#peek-a-boo">Peek-a-boo</a>
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
Demonstrates every lifecycle hook.
|
Demonstrates every lifecycle hook.
|
||||||
Each hook method writes to the on-screen log.
|
Each hook method writes to the on-screen log.
|
||||||
@ -297,13 +338,16 @@ Here's a brief description of each exercise:
|
|||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<tr style=top>
|
<tr style=top>
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
<a href="#spy">Spy</a>
|
<a href="#spy">Spy</a>
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
Directives have lifecycle hooks too.
|
Directives have lifecycle hooks too.
|
||||||
A `SpyDirective` can log when the element it spies upon is
|
A `SpyDirective` can log when the element it spies upon is
|
||||||
@ -317,13 +361,16 @@ Here's a brief description of each exercise:
|
|||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<tr style=top>
|
<tr style=top>
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
<a href="#onchanges">OnChanges</a>
|
<a href="#onchanges">OnChanges</a>
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
See how Angular calls the `ngOnChanges()` hook with a `changes` object
|
See how Angular calls the `ngOnChanges()` hook with a `changes` object
|
||||||
every time one of the component input properties changes.
|
every time one of the component input properties changes.
|
||||||
@ -334,13 +381,16 @@ Here's a brief description of each exercise:
|
|||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<tr style=top>
|
<tr style=top>
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
<a href="#docheck">DoCheck</a>
|
<a href="#docheck">DoCheck</a>
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
Implements an `ngDoCheck()` method with custom change detection.
|
Implements an `ngDoCheck()` method with custom change detection.
|
||||||
See how often Angular calls this hook and watch it post changes to a log.
|
See how often Angular calls this hook and watch it post changes to a log.
|
||||||
@ -350,13 +400,16 @@ Here's a brief description of each exercise:
|
|||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<tr style=top>
|
<tr style=top>
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
<a href="#afterview">AfterView</a>
|
<a href="#afterview">AfterView</a>
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
Shows what Angular means by a *view*.
|
Shows what Angular means by a *view*.
|
||||||
Demonstrates the `ngAfterViewInit` and `ngAfterViewChecked` hooks.
|
Demonstrates the `ngAfterViewInit` and `ngAfterViewChecked` hooks.
|
||||||
@ -366,13 +419,16 @@ Here's a brief description of each exercise:
|
|||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<tr style=top>
|
<tr style=top>
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
<a href="#aftercontent">AfterContent</a>
|
<a href="#aftercontent">AfterContent</a>
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
Shows how to project external content into a component and
|
Shows how to project external content into a component and
|
||||||
how to distinguish projected content from a component's view children.
|
how to distinguish projected content from a component's view children.
|
||||||
@ -383,13 +439,16 @@ Here's a brief description of each exercise:
|
|||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<tr style=top>
|
<tr style=top>
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
Counter
|
Counter
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
Demonstrates a combination of a component and a directive
|
Demonstrates a combination of a component and a directive
|
||||||
each with its own hooks.
|
each with its own hooks.
|
||||||
@ -419,6 +478,7 @@ You would rarely, if ever, implement all of the interfaces like this.
|
|||||||
The peek-a-boo exists to show how Angular calls the hooks in the expected order.
|
The peek-a-boo exists to show how Angular calls the hooks in the expected order.
|
||||||
|
|
||||||
This snapshot reflects the state of the log after the user clicked the *Create...* button and then the *Destroy...* button.
|
This snapshot reflects the state of the log after the user clicked the *Create...* button and then the *Destroy...* button.
|
||||||
|
|
||||||
<figure class='image-display'>
|
<figure class='image-display'>
|
||||||
<img src="assets/images/devguide/lifecycle-hooks/peek-a-boo.png" alt="Peek-a-boo"> </img>
|
<img src="assets/images/devguide/lifecycle-hooks/peek-a-boo.png" alt="Peek-a-boo"> </img>
|
||||||
</figure>
|
</figure>
|
||||||
@ -471,6 +531,7 @@ The sneaky spy directive is simple, consisting almost entirely of `ngOnInit()` a
|
|||||||
that log messages to the parent via an injected `LoggerService`.
|
that log messages to the parent via an injected `LoggerService`.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="lifecycle-hooks/src/app/spy.directive.ts" region="spy-directive" linenums="false">
|
<code-example path="lifecycle-hooks/src/app/spy.directive.ts" region="spy-directive" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -479,6 +540,7 @@ You can apply the spy to any native or component element and it'll be initialize
|
|||||||
at the same time as that element.
|
at the same time as that element.
|
||||||
Here it is attached to the repeated hero `<div>`:
|
Here it is attached to the repeated hero `<div>`:
|
||||||
|
|
||||||
|
|
||||||
<code-example path="lifecycle-hooks/src/app/spy.component.html" region="template" linenums="false">
|
<code-example path="lifecycle-hooks/src/app/spy.component.html" region="template" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -486,6 +548,7 @@ Here it is attached to the repeated hero `<div>`:
|
|||||||
Each spy's birth and death marks the birth and death of the attached hero `<div>`
|
Each spy's birth and death marks the birth and death of the attached hero `<div>`
|
||||||
with an entry in the *Hook Log* as seen here:
|
with an entry in the *Hook Log* as seen here:
|
||||||
|
|
||||||
|
|
||||||
<figure class='image-display'>
|
<figure class='image-display'>
|
||||||
<img src='assets/images/devguide/lifecycle-hooks/spy-directive.gif' alt="Spy Directive"> </img>
|
<img src='assets/images/devguide/lifecycle-hooks/spy-directive.gif' alt="Spy Directive"> </img>
|
||||||
</figure>
|
</figure>
|
||||||
@ -562,6 +625,7 @@ You risk memory leaks if you neglect to do so.
|
|||||||
Angular calls its `ngOnChanges()` method whenever it detects changes to ***input properties*** of the component (or directive).
|
Angular calls its `ngOnChanges()` method whenever it detects changes to ***input properties*** of the component (or directive).
|
||||||
This example monitors the `OnChanges` hook.
|
This example monitors the `OnChanges` hook.
|
||||||
|
|
||||||
|
|
||||||
<code-example path="lifecycle-hooks/src/app/on-changes.component.ts" region="ng-on-changes" linenums="false">
|
<code-example path="lifecycle-hooks/src/app/on-changes.component.ts" region="ng-on-changes" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -572,6 +636,7 @@ This hook iterates over the changed properties and logs them.
|
|||||||
|
|
||||||
The example component, `OnChangesComponent`, has two input properties: `hero` and `power`.
|
The example component, `OnChangesComponent`, has two input properties: `hero` and `power`.
|
||||||
|
|
||||||
|
|
||||||
<code-example path="lifecycle-hooks/src/app/on-changes.component.ts" region="inputs" linenums="false">
|
<code-example path="lifecycle-hooks/src/app/on-changes.component.ts" region="inputs" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -579,12 +644,14 @@ The example component, `OnChangesComponent`, has two input properties: `hero` an
|
|||||||
The host `OnChangesParentComponent` binds to them like this:
|
The host `OnChangesParentComponent` binds to them like this:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="lifecycle-hooks/src/app/on-changes-parent.component.html" region="on-changes">
|
<code-example path="lifecycle-hooks/src/app/on-changes-parent.component.html" region="on-changes">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
|
|
||||||
Here's the sample in action as the user makes changes.
|
Here's the sample in action as the user makes changes.
|
||||||
|
|
||||||
|
|
||||||
<figure class='image-display'>
|
<figure class='image-display'>
|
||||||
<img src='assets/images/devguide/lifecycle-hooks/on-changes-anim.gif' alt="OnChanges"> </img>
|
<img src='assets/images/devguide/lifecycle-hooks/on-changes-anim.gif' alt="OnChanges"> </img>
|
||||||
</figure>
|
</figure>
|
||||||
@ -612,6 +679,7 @@ Use this method to detect a change that Angular overlooked.
|
|||||||
|
|
||||||
The *DoCheck* sample extends the *OnChanges* sample with the following `ngDoCheck()` hook:
|
The *DoCheck* sample extends the *OnChanges* sample with the following `ngDoCheck()` hook:
|
||||||
|
|
||||||
|
|
||||||
<code-example path="lifecycle-hooks/src/app/do-check.component.ts" region="ng-do-check" linenums="false">
|
<code-example path="lifecycle-hooks/src/app/do-check.component.ts" region="ng-do-check" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -620,6 +688,7 @@ This code inspects certain _values of interest_, capturing and comparing their c
|
|||||||
It writes a special message to the log when there are no substantive changes to the `hero` or the `power`
|
It writes a special message to the log when there are no substantive changes to the `hero` or the `power`
|
||||||
so you can see how often `DoCheck` is called. The results are illuminating:
|
so you can see how often `DoCheck` is called. The results are illuminating:
|
||||||
|
|
||||||
|
|
||||||
<figure class='image-display'>
|
<figure class='image-display'>
|
||||||
<img src='assets/images/devguide/lifecycle-hooks/do-check-anim.gif' alt="DoCheck"> </img>
|
<img src='assets/images/devguide/lifecycle-hooks/do-check-anim.gif' alt="DoCheck"> </img>
|
||||||
</figure>
|
</figure>
|
||||||
@ -643,12 +712,14 @@ The *AfterView* sample explores the `AfterViewInit()` and `AfterViewChecked()` h
|
|||||||
|
|
||||||
Here's a child view that displays a hero's name in an `<input>`:
|
Here's a child view that displays a hero's name in an `<input>`:
|
||||||
|
|
||||||
|
|
||||||
<code-example path="lifecycle-hooks/src/app/after-view.component.ts" region="child-view" linenums="false">
|
<code-example path="lifecycle-hooks/src/app/after-view.component.ts" region="child-view" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
|
|
||||||
The `AfterViewComponent` displays this child view *within its template*:
|
The `AfterViewComponent` displays this child view *within its template*:
|
||||||
|
|
||||||
|
|
||||||
<code-example path="lifecycle-hooks/src/app/after-view.component.ts" region="template" linenums="false">
|
<code-example path="lifecycle-hooks/src/app/after-view.component.ts" region="template" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -658,6 +729,7 @@ which can only be reached by querying for the child view via the property decora
|
|||||||
[@ViewChild](api/core/index/ViewChild-decorator).
|
[@ViewChild](api/core/index/ViewChild-decorator).
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="lifecycle-hooks/src/app/after-view.component.ts" region="hooks" linenums="false">
|
<code-example path="lifecycle-hooks/src/app/after-view.component.ts" region="hooks" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -669,6 +741,7 @@ which can only be reached by querying for the child view via the property decora
|
|||||||
The `doSomething()` method updates the screen when the hero name exceeds 10 characters.
|
The `doSomething()` method updates the screen when the hero name exceeds 10 characters.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="lifecycle-hooks/src/app/after-view.component.ts" region="do-something" linenums="false">
|
<code-example path="lifecycle-hooks/src/app/after-view.component.ts" region="do-something" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -682,6 +755,7 @@ Angular throws an error if the hook updates the component's data-bound `comment`
|
|||||||
The `LoggerService.tick_then()` postpones the log update
|
The `LoggerService.tick_then()` postpones the log update
|
||||||
for one turn of the browser's JavaScript cycle and that's just long enough.
|
for one turn of the browser's JavaScript cycle and that's just long enough.
|
||||||
Here's *AfterView* in action:
|
Here's *AfterView* in action:
|
||||||
|
|
||||||
<figure class='image-display'>
|
<figure class='image-display'>
|
||||||
<img src='assets/images/devguide/lifecycle-hooks/after-view-anim.gif' alt="AfterView"> </img>
|
<img src='assets/images/devguide/lifecycle-hooks/after-view-anim.gif' alt="AfterView"> </img>
|
||||||
</figure>
|
</figure>
|
||||||
@ -714,6 +788,7 @@ Consider this variation on the [previous _AfterView_](guide/lifecycle-hooks#afte
|
|||||||
This time, instead of including the child view within the template, it imports the content from
|
This time, instead of including the child view within the template, it imports the content from
|
||||||
the `AfterContentComponent`'s parent. Here's the parent's template:
|
the `AfterContentComponent`'s parent. Here's the parent's template:
|
||||||
|
|
||||||
|
|
||||||
<code-example path="lifecycle-hooks/src/app/after-content.component.ts" region="parent-template" linenums="false">
|
<code-example path="lifecycle-hooks/src/app/after-content.component.ts" region="parent-template" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -724,6 +799,7 @@ into the component*.
|
|||||||
|
|
||||||
Now look at the component's template:
|
Now look at the component's template:
|
||||||
|
|
||||||
|
|
||||||
<code-example path="lifecycle-hooks/src/app/after-content.component.ts" region="template" linenums="false">
|
<code-example path="lifecycle-hooks/src/app/after-content.component.ts" region="template" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -731,6 +807,7 @@ Now look at the component's template:
|
|||||||
The `<ng-content>` tag is a *placeholder* for the external content.
|
The `<ng-content>` tag is a *placeholder* for the external content.
|
||||||
It tells Angular where to insert that content.
|
It tells Angular where to insert that content.
|
||||||
In this case, the projected content is the `<my-child>` from the parent.
|
In this case, the projected content is the `<my-child>` from the parent.
|
||||||
|
|
||||||
<figure class='image-display'>
|
<figure class='image-display'>
|
||||||
<img src='assets/images/devguide/lifecycle-hooks/projected-child-view.png' width="230" alt="Projected Content"> </img>
|
<img src='assets/images/devguide/lifecycle-hooks/projected-child-view.png' width="230" alt="Projected Content"> </img>
|
||||||
</figure>
|
</figure>
|
||||||
@ -763,6 +840,7 @@ which can only be reached by querying for them via the property decorated with
|
|||||||
[@ContentChild](api/core/index/ContentChild-decorator).
|
[@ContentChild](api/core/index/ContentChild-decorator).
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="lifecycle-hooks/src/app/after-content.component.ts" region="hooks" linenums="false">
|
<code-example path="lifecycle-hooks/src/app/after-content.component.ts" region="hooks" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
@description
|
@description
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
h4 {font-size: 17px !important; text-transform: none !important;}
|
h4 {font-size: 17px !important; text-transform: none !important;}
|
||||||
.syntax { font-family: Consolas, 'Lucida Sans', Courier, sans-serif; color: black; font-size: 85%; }
|
.syntax { font-family: Consolas, 'Lucida Sans', Courier, sans-serif; color: black; font-size: 85%; }
|
||||||
|
@ -63,6 +63,7 @@ General
|
|||||||
* [What is the Angular compiler?](guide/ngmodule-faq#q-angular-compiler)
|
* [What is the Angular compiler?](guide/ngmodule-faq#q-angular-compiler)
|
||||||
* [Can you summarize the NgModule API?](guide/ngmodule-faq#q-ngmodule-api)
|
* [Can you summarize the NgModule API?](guide/ngmodule-faq#q-ngmodule-api)
|
||||||
|
|
||||||
|
|
||||||
<div class='l-hr'>
|
<div class='l-hr'>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
@ -78,6 +79,7 @@ Add [declarable](guide/ngmodule-faq#q-declarable) classes—components, dire
|
|||||||
Declare these classes in _exactly one_ module of the application.
|
Declare these classes in _exactly one_ module of the application.
|
||||||
Declare them in _this_ module if they _belong_ to this module.
|
Declare them in _this_ module if they _belong_ to this module.
|
||||||
|
|
||||||
|
|
||||||
<div class='l-hr'>
|
<div class='l-hr'>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
@ -92,6 +94,7 @@ Declarables are the class types—components, directives, and pipes—th
|
|||||||
you can add to a module's `declarations` list.
|
you can add to a module's `declarations` list.
|
||||||
They're the _only_ classes that you can add to `declarations`.
|
They're the _only_ classes that you can add to `declarations`.
|
||||||
|
|
||||||
|
|
||||||
<div class='l-hr'>
|
<div class='l-hr'>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
@ -113,6 +116,7 @@ For example, don't declare FORMS_DIRECTIVES from `@angular/forms`.
|
|||||||
* Non-Angular classes and objects, such as
|
* Non-Angular classes and objects, such as
|
||||||
strings, numbers, functions, entity models, configurations, business logic, and helper classes.
|
strings, numbers, functions, entity models, configurations, business logic, and helper classes.
|
||||||
|
|
||||||
|
|
||||||
<div class='l-hr'>
|
<div class='l-hr'>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
@ -135,6 +139,7 @@ Membership in one list doesn't imply membership in another list.
|
|||||||
* `HeroComponent` could be exported for inclusion in an external component's template
|
* `HeroComponent` could be exported for inclusion in an external component's template
|
||||||
as well as dynamically loaded in a pop-up dialog.
|
as well as dynamically loaded in a pop-up dialog.
|
||||||
|
|
||||||
|
|
||||||
<div class='l-hr'>
|
<div class='l-hr'>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
@ -153,6 +158,7 @@ For example, if "x" is `ngModel`, you probably haven't imported the `FormsModule
|
|||||||
Perhaps you declared "x" in an application sub-module but forgot to export it?
|
Perhaps you declared "x" in an application sub-module but forgot to export it?
|
||||||
The "x" class isn't visible to other modules until you add it to the `exports` list.
|
The "x" class isn't visible to other modules until you add it to the `exports` list.
|
||||||
|
|
||||||
|
|
||||||
<div class='l-hr'>
|
<div class='l-hr'>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
@ -178,6 +184,7 @@ components, directives, and pipes.
|
|||||||
|
|
||||||
Import only [BrowserModule](guide/ngmodule-faq#q-browser-vs-common-module) in the root `AppModule`.
|
Import only [BrowserModule](guide/ngmodule-faq#q-browser-vs-common-module) in the root `AppModule`.
|
||||||
|
|
||||||
|
|
||||||
<div class='l-hr'>
|
<div class='l-hr'>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
@ -209,6 +216,7 @@ They need the common directives. They don't need to re-install the app-wide prov
|
|||||||
|
|
||||||
Importing `CommonModule` also frees feature modules for use on _any_ target platform, not just browsers.
|
Importing `CommonModule` also frees feature modules for use on _any_ target platform, not just browsers.
|
||||||
|
|
||||||
|
|
||||||
<div class='l-hr'>
|
<div class='l-hr'>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
@ -229,6 +237,7 @@ When Angular gets to the 'B' and 'A' in 'D', they're already cached and ready to
|
|||||||
|
|
||||||
Angular doesn't like modules with circular references, so don't let Module 'A' import Module 'B', which imports Module 'A'.
|
Angular doesn't like modules with circular references, so don't let Module 'A' import Module 'B', which imports Module 'A'.
|
||||||
|
|
||||||
|
|
||||||
<div class='l-hr'>
|
<div class='l-hr'>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
@ -250,6 +259,7 @@ it's declared in this module or in an imported module.
|
|||||||
You _can_ re-export entire imported modules, which effectively re-exports all of their exported classes.
|
You _can_ re-export entire imported modules, which effectively re-exports all of their exported classes.
|
||||||
A module can even export a module that it doesn't import.
|
A module can even export a module that it doesn't import.
|
||||||
|
|
||||||
|
|
||||||
<div class='l-hr'>
|
<div class='l-hr'>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
@ -272,6 +282,7 @@ While there's no harm in exporting them, there's also no benefit.
|
|||||||
For example, there's no point in re-exporting `HttpModule` because it doesn't export anything.
|
For example, there's no point in re-exporting `HttpModule` because it doesn't export anything.
|
||||||
It's only purpose is to add http service providers to the application as a whole.
|
It's only purpose is to add http service providers to the application as a whole.
|
||||||
|
|
||||||
|
|
||||||
<div class='l-hr'>
|
<div class='l-hr'>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
@ -292,6 +303,7 @@ re-export them in a consolidated, convenience module.
|
|||||||
|
|
||||||
A module can re-export entire modules, which effectively re-exports all of their exported classes.
|
A module can re-export entire modules, which effectively re-exports all of their exported classes.
|
||||||
Angular's own `BrowserModule` exports a couple of modules like this:
|
Angular's own `BrowserModule` exports a couple of modules like this:
|
||||||
|
|
||||||
<code-example>
|
<code-example>
|
||||||
exports: [CommonModule, ApplicationModule]
|
exports: [CommonModule, ApplicationModule]
|
||||||
|
|
||||||
@ -310,6 +322,7 @@ It's only purpose is to add http service providers to the application as a whole
|
|||||||
~~~
|
~~~
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<div class='l-hr'>
|
<div class='l-hr'>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
@ -344,6 +357,7 @@ configure services in root and feature modules respectively.
|
|||||||
Angular doesn't recognize these names but Angular developers do.
|
Angular doesn't recognize these names but Angular developers do.
|
||||||
Follow this convention when you write similar modules with configurable service providers.
|
Follow this convention when you write similar modules with configurable service providers.
|
||||||
|
|
||||||
|
|
||||||
<div class='l-hr'>
|
<div class='l-hr'>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
@ -375,6 +389,7 @@ If the `HeroModule` provides the `HeroService` and the root `AppModule` imports
|
|||||||
any class that knows the `HeroService` _type_ can inject that service,
|
any class that knows the `HeroService` _type_ can inject that service,
|
||||||
not just the classes declared in the `HeroModule`.
|
not just the classes declared in the `HeroModule`.
|
||||||
|
|
||||||
|
|
||||||
<div class='l-hr'>
|
<div class='l-hr'>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
@ -398,6 +413,7 @@ These providers are insulated from changes to application providers with the sam
|
|||||||
When the router creates a component within the lazy-loaded context,
|
When the router creates a component within the lazy-loaded context,
|
||||||
Angular prefers service instances created from these providers to the service instances of the application root injector.
|
Angular prefers service instances created from these providers to the service instances of the application root injector.
|
||||||
|
|
||||||
|
|
||||||
<div class='l-hr'>
|
<div class='l-hr'>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
@ -423,6 +439,7 @@ that also provides a service for token 'X', then Module A's service definition "
|
|||||||
The service provided by the root `AppModule` takes precedence over services provided by imported modules.
|
The service provided by the root `AppModule` takes precedence over services provided by imported modules.
|
||||||
The `AppModule` always wins.
|
The `AppModule` always wins.
|
||||||
|
|
||||||
|
|
||||||
<div class='l-hr'>
|
<div class='l-hr'>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
@ -483,6 +500,7 @@ You can embed the child components in the top component's template.
|
|||||||
Alternatively, make the top component a routing host by giving it a `<router-outlet>`.
|
Alternatively, make the top component a routing host by giving it a `<router-outlet>`.
|
||||||
Define child routes and let the router load module components into that outlet.
|
Define child routes and let the router load module components into that outlet.
|
||||||
|
|
||||||
|
|
||||||
<div class='l-hr'>
|
<div class='l-hr'>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
@ -524,6 +542,7 @@ In the NgModule page sample applications, if you had registered `UserService` in
|
|||||||
the `HeroComponent` couldn't inject it.
|
the `HeroComponent` couldn't inject it.
|
||||||
The application would fail the moment a user navigated to "Heroes".
|
The application would fail the moment a user navigated to "Heroes".
|
||||||
|
|
||||||
|
|
||||||
<div class='l-hr'>
|
<div class='l-hr'>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
@ -549,6 +568,7 @@ The changes that editor makes to heroes in its service don't touch the hero inst
|
|||||||
[Always register _application-wide_ services with the root `AppModule`](guide/ngmodule-faq#q-root-component-or-module),
|
[Always register _application-wide_ services with the root `AppModule`](guide/ngmodule-faq#q-root-component-or-module),
|
||||||
not the root `AppComponent`.
|
not the root `AppComponent`.
|
||||||
|
|
||||||
|
|
||||||
<div class='l-hr'>
|
<div class='l-hr'>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
@ -598,6 +618,7 @@ The username goes bonkers as the Angular creates a new `UserService` instance ea
|
|||||||
~~~
|
~~~
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<div class='l-hr'>
|
<div class='l-hr'>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
@ -629,6 +650,7 @@ Angular must add the lazy-loaded module's providers to an injector somewhere.
|
|||||||
It can't added them to the app root injector because that injector is closed to new providers.
|
It can't added them to the app root injector because that injector is closed to new providers.
|
||||||
So Angular creates a new child injector for the lazy-loaded module context.
|
So Angular creates a new child injector for the lazy-loaded module context.
|
||||||
|
|
||||||
|
|
||||||
<div class='l-hr'>
|
<div class='l-hr'>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
@ -650,11 +672,13 @@ You can throw an error or take other remedial action.
|
|||||||
Certain NgModules (such as `BrowserModule`) implement such a guard,
|
Certain NgModules (such as `BrowserModule`) implement such a guard,
|
||||||
such as this `CoreModule` constructor from the NgModules page.
|
such as this `CoreModule` constructor from the NgModules page.
|
||||||
|
|
||||||
|
|
||||||
<code-example path="ngmodule/src/app/core/core.module.ts" region="ctor" linenums="false">
|
<code-example path="ngmodule/src/app/core/core.module.ts" region="ctor" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<div class='l-hr'>
|
<div class='l-hr'>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
@ -698,6 +722,7 @@ Angular automatically adds the following types of components to the module's `en
|
|||||||
|
|
||||||
You don't have to mention these components explicitly, although doing so is harmless.
|
You don't have to mention these components explicitly, although doing so is harmless.
|
||||||
|
|
||||||
|
|
||||||
<div class='l-hr'>
|
<div class='l-hr'>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
@ -718,6 +743,7 @@ it should generate code to bootstrap the application with this component.
|
|||||||
There's no need to list a component in both the `bootstrap` and `entryComponent` lists,
|
There's no need to list a component in both the `bootstrap` and `entryComponent` lists,
|
||||||
although doing so is harmless.
|
although doing so is harmless.
|
||||||
|
|
||||||
|
|
||||||
<div class='l-hr'>
|
<div class='l-hr'>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
@ -743,6 +769,7 @@ it's best to add only the components that are truly _entry components_.
|
|||||||
Don't include components that [are referenced](guide/ngmodule-faq#q-template-reference)
|
Don't include components that [are referenced](guide/ngmodule-faq#q-template-reference)
|
||||||
in the templates of other components.
|
in the templates of other components.
|
||||||
|
|
||||||
|
|
||||||
<div class='l-hr'>
|
<div class='l-hr'>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
@ -778,6 +805,7 @@ If a component isn't an _entry component_ or wasn't found in a template,
|
|||||||
the compiler omits it.
|
the compiler omits it.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<div class='l-hr'>
|
<div class='l-hr'>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
@ -854,15 +882,19 @@ follow them unless you have a good reason to do otherwise.
|
|||||||
~~~
|
~~~
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<table>
|
<table>
|
||||||
|
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
|
|
||||||
|
|
||||||
<th style="vertical-align: top">
|
<th style="vertical-align: top">
|
||||||
Feature Module
|
Feature Module
|
||||||
</th>
|
</th>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<th style="vertical-align: top">
|
<th style="vertical-align: top">
|
||||||
Guidelines
|
Guidelines
|
||||||
</th>
|
</th>
|
||||||
@ -871,13 +903,16 @@ follow them unless you have a good reason to do otherwise.
|
|||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
|
|
||||||
|
|
||||||
<td style="vertical-align: top">
|
<td style="vertical-align: top">
|
||||||
<a id="domain-feature-module"></a>Domain
|
<a id="domain-feature-module"></a>Domain
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
Domain feature modules deliver a user experience *dedicated to a particular application domain*
|
Domain feature modules deliver a user experience *dedicated to a particular application domain*
|
||||||
like editing a customer or placing an order.
|
like editing a customer or placing an order.
|
||||||
@ -913,13 +948,16 @@ follow them unless you have a good reason to do otherwise.
|
|||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
|
|
||||||
|
|
||||||
<td style="vertical-align: top">
|
<td style="vertical-align: top">
|
||||||
<a id="routed-feature-module"></a>Routed
|
<a id="routed-feature-module"></a>Routed
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
_Routed feature modules_ are _domain feature modules_
|
_Routed feature modules_ are _domain feature modules_
|
||||||
whose top components are the *targets of router navigation routes*.
|
whose top components are the *targets of router navigation routes*.
|
||||||
@ -951,13 +989,16 @@ follow them unless you have a good reason to do otherwise.
|
|||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
|
|
||||||
|
|
||||||
<td style="vertical-align: top">
|
<td style="vertical-align: top">
|
||||||
<a id="routing-module"></a>Routing
|
<a id="routing-module"></a>Routing
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
A [routing module](guide/router) *provides routing configuration* for another module.
|
A [routing module](guide/router) *provides routing configuration* for another module.
|
||||||
|
|
||||||
@ -1004,13 +1045,16 @@ follow them unless you have a good reason to do otherwise.
|
|||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
|
|
||||||
|
|
||||||
<td style="vertical-align: top">
|
<td style="vertical-align: top">
|
||||||
<a id="service-feature-module"></a>Service
|
<a id="service-feature-module"></a>Service
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
Service modules *provide utility services* such as data access and messaging.
|
Service modules *provide utility services* such as data access and messaging.
|
||||||
|
|
||||||
@ -1027,13 +1071,16 @@ follow them unless you have a good reason to do otherwise.
|
|||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
|
|
||||||
|
|
||||||
<td style="vertical-align: top">
|
<td style="vertical-align: top">
|
||||||
<a id="widget-feature-module"></a>Widget
|
<a id="widget-feature-module"></a>Widget
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
A widget module makes *components, directives, and pipes* available to external modules.
|
A widget module makes *components, directives, and pipes* available to external modules.
|
||||||
|
|
||||||
@ -1064,35 +1111,43 @@ Real-world modules are often hybrids that knowingly deviate from these guideline
|
|||||||
~~~
|
~~~
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<table>
|
<table>
|
||||||
|
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
|
|
||||||
|
|
||||||
<th>
|
<th>
|
||||||
Feature Module
|
Feature Module
|
||||||
</th>
|
</th>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<th>
|
<th>
|
||||||
Declarations
|
Declarations
|
||||||
</th>
|
</th>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<th>
|
<th>
|
||||||
Providers
|
Providers
|
||||||
</th>
|
</th>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<th>
|
<th>
|
||||||
Exports
|
Exports
|
||||||
</th>
|
</th>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<th>
|
<th>
|
||||||
Imported By
|
Imported By
|
||||||
</th>
|
</th>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<th>
|
<th>
|
||||||
Examples
|
Examples
|
||||||
</th>
|
</th>
|
||||||
@ -1101,33 +1156,40 @@ Real-world modules are often hybrids that knowingly deviate from these guideline
|
|||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
Domain
|
Domain
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
Yes
|
Yes
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
Rare
|
Rare
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
Top component
|
Top component
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
Feature, <code>AppModule</code>
|
Feature, <code>AppModule</code>
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
<code>ContactModule</code> (before routing)
|
<code>ContactModule</code> (before routing)
|
||||||
</td>
|
</td>
|
||||||
@ -1136,33 +1198,40 @@ Real-world modules are often hybrids that knowingly deviate from these guideline
|
|||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
Routed
|
Routed
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
Yes
|
Yes
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
Rare
|
Rare
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
No
|
No
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
Nobody
|
Nobody
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
<code>ContactModule</code>, <code>HeroModule</code>, <code>CrisisModule</code>
|
<code>ContactModule</code>, <code>HeroModule</code>, <code>CrisisModule</code>
|
||||||
</td>
|
</td>
|
||||||
@ -1171,33 +1240,40 @@ Real-world modules are often hybrids that knowingly deviate from these guideline
|
|||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
Routing
|
Routing
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
No
|
No
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
Yes (Guards)
|
Yes (Guards)
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
<code>RouterModule</code>
|
<code>RouterModule</code>
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
Feature (for routing)
|
Feature (for routing)
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
<code>AppRoutingModule</code>, <code>ContactRoutingModule</code>, <code>HeroRoutingModule</code>
|
<code>AppRoutingModule</code>, <code>ContactRoutingModule</code>, <code>HeroRoutingModule</code>
|
||||||
</td>
|
</td>
|
||||||
@ -1206,33 +1282,40 @@ Real-world modules are often hybrids that knowingly deviate from these guideline
|
|||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
Service
|
Service
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
No
|
No
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
Yes
|
Yes
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
No
|
No
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
<code>AppModule</code>
|
<code>AppModule</code>
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
<code>HttpModule</code>, <code>CoreModule</code>
|
<code>HttpModule</code>, <code>CoreModule</code>
|
||||||
</td>
|
</td>
|
||||||
@ -1241,33 +1324,40 @@ Real-world modules are often hybrids that knowingly deviate from these guideline
|
|||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
Widget
|
Widget
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
Yes
|
Yes
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
Rare
|
Rare
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
Yes
|
Yes
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
Feature
|
Feature
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
<code>CommonModule</code>, <code>SharedModule</code>
|
<code>CommonModule</code>, <code>SharedModule</code>
|
||||||
</td>
|
</td>
|
||||||
@ -1279,6 +1369,7 @@ Real-world modules are often hybrids that knowingly deviate from these guideline
|
|||||||
</table>
|
</table>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<div class='l-hr'>
|
<div class='l-hr'>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
@ -1295,6 +1386,7 @@ In modern JavaScript, every file is a _module_
|
|||||||
(see the [Modules](http://exploringjs.com/es6/ch_modules.html) page of the Exploring ES6 website).
|
(see the [Modules](http://exploringjs.com/es6/ch_modules.html) page of the Exploring ES6 website).
|
||||||
Within each file you write an `export` statement to make parts of the module public:
|
Within each file you write an `export` statement to make parts of the module public:
|
||||||
|
|
||||||
|
|
||||||
<code-example format='.'>
|
<code-example format='.'>
|
||||||
export class AppComponent { ... }
|
export class AppComponent { ... }
|
||||||
|
|
||||||
@ -1302,6 +1394,7 @@ Within each file you write an `export` statement to make parts of the module pub
|
|||||||
|
|
||||||
Then you `import` a part in another module:
|
Then you `import` a part in another module:
|
||||||
|
|
||||||
|
|
||||||
<code-example format='.'>
|
<code-example format='.'>
|
||||||
import { AppComponent } from './app.component';
|
import { AppComponent } from './app.component';
|
||||||
|
|
||||||
@ -1342,17 +1435,20 @@ They are available _everywhere_.
|
|||||||
|
|
||||||
Here's an _NgModule_ class with imports, exports, and declarations.
|
Here's an _NgModule_ class with imports, exports, and declarations.
|
||||||
|
|
||||||
|
|
||||||
<code-example path="ngmodule/src/app/contact/contact.module.2.ts" region="class" linenums="false">
|
<code-example path="ngmodule/src/app/contact/contact.module.2.ts" region="class" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
|
|
||||||
Of course you use _JavaScript_ modules to write _Angular_ modules as seen in the complete `contact.module.ts` file:
|
Of course you use _JavaScript_ modules to write _Angular_ modules as seen in the complete `contact.module.ts` file:
|
||||||
|
|
||||||
|
|
||||||
<code-example path="ngmodule/src/app/contact/contact.module.2.ts" linenums="false">
|
<code-example path="ngmodule/src/app/contact/contact.module.2.ts" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<div class='l-hr'>
|
<div class='l-hr'>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
@ -1374,6 +1470,7 @@ The compiler finds a pipe if the pipe's *name* appears within the pipe syntax of
|
|||||||
Angular only matches selectors and pipe names for classes that are declared by this module
|
Angular only matches selectors and pipe names for classes that are declared by this module
|
||||||
or exported by a module that this module imports.
|
or exported by a module that this module imports.
|
||||||
|
|
||||||
|
|
||||||
<div class='l-hr'>
|
<div class='l-hr'>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
@ -1405,6 +1502,7 @@ the Angular compiler incorporates them into compiled component code too.
|
|||||||
`@NgModule` metadata tells the Angular compiler what components to compile for this module and
|
`@NgModule` metadata tells the Angular compiler what components to compile for this module and
|
||||||
how to link this module with other modules.
|
how to link this module with other modules.
|
||||||
|
|
||||||
|
|
||||||
<div class='l-hr'>
|
<div class='l-hr'>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
@ -1416,15 +1514,19 @@ how to link this module with other modules.
|
|||||||
## NgModule API
|
## NgModule API
|
||||||
|
|
||||||
The following table summarizes the `NgModule` metadata properties.
|
The following table summarizes the `NgModule` metadata properties.
|
||||||
|
|
||||||
<table>
|
<table>
|
||||||
|
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
|
|
||||||
|
|
||||||
<th>
|
<th>
|
||||||
Property
|
Property
|
||||||
</th>
|
</th>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<th>
|
<th>
|
||||||
Description
|
Description
|
||||||
</th>
|
</th>
|
||||||
@ -1433,13 +1535,16 @@ The following table summarizes the `NgModule` metadata properties.
|
|||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
|
|
||||||
|
|
||||||
<td style="vertical-align: top">
|
<td style="vertical-align: top">
|
||||||
<code>declarations</code>
|
<code>declarations</code>
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
A list of [declarable](guide/ngmodule-faq#q-declarable) classes,
|
A list of [declarable](guide/ngmodule-faq#q-declarable) classes,
|
||||||
the *component*, *directive*, and *pipe* classes that _belong to this module_.
|
the *component*, *directive*, and *pipe* classes that _belong to this module_.
|
||||||
@ -1459,13 +1564,16 @@ The following table summarizes the `NgModule` metadata properties.
|
|||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
|
|
||||||
|
|
||||||
<td style="vertical-align: top">
|
<td style="vertical-align: top">
|
||||||
<code>providers</code>
|
<code>providers</code>
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
A list of dependency-injection providers.
|
A list of dependency-injection providers.
|
||||||
|
|
||||||
@ -1492,13 +1600,16 @@ The following table summarizes the `NgModule` metadata properties.
|
|||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
|
|
||||||
|
|
||||||
<td style="vertical-align: top">
|
<td style="vertical-align: top">
|
||||||
<code>imports</code>
|
<code>imports</code>
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
A list of supporting modules.
|
A list of supporting modules.
|
||||||
|
|
||||||
@ -1521,13 +1632,16 @@ The following table summarizes the `NgModule` metadata properties.
|
|||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
|
|
||||||
|
|
||||||
<td style="vertical-align: top">
|
<td style="vertical-align: top">
|
||||||
<code>exports</code>
|
<code>exports</code>
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
A list of declarations—*component*, *directive*, and *pipe* classes—that
|
A list of declarations—*component*, *directive*, and *pipe* classes—that
|
||||||
an importing module can use.
|
an importing module can use.
|
||||||
@ -1539,7 +1653,7 @@ The following table summarizes the `NgModule` metadata properties.
|
|||||||
Declarations are private by default.
|
Declarations are private by default.
|
||||||
If this module does _not_ export `HeroComponent`, no other module can see it.
|
If this module does _not_ export `HeroComponent`, no other module can see it.
|
||||||
|
|
||||||
Importing a module does _not_ automatically re-export the imported module's exports.
|
Importing a module does _not_ automatically re-export the imported module's imports.
|
||||||
Module 'B' can't use `ngIf` just because it imported module `A` which imported `CommonModule`.
|
Module 'B' can't use `ngIf` just because it imported module `A` which imported `CommonModule`.
|
||||||
Module 'B' must import `CommonModule` itself.
|
Module 'B' must import `CommonModule` itself.
|
||||||
|
|
||||||
@ -1556,13 +1670,16 @@ The following table summarizes the `NgModule` metadata properties.
|
|||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
|
|
||||||
|
|
||||||
<td style="vertical-align: top">
|
<td style="vertical-align: top">
|
||||||
<code>bootstrap</code>
|
<code>bootstrap</code>
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
A list of components that can be bootstrapped.
|
A list of components that can be bootstrapped.
|
||||||
|
|
||||||
@ -1579,13 +1696,16 @@ The following table summarizes the `NgModule` metadata properties.
|
|||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
|
|
||||||
|
|
||||||
<td style="vertical-align: top">
|
<td style="vertical-align: top">
|
||||||
<code>entryComponents</code>
|
<code>entryComponents</code>
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
A list of components that are _not_ [referenced](guide/ngmodule-faq#q-template-reference) in a reachable component template.
|
A list of components that are _not_ [referenced](guide/ngmodule-faq#q-template-reference) in a reachable component template.
|
||||||
|
|
||||||
|
@ -66,6 +66,7 @@ The companion [NgModule FAQs](cookbook/ngmodule-faq) cookbook
|
|||||||
offers answers to specific design and implementation questions.
|
offers answers to specific design and implementation questions.
|
||||||
Read this page before reading those FAQs.
|
Read this page before reading those FAQs.
|
||||||
|
|
||||||
|
|
||||||
<div class='l-hr'>
|
<div class='l-hr'>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
@ -122,6 +123,7 @@ By convention, the *root module* class is called `AppModule` and it exists in a
|
|||||||
|
|
||||||
The `AppModule` from the QuickStart seed on the [Setup](guide/setup) page is as minimal as possible:
|
The `AppModule` from the QuickStart seed on the [Setup](guide/setup) page is as minimal as possible:
|
||||||
|
|
||||||
|
|
||||||
<code-example path="setup/src/app/app.module.ts" linenums="false">
|
<code-example path="setup/src/app/app.module.ts" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -140,6 +142,7 @@ the _root component_, the top of the app's rather bare component tree.
|
|||||||
|
|
||||||
The example `AppComponent` simply displays a data-bound title:
|
The example `AppComponent` simply displays a data-bound title:
|
||||||
|
|
||||||
|
|
||||||
<code-example path="ngmodule/src/app/app.component.0.ts" linenums="false">
|
<code-example path="ngmodule/src/app/app.component.0.ts" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -162,6 +165,7 @@ In the first, _dynamic_ option, the [Angular compiler](cookbook/ngmodule-faq)
|
|||||||
compiles the application in the browser and then launches the app.
|
compiles the application in the browser and then launches the app.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="ngmodule/src/main.ts" linenums="false">
|
<code-example path="ngmodule/src/main.ts" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -184,6 +188,7 @@ The syntax for bootstrapping the pre-compiled `AppModuleNgFactory` is similar to
|
|||||||
the dynamic version that bootstraps the `AppModule` class.
|
the dynamic version that bootstraps the `AppModule` class.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="ngmodule/src/main-static.ts" linenums="false">
|
<code-example path="ngmodule/src/main-static.ts" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -205,6 +210,7 @@ In general, the `AppModule` should neither know nor care how it is bootstrapped.
|
|||||||
Although the `AppModule` evolves as the app grows, the bootstrap code in `main.ts` doesn't change.
|
Although the `AppModule` evolves as the app grows, the bootstrap code in `main.ts` doesn't change.
|
||||||
This is the last time you'll look at `main.ts`.
|
This is the last time you'll look at `main.ts`.
|
||||||
|
|
||||||
|
|
||||||
<div class='l-hr'>
|
<div class='l-hr'>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
@ -218,12 +224,14 @@ As the app evolves,
|
|||||||
the first addition is a `HighlightDirective`, an [attribute directive](guide/attribute-directives)
|
the first addition is a `HighlightDirective`, an [attribute directive](guide/attribute-directives)
|
||||||
that sets the background color of the attached element.
|
that sets the background color of the attached element.
|
||||||
|
|
||||||
|
|
||||||
<code-example path="ngmodule/src/app/highlight.directive.ts" linenums="false">
|
<code-example path="ngmodule/src/app/highlight.directive.ts" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
|
|
||||||
Update the `AppComponent` template to attach the directive to the title:
|
Update the `AppComponent` template to attach the directive to the title:
|
||||||
|
|
||||||
|
|
||||||
<code-example path="ngmodule/src/app/app.component.1.ts" region="template" linenums="false">
|
<code-example path="ngmodule/src/app/app.component.1.ts" region="template" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -233,6 +241,7 @@ You must declare the directive in `AppModule`.
|
|||||||
|
|
||||||
Import the `HighlightDirective` class and add it to the module's `declarations` like this:
|
Import the `HighlightDirective` class and add it to the module's `declarations` like this:
|
||||||
|
|
||||||
|
|
||||||
<code-example path="ngmodule/src/app/app.module.1.ts" region="directive" linenums="false">
|
<code-example path="ngmodule/src/app/app.module.1.ts" region="directive" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -242,12 +251,14 @@ Import the `HighlightDirective` class and add it to the module's `declarations`
|
|||||||
Refactor the title into its own `TitleComponent`.
|
Refactor the title into its own `TitleComponent`.
|
||||||
The component's template binds to the component's `title` and `subtitle` properties like this:
|
The component's template binds to the component's `title` and `subtitle` properties like this:
|
||||||
|
|
||||||
|
|
||||||
<code-example path="ngmodule/src/app/title.component.html" region="v1" linenums="false">
|
<code-example path="ngmodule/src/app/title.component.html" region="v1" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="ngmodule/src/app/title.component.ts" region="v1" linenums="false">
|
<code-example path="ngmodule/src/app/title.component.ts" region="v1" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -255,6 +266,7 @@ The component's template binds to the component's `title` and `subtitle` propert
|
|||||||
Rewrite the `AppComponent` to display the new `TitleComponent` in the `<app-title>` element,
|
Rewrite the `AppComponent` to display the new `TitleComponent` in the `<app-title>` element,
|
||||||
using an input binding to set the `subtitle`.
|
using an input binding to set the `subtitle`.
|
||||||
|
|
||||||
|
|
||||||
<code-example path="ngmodule/src/app/app.component.1.ts" linenums="false">
|
<code-example path="ngmodule/src/app/app.component.1.ts" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -262,6 +274,7 @@ using an input binding to set the `subtitle`.
|
|||||||
Angular won't recognize the `<app-title>` tag until you declare it in `AppModule`.
|
Angular won't recognize the `<app-title>` tag until you declare it in `AppModule`.
|
||||||
Import the `TitleComponent` class and add it to the module's `declarations`:
|
Import the `TitleComponent` class and add it to the module's `declarations`:
|
||||||
|
|
||||||
|
|
||||||
<code-example path="ngmodule/src/app/app.module.1.ts" region="component" linenums="false">
|
<code-example path="ngmodule/src/app/app.module.1.ts" region="component" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -287,6 +300,7 @@ accessible through a user service.
|
|||||||
This sample application has a dummy implementation of such a `UserService`.
|
This sample application has a dummy implementation of such a `UserService`.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="ngmodule/src/app/user.service.ts" linenums="false">
|
<code-example path="ngmodule/src/app/user.service.ts" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -294,6 +308,7 @@ This sample application has a dummy implementation of such a `UserService`.
|
|||||||
The sample application should display a welcome message to the logged-in user just below the application title.
|
The sample application should display a welcome message to the logged-in user just below the application title.
|
||||||
Update the `TitleComponent` template to show the welcome message below the application title.
|
Update the `TitleComponent` template to show the welcome message below the application title.
|
||||||
|
|
||||||
|
|
||||||
<code-example path="ngmodule/src/app/title.component.html" linenums="false">
|
<code-example path="ngmodule/src/app/title.component.html" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -301,6 +316,7 @@ Update the `TitleComponent` template to show the welcome message below the appli
|
|||||||
Update the `TitleComponent` class with a constructor that injects the `UserService`
|
Update the `TitleComponent` class with a constructor that injects the `UserService`
|
||||||
and sets the component's `user` property from the service.
|
and sets the component's `user` property from the service.
|
||||||
|
|
||||||
|
|
||||||
<code-example path="ngmodule/src/app/title.component.ts" linenums="false">
|
<code-example path="ngmodule/src/app/title.component.ts" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -308,6 +324,7 @@ and sets the component's `user` property from the service.
|
|||||||
You've defined and used the service. Now to _provide_ it for all components to use,
|
You've defined and used the service. Now to _provide_ it for all components to use,
|
||||||
add it to a `providers` property in the `AppModule` metadata:
|
add it to a `providers` property in the `AppModule` metadata:
|
||||||
|
|
||||||
|
|
||||||
<code-example path="ngmodule/src/app/app.module.1.ts" region="providers" linenums="false">
|
<code-example path="ngmodule/src/app/app.module.1.ts" region="providers" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -321,6 +338,7 @@ add it to a `providers` property in the `AppModule` metadata:
|
|||||||
In the revised `TitleComponent`, an `*ngIf` directive guards the message.
|
In the revised `TitleComponent`, an `*ngIf` directive guards the message.
|
||||||
There is no message if there is no user.
|
There is no message if there is no user.
|
||||||
|
|
||||||
|
|
||||||
<code-example path="ngmodule/src/app/title.component.html" region="ngIf" linenums="false">
|
<code-example path="ngmodule/src/app/title.component.html" region="ngIf" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -331,6 +349,7 @@ How can that be? The Angular compiler should either ignore or complain about unr
|
|||||||
Angular does recognize `NgIf` because you imported it earlier.
|
Angular does recognize `NgIf` because you imported it earlier.
|
||||||
The initial version of `AppModule` imports `BrowserModule`.
|
The initial version of `AppModule` imports `BrowserModule`.
|
||||||
|
|
||||||
|
|
||||||
<code-example path="ngmodule/src/app/app.module.0.ts" region="imports" linenums="false">
|
<code-example path="ngmodule/src/app/app.module.0.ts" region="imports" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -384,6 +403,7 @@ import the `ReactiveFormsModule`.
|
|||||||
The `ContactComponent` selector matches an element named `<app-contact>`.
|
The `ContactComponent` selector matches an element named `<app-contact>`.
|
||||||
Add an element with that name to the `AppComponent` template, just below the `<app-title>`:
|
Add an element with that name to the `AppComponent` template, just below the `<app-title>`:
|
||||||
|
|
||||||
|
|
||||||
<code-example path="ngmodule/src/app/app.component.1b.ts" region="template" linenums="false">
|
<code-example path="ngmodule/src/app/app.component.1b.ts" region="template" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -395,33 +415,40 @@ and an alternative version of the `HighlightDirective`.
|
|||||||
To make it manageable, place all contact-related material in an `src/app/contact` folder
|
To make it manageable, place all contact-related material in an `src/app/contact` folder
|
||||||
and break the component into three constituent HTML, TypeScript, and css files:
|
and break the component into three constituent HTML, TypeScript, and css files:
|
||||||
|
|
||||||
|
|
||||||
<code-tabs>
|
<code-tabs>
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="src/app/contact/contact.component.html" path="ngmodule/src/app/contact/contact.component.html">
|
<code-pane title="src/app/contact/contact.component.html" path="ngmodule/src/app/contact/contact.component.html">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="src/app/contact/contact.component.ts" path="ngmodule/src/app/contact/contact.component.3.ts">
|
<code-pane title="src/app/contact/contact.component.ts" path="ngmodule/src/app/contact/contact.component.3.ts">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="src/app/contact/contact.component.css" path="ngmodule/src/app/contact/contact.component.css">
|
<code-pane title="src/app/contact/contact.component.css" path="ngmodule/src/app/contact/contact.component.css">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="src/app/contact/contact.service.ts" path="ngmodule/src/app/contact/contact.service.ts">
|
<code-pane title="src/app/contact/contact.service.ts" path="ngmodule/src/app/contact/contact.service.ts">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="src/app/contact/awesome.pipe.ts" path="ngmodule/src/app/contact/awesome.pipe.ts">
|
<code-pane title="src/app/contact/awesome.pipe.ts" path="ngmodule/src/app/contact/awesome.pipe.ts">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="src/app/contact/highlight.directive.ts" path="ngmodule/src/app/contact/highlight.directive.ts">
|
<code-pane title="src/app/contact/highlight.directive.ts" path="ngmodule/src/app/contact/highlight.directive.ts">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
@ -445,6 +472,7 @@ form features such as validation aren't yet available.
|
|||||||
|
|
||||||
Add the `FormsModule` to the `AppModule` metadata's `imports` list.
|
Add the `FormsModule` to the `AppModule` metadata's `imports` list.
|
||||||
|
|
||||||
|
|
||||||
<code-example path="ngmodule/src/app/app.module.1.ts" region="imports" linenums="false">
|
<code-example path="ngmodule/src/app/app.module.1.ts" region="imports" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -474,6 +502,7 @@ Components, directives, and pipes belong to _one module only_.
|
|||||||
The application won't compile until you declare the contact component, directive, and pipe.
|
The application won't compile until you declare the contact component, directive, and pipe.
|
||||||
Update the `declarations` in the `AppModule` accordingly:
|
Update the `declarations` in the `AppModule` accordingly:
|
||||||
|
|
||||||
|
|
||||||
<code-example path="ngmodule/src/app/app.module.1.ts" region="declarations" linenums="false">
|
<code-example path="ngmodule/src/app/app.module.1.ts" region="declarations" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -489,6 +518,7 @@ There are two directives with the same name, both called `HighlightDirective`.
|
|||||||
|
|
||||||
To work around this, create an alias for the contact version using the `as` JavaScript import keyword.
|
To work around this, create an alias for the contact version using the `as` JavaScript import keyword.
|
||||||
|
|
||||||
|
|
||||||
<code-example path="ngmodule/src/app/app.module.1b.ts" region="import-alias" linenums="false">
|
<code-example path="ngmodule/src/app/app.module.1b.ts" region="import-alias" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -511,6 +541,7 @@ You want to share this service with other contact-related components that you'll
|
|||||||
|
|
||||||
In this app, add `ContactService` to the `AppModule` metadata's `providers` list:
|
In this app, add `ContactService` to the `AppModule` metadata's `providers` list:
|
||||||
|
|
||||||
|
|
||||||
<code-example path="ngmodule/src/app/app.module.1b.ts" region="providers" linenums="false">
|
<code-example path="ngmodule/src/app/app.module.1b.ts" region="providers" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -553,52 +584,64 @@ Now you can inject `ContactService` (like `UserService`) into any component in t
|
|||||||
Everything is in place to run the application with its contact editor.
|
Everything is in place to run the application with its contact editor.
|
||||||
|
|
||||||
The app file structure looks like this:
|
The app file structure looks like this:
|
||||||
|
|
||||||
<aio-filetree>
|
<aio-filetree>
|
||||||
|
|
||||||
|
|
||||||
<aio-folder>
|
<aio-folder>
|
||||||
app
|
app
|
||||||
|
|
||||||
<aio-file>
|
<aio-file>
|
||||||
app.component.ts
|
app.component.ts
|
||||||
</aio-file>
|
</aio-file>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<aio-file>
|
<aio-file>
|
||||||
app.module.ts
|
app.module.ts
|
||||||
</aio-file>
|
</aio-file>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<aio-file>
|
<aio-file>
|
||||||
highlight.directive.ts
|
highlight.directive.ts
|
||||||
</aio-file>
|
</aio-file>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<aio-file>
|
<aio-file>
|
||||||
title.component.(html|ts)
|
title.component.(html|ts)
|
||||||
</aio-file>
|
</aio-file>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<aio-file>
|
<aio-file>
|
||||||
user.service.ts
|
user.service.ts
|
||||||
</aio-file>
|
</aio-file>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<aio-folder>
|
<aio-folder>
|
||||||
contact
|
contact
|
||||||
|
|
||||||
<aio-file>
|
<aio-file>
|
||||||
awesome.pipe.ts
|
awesome.pipe.ts
|
||||||
</aio-file>
|
</aio-file>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<aio-file>
|
<aio-file>
|
||||||
contact.component.(css|html|ts)
|
contact.component.(css|html|ts)
|
||||||
</aio-file>
|
</aio-file>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<aio-file>
|
<aio-file>
|
||||||
contact.service.ts
|
contact.service.ts
|
||||||
</aio-file>
|
</aio-file>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<aio-file>
|
<aio-file>
|
||||||
highlight.directive.ts
|
highlight.directive.ts
|
||||||
</aio-file>
|
</aio-file>
|
||||||
@ -628,13 +671,16 @@ you already had a `HighlightDirective` class at the application level.
|
|||||||
|
|
||||||
The selectors of the two directives both highlight the attached element with a different color.
|
The selectors of the two directives both highlight the attached element with a different color.
|
||||||
|
|
||||||
|
|
||||||
<code-tabs>
|
<code-tabs>
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="src/app/highlight.directive.ts" path="ngmodule/src/app/highlight.directive.ts">
|
<code-pane title="src/app/highlight.directive.ts" path="ngmodule/src/app/highlight.directive.ts">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="src/app/contact/highlight.directive.ts" path="ngmodule/src/app/contact/highlight.directive.ts">
|
<code-pane title="src/app/contact/highlight.directive.ts" path="ngmodule/src/app/contact/highlight.directive.ts">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
@ -736,6 +782,7 @@ It's easy to refactor the contact material into a contact feature module.
|
|||||||
|
|
||||||
Here's the new `ContactModule`:
|
Here's the new `ContactModule`:
|
||||||
|
|
||||||
|
|
||||||
<code-example path="ngmodule/src/app/contact/contact.module.2.ts">
|
<code-example path="ngmodule/src/app/contact/contact.module.2.ts">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -778,13 +825,16 @@ Then import the `ContactModule` so the app can continue to display the exported
|
|||||||
|
|
||||||
Here's the refactored version of the `AppModule` along with the previous version.
|
Here's the refactored version of the `AppModule` along with the previous version.
|
||||||
|
|
||||||
|
|
||||||
<code-tabs>
|
<code-tabs>
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="src/app/app.module.ts (v2)" path="ngmodule/src/app/app.module.2.ts">
|
<code-pane title="src/app/app.module.ts (v2)" path="ngmodule/src/app/app.module.2.ts">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="src/app/app.module.ts (v1)" path="ngmodule/src/app/app.module.1b.ts">
|
<code-pane title="src/app/app.module.ts (v1)" path="ngmodule/src/app/app.module.1b.ts">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
@ -835,6 +885,7 @@ Some facets of the current application merit discussion are as follows:
|
|||||||
The new `AppComponent` template has
|
The new `AppComponent` template has
|
||||||
a title, three links, and a `<router-outlet>`.
|
a title, three links, and a `<router-outlet>`.
|
||||||
|
|
||||||
|
|
||||||
<code-example path="ngmodule/src/app/app.component.3.ts" region="template" linenums="false">
|
<code-example path="ngmodule/src/app/app.component.3.ts" region="template" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -843,6 +894,7 @@ The `<app-contact>` element is gone; you're routing to the _Contact_ page now.
|
|||||||
|
|
||||||
The `AppModule` has changed modestly:
|
The `AppModule` has changed modestly:
|
||||||
|
|
||||||
|
|
||||||
<code-example path="ngmodule/src/app/app.module.3.ts">
|
<code-example path="ngmodule/src/app/app.module.3.ts">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -870,6 +922,7 @@ that handles the app's routing concerns.
|
|||||||
|
|
||||||
### App routing
|
### App routing
|
||||||
|
|
||||||
|
|
||||||
<code-example path="ngmodule/src/app/app-routing.module.ts" linenums="false">
|
<code-example path="ngmodule/src/app/app-routing.module.ts" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -889,6 +942,7 @@ You'll get to that file in a moment.
|
|||||||
|
|
||||||
The remaining two routes use lazy loading syntax to tell the router where to find the modules:
|
The remaining two routes use lazy loading syntax to tell the router where to find the modules:
|
||||||
|
|
||||||
|
|
||||||
<code-example path="ngmodule/src/app/app-routing.module.ts" region="lazy-routes" linenums="false">
|
<code-example path="ngmodule/src/app/app-routing.module.ts" region="lazy-routes" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -909,6 +963,7 @@ the latter separated from the former by a `#`.
|
|||||||
The `forRoot` static class method of the `RouterModule` with the provided configuration and
|
The `forRoot` static class method of the `RouterModule` with the provided configuration and
|
||||||
added to the `imports` array provides the routing concerns for the module.
|
added to the `imports` array provides the routing concerns for the module.
|
||||||
|
|
||||||
|
|
||||||
<code-example path="ngmodule/src/app/app-routing.module.ts" region="forRoot" linenums="false">
|
<code-example path="ngmodule/src/app/app-routing.module.ts" region="forRoot" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -928,6 +983,7 @@ Never call `RouterModule.forRoot` in a feature-routing module.
|
|||||||
Back in the root `AppModule`, add the `AppRoutingModule` to its `imports` list,
|
Back in the root `AppModule`, add the `AppRoutingModule` to its `imports` list,
|
||||||
and the app is ready to navigate.
|
and the app is ready to navigate.
|
||||||
|
|
||||||
|
|
||||||
<code-example path="ngmodule/src/app/app.module.3.ts" region="imports" linenums="false">
|
<code-example path="ngmodule/src/app/app.module.3.ts" region="imports" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -936,6 +992,7 @@ and the app is ready to navigate.
|
|||||||
The `src/app/contact` folder holds a new file, `contact-routing.module.ts`.
|
The `src/app/contact` folder holds a new file, `contact-routing.module.ts`.
|
||||||
It defines the `contact` route mentioned earlier and provides a `ContactRoutingModule` as follows:
|
It defines the `contact` route mentioned earlier and provides a `ContactRoutingModule` as follows:
|
||||||
|
|
||||||
|
|
||||||
<code-example path="ngmodule/src/app/contact/contact-routing.module.ts" region="routing" linenums="false">
|
<code-example path="ngmodule/src/app/contact/contact-routing.module.ts" region="routing" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -967,13 +1024,16 @@ that has both shared [declarables](cookbook/ngmodule-faq) and services.
|
|||||||
|
|
||||||
`ContactModule` has changed in two small but important ways.
|
`ContactModule` has changed in two small but important ways.
|
||||||
|
|
||||||
|
|
||||||
<code-tabs>
|
<code-tabs>
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="src/app/contact/contact.module.3.ts" path="ngmodule/src/app/contact/contact.module.3.ts" region="class">
|
<code-pane title="src/app/contact/contact.module.3.ts" path="ngmodule/src/app/contact/contact.module.3.ts" region="class">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="src/app/contact/contact.module.2.ts" path="ngmodule/src/app/contact/contact.module.2.ts" region="class">
|
<code-pane title="src/app/contact/contact.module.2.ts" path="ngmodule/src/app/contact/contact.module.2.ts" region="class">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
@ -999,40 +1059,49 @@ They don't look different from the eagerly loaded `ContactModule`.
|
|||||||
The `HeroModule` is a bit more complex than the `CrisisModule`, which makes it
|
The `HeroModule` is a bit more complex than the `CrisisModule`, which makes it
|
||||||
a more interesting and useful example. Its file structure is as follows:
|
a more interesting and useful example. Its file structure is as follows:
|
||||||
|
|
||||||
|
|
||||||
<aio-filetree>
|
<aio-filetree>
|
||||||
|
|
||||||
|
|
||||||
<aio-folder>
|
<aio-folder>
|
||||||
hero
|
hero
|
||||||
|
|
||||||
<aio-file>
|
<aio-file>
|
||||||
hero-detail.component.ts
|
hero-detail.component.ts
|
||||||
</aio-file>
|
</aio-file>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<aio-file>
|
<aio-file>
|
||||||
hero-list.component.ts
|
hero-list.component.ts
|
||||||
</aio-file>
|
</aio-file>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<aio-file>
|
<aio-file>
|
||||||
hero.component.ts
|
hero.component.ts
|
||||||
</aio-file>
|
</aio-file>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<aio-file>
|
<aio-file>
|
||||||
hero.module.ts
|
hero.module.ts
|
||||||
</aio-file>
|
</aio-file>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<aio-file>
|
<aio-file>
|
||||||
hero-routing.module.ts
|
hero-routing.module.ts
|
||||||
</aio-file>
|
</aio-file>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<aio-file>
|
<aio-file>
|
||||||
hero.service.ts
|
hero.service.ts
|
||||||
</aio-file>
|
</aio-file>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<aio-file>
|
<aio-file>
|
||||||
highlight.directive.ts
|
highlight.directive.ts
|
||||||
</aio-file>
|
</aio-file>
|
||||||
@ -1056,6 +1125,7 @@ In the next section, [Shared modules](guide/ngmodule#shared-module "Shared modul
|
|||||||
|
|
||||||
The `HeroModule` is a feature module like any other.
|
The `HeroModule` is a feature module like any other.
|
||||||
|
|
||||||
|
|
||||||
<code-example path="ngmodule/src/app/hero/hero.module.3.ts" region="class" linenums="false">
|
<code-example path="ngmodule/src/app/hero/hero.module.3.ts" region="class" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -1087,6 +1157,7 @@ and share them with the modules that need them.
|
|||||||
|
|
||||||
Here is the `SharedModule`:
|
Here is the `SharedModule`:
|
||||||
|
|
||||||
|
|
||||||
<code-example path="ngmodule/src/app/shared/shared.module.ts">
|
<code-example path="ngmodule/src/app/shared/shared.module.ts">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -1166,6 +1237,7 @@ Perform the following steps:
|
|||||||
|
|
||||||
Most of this work is familiar. The interesting part is the `CoreModule`.
|
Most of this work is familiar. The interesting part is the `CoreModule`.
|
||||||
|
|
||||||
|
|
||||||
<code-example path="ngmodule/src/app/core/core.module.ts" region="v4">
|
<code-example path="ngmodule/src/app/core/core.module.ts" region="v4">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -1227,13 +1299,16 @@ Having refactored to a `CoreModule` and a `SharedModule`, it's time to clean up
|
|||||||
|
|
||||||
Here is the updated `AppModule` paired with version 3 for comparison:
|
Here is the updated `AppModule` paired with version 3 for comparison:
|
||||||
|
|
||||||
|
|
||||||
<code-tabs>
|
<code-tabs>
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="src/app/app.module.ts (v4)" path="ngmodule/src/app/app.module.ts" region="v4">
|
<code-pane title="src/app/app.module.ts (v4)" path="ngmodule/src/app/app.module.ts" region="v4">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="src/app/app.module.ts (v3)" path="ngmodule/src/app/app.module.3.ts">
|
<code-pane title="src/app/app.module.ts (v3)" path="ngmodule/src/app/app.module.3.ts">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
@ -1250,13 +1325,16 @@ Here is the updated `AppModule` paired with version 3 for comparison:
|
|||||||
### A trimmer _ContactModule_
|
### A trimmer _ContactModule_
|
||||||
Here is the new `ContactModule` paired with the prior version:
|
Here is the new `ContactModule` paired with the prior version:
|
||||||
|
|
||||||
|
|
||||||
<code-tabs>
|
<code-tabs>
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="src/app/contact/contact.module.ts (v4)" path="ngmodule/src/app/contact/contact.module.ts">
|
<code-pane title="src/app/contact/contact.module.ts (v4)" path="ngmodule/src/app/contact/contact.module.ts">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="src/app/contact/contact.module.ts (v3)" path="ngmodule/src/app/contact/contact.module.3.ts">
|
<code-pane title="src/app/contact/contact.module.ts (v3)" path="ngmodule/src/app/contact/contact.module.3.ts">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
@ -1269,6 +1347,7 @@ Notice the following:
|
|||||||
* The imports include `SharedModule` instead of `CommonModule` and `FormsModule`.
|
* The imports include `SharedModule` instead of `CommonModule` and `FormsModule`.
|
||||||
* The new version is leaner and cleaner.
|
* The new version is leaner and cleaner.
|
||||||
|
|
||||||
|
|
||||||
<div class='l-hr'>
|
<div class='l-hr'>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
@ -1303,18 +1382,21 @@ Add a `CoreModule.forRoot` method that configures the core `UserService`.
|
|||||||
You've extended the core `UserService` with an optional, injected `UserServiceConfig`.
|
You've extended the core `UserService` with an optional, injected `UserServiceConfig`.
|
||||||
If a `UserServiceConfig` exists, the `UserService` sets the user name from that config.
|
If a `UserServiceConfig` exists, the `UserService` sets the user name from that config.
|
||||||
|
|
||||||
|
|
||||||
<code-example path="ngmodule/src/app/core/user.service.ts" region="ctor" linenums="false">
|
<code-example path="ngmodule/src/app/core/user.service.ts" region="ctor" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
|
|
||||||
Here's `CoreModule.forRoot` that takes a `UserServiceConfig` object:
|
Here's `CoreModule.forRoot` that takes a `UserServiceConfig` object:
|
||||||
|
|
||||||
|
|
||||||
<code-example path="ngmodule/src/app/core/core.module.ts" region="for-root" linenums="false">
|
<code-example path="ngmodule/src/app/core/core.module.ts" region="for-root" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
|
|
||||||
Lastly, call it within the `imports` list of the `AppModule`.
|
Lastly, call it within the `imports` list of the `AppModule`.
|
||||||
|
|
||||||
|
|
||||||
<code-example path="ngmodule/src/app/app.module.ts" region="import-for-root" linenums="false">
|
<code-example path="ngmodule/src/app/app.module.ts" region="import-for-root" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -1334,6 +1416,7 @@ Remember to _import_ the result; don't add it to any other `@NgModule` list.
|
|||||||
~~~
|
~~~
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<div class='l-hr'>
|
<div class='l-hr'>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
@ -1352,6 +1435,7 @@ It looks like it is supposed to go to a specific question/section within the pag
|
|||||||
You could hope that no developer makes that mistake.
|
You could hope that no developer makes that mistake.
|
||||||
Or you can guard against it and fail fast by adding the following `CoreModule` constructor.
|
Or you can guard against it and fail fast by adding the following `CoreModule` constructor.
|
||||||
|
|
||||||
|
|
||||||
<code-example path="ngmodule/src/app/core/core.module.ts" region="ctor" linenums="false">
|
<code-example path="ngmodule/src/app/core/core.module.ts" region="ctor" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
|
@ -53,6 +53,7 @@ The `package.json` includes two sets of packages,
|
|||||||
The *dependencies* are essential to *running* the application.
|
The *dependencies* are essential to *running* the application.
|
||||||
The *devDependencies* are only necessary to *develop* the application.
|
The *devDependencies* are only necessary to *develop* the application.
|
||||||
You can exclude them from production installations by adding `--production` to the install command, as follows:
|
You can exclude them from production installations by adding `--production` to the install command, as follows:
|
||||||
|
|
||||||
<code-example format="." language="bash">
|
<code-example format="." language="bash">
|
||||||
npm install my-application --production
|
npm install my-application --production
|
||||||
|
|
||||||
|
@ -31,6 +31,7 @@ In this page, you'll use pipes to transform a component's birthday property into
|
|||||||
a human-friendly date.
|
a human-friendly date.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="pipes/src/app/hero-birthday1.component.ts" linenums="false">
|
<code-example path="pipes/src/app/hero-birthday1.component.ts" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -38,6 +39,7 @@ a human-friendly date.
|
|||||||
Focus on the component's template.
|
Focus on the component's template.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="pipes/src/app/app.component.html" region="hero-birthday-template" linenums="false">
|
<code-example path="pipes/src/app/app.component.html" region="hero-birthday-template" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -52,6 +54,7 @@ function on the right. All pipes work this way.
|
|||||||
The `Date` and `Currency` pipes need the *ECMAScript Internationalization API*.
|
The `Date` and `Currency` pipes need the *ECMAScript Internationalization API*.
|
||||||
Safari and other older browsers don't support it. You can add support with a polyfill.
|
Safari and other older browsers don't support it. You can add support with a polyfill.
|
||||||
|
|
||||||
|
|
||||||
<code-example language="html">
|
<code-example language="html">
|
||||||
<script src="https://cdn.polyfill.io/v2/polyfill.min.js?features=Intl.~locale.en"></script>
|
<script src="https://cdn.polyfill.io/v2/polyfill.min.js?features=Intl.~locale.en"></script>
|
||||||
|
|
||||||
@ -89,6 +92,7 @@ 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>**:
|
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 path="pipes/src/app/app.component.html" region="format-birthday" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -103,6 +107,7 @@ Write a second component that *binds* the pipe's format parameter
|
|||||||
to the component's `format` property. Here's the template for that component:
|
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 path="pipes/src/app/hero-birthday2.component.ts" region="template" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -112,6 +117,7 @@ That method toggles the component's `format` property between a short form
|
|||||||
(`'shortDate'`) and a longer form (`'fullDate'`).
|
(`'shortDate'`) and a longer form (`'fullDate'`).
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="pipes/src/app/hero-birthday2.component.ts" region="class" linenums="false">
|
<code-example path="pipes/src/app/hero-birthday2.component.ts" region="class" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -120,6 +126,7 @@ As you click the button, the displayed date alternates between
|
|||||||
"**<samp>04/15/1988</samp>**" and
|
"**<samp>04/15/1988</samp>**" and
|
||||||
"**<samp>Friday, April 15, 1988</samp>**".
|
"**<samp>Friday, April 15, 1988</samp>**".
|
||||||
|
|
||||||
|
|
||||||
<figure class='image-display'>
|
<figure class='image-display'>
|
||||||
<img src='assets/images/devguide/pipes/date-format-toggle-anim.gif' alt="Date Format Toggle"> </img>
|
<img src='assets/images/devguide/pipes/date-format-toggle-anim.gif' alt="Date Format Toggle"> </img>
|
||||||
</figure>
|
</figure>
|
||||||
@ -142,6 +149,7 @@ the birthday is chained to the `DatePipe` and on to the `UpperCasePipe`.
|
|||||||
The birthday displays as **<samp>APR 15, 1988</samp>**.
|
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 path="pipes/src/app/app.component.html" region="chained-birthday" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -150,6 +158,7 @@ This example—which displays **<samp>FRIDAY, APRIL 15, 1988</samp>**—
|
|||||||
the same pipes as above, but passes in a parameter to `date` as well.
|
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 path="pipes/src/app/app.component.html" region="chained-parameter-birthday" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -161,6 +170,7 @@ You can write your own custom pipes.
|
|||||||
Here's a custom pipe named `ExponentialStrengthPipe` that can boost a hero's powers:
|
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 path="pipes/src/app/exponential-strength.pipe.ts" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -192,11 +202,13 @@ Technically, it's optional; Angular looks for and executes the `transform` metho
|
|||||||
|
|
||||||
Now you need a component to demonstrate the pipe.
|
Now you need a component to demonstrate the pipe.
|
||||||
|
|
||||||
|
|
||||||
<code-example path="pipes/src/app/power-booster.component.ts" linenums="false">
|
<code-example path="pipes/src/app/power-booster.component.ts" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<figure class='image-display'>
|
<figure class='image-display'>
|
||||||
<img src='assets/images/devguide/pipes/power-booster.png' alt="Power Booster"> </img>
|
<img src='assets/images/devguide/pipes/power-booster.png' alt="Power Booster"> </img>
|
||||||
</figure>
|
</figure>
|
||||||
@ -210,6 +222,7 @@ Note the following:
|
|||||||
~~~ {.callout.is-helpful}
|
~~~ {.callout.is-helpful}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<header>
|
<header>
|
||||||
Remember the
|
Remember the
|
||||||
</header>
|
</header>
|
||||||
@ -232,11 +245,13 @@ Upgrade the example to a "Power Boost Calculator" that combines
|
|||||||
your pipe and two-way data binding with `ngModel`.
|
your pipe and two-way data binding with `ngModel`.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="pipes/src/app/power-boost-calculator.component.ts">
|
<code-example path="pipes/src/app/power-boost-calculator.component.ts">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<figure class='image-display'>
|
<figure class='image-display'>
|
||||||
<img src='assets/images/devguide/pipes/power-boost-calculator-anim.gif' alt="Power Boost Calculator"> </img>
|
<img src='assets/images/devguide/pipes/power-boost-calculator-anim.gif' alt="Power Boost Calculator"> </img>
|
||||||
</figure>
|
</figure>
|
||||||
@ -259,12 +274,14 @@ In the next example, the component uses the default, aggressive change detection
|
|||||||
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 path="pipes/src/app/flying-heroes.component.html" region="template-1" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</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 path="pipes/src/app/flying-heroes.component.ts" region="v1" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -277,12 +294,14 @@ If you added the ability to remove or change a hero, Angular would detect those
|
|||||||
|
|
||||||
Add a `FlyingHeroesPipe` to the `*ngFor` repeater that filters the list of heroes to just those heroes who can fly.
|
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 path="pipes/src/app/flying-heroes.component.html" region="template-flying-heroes" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
|
|
||||||
Here's the `FlyingHeroesPipe` implementation, which follows the pattern for custom pipes described earlier.
|
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 path="pipes/src/app/flying-heroes.pipe.ts" region="pure" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -295,6 +314,7 @@ It's just using a different change-detection algorithm that ignores changes to t
|
|||||||
|
|
||||||
Notice how a hero is added:
|
Notice how a hero is added:
|
||||||
|
|
||||||
|
|
||||||
<code-example path="pipes/src/app/flying-heroes.component.ts" region="push" linenums="false">
|
<code-example path="pipes/src/app/flying-heroes.component.ts" region="push" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -311,6 +331,7 @@ if you *replace* the #{_array}, the pipe executes and the display is updated.
|
|||||||
The Flying Heroes application extends the
|
The Flying Heroes application extends the
|
||||||
code with checkbox switches and additional displays to help you experience these effects.
|
code with checkbox switches and additional displays to help you experience these effects.
|
||||||
|
|
||||||
|
|
||||||
<figure class='image-display'>
|
<figure class='image-display'>
|
||||||
<img src='assets/images/devguide/pipes/flying-heroes-anim.gif' alt="Flying Heroes"> </img>
|
<img src='assets/images/devguide/pipes/flying-heroes-anim.gif' alt="Flying Heroes"> </img>
|
||||||
</figure>
|
</figure>
|
||||||
@ -338,6 +359,7 @@ You make a pipe impure by setting its pure flag to false. You could make the `Fl
|
|||||||
impure like this:
|
impure like this:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="pipes/src/app/flying-heroes.pipe.ts" region="pipe-decorator" linenums="false">
|
<code-example path="pipes/src/app/flying-heroes.pipe.ts" region="pipe-decorator" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -385,13 +407,16 @@ An expensive, long-running pipe could destroy the user experience.
|
|||||||
A flip of the switch turns the `FlyingHeroesPipe` into a `FlyingHeroesImpurePipe`.
|
A flip of the switch turns the `FlyingHeroesPipe` into a `FlyingHeroesImpurePipe`.
|
||||||
The complete implementation is as follows:
|
The complete implementation is as follows:
|
||||||
|
|
||||||
|
|
||||||
<code-tabs>
|
<code-tabs>
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="FlyingHeroesImpurePipe" path="pipes/src/app/flying-heroes.pipe.ts" region="impure">
|
<code-pane title="FlyingHeroesImpurePipe" path="pipes/src/app/flying-heroes.pipe.ts" region="impure">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="FlyingHeroesPipe" path="pipes/src/app/flying-heroes.pipe.ts" region="pure">
|
<code-pane title="FlyingHeroesPipe" path="pipes/src/app/flying-heroes.pipe.ts" region="pure">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
@ -405,6 +430,7 @@ 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.
|
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 path="pipes/src/app/flying-heroes.pipe.ts" linenums="false" title="src/app/flying-heroes.pipe.ts (filter)" region="filter">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -412,6 +438,7 @@ This is a good candidate for an impure pipe because the `transform` function is
|
|||||||
You can derive a `FlyingHeroesImpureComponent` from `FlyingHeroesComponent`.
|
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" linenums="false" title="src/app/flying-heroes (_region)" region="_region">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -420,6 +447,7 @@ The only substantive change is the pipe in the template.
|
|||||||
You can confirm in the <live-example></live-example> that the _flying heroes_
|
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'>
|
<h3 id='async-pipe'>
|
||||||
The impure <i> AsyncPipe </i>
|
The impure <i> AsyncPipe </i>
|
||||||
</h3>
|
</h3>
|
||||||
@ -436,6 +464,7 @@ This next example binds an `#{_Observable}` of message strings
|
|||||||
(`message#{_dollar}`) to a view with the `async` pipe.
|
(`message#{_dollar}`) to a view with the `async` pipe.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="pipes/src/app/hero-async-message.component.ts">
|
<code-example path="pipes/src/app/hero-async-message.component.ts">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -457,6 +486,7 @@ In the following code, the pipe only calls the server when the request URL chang
|
|||||||
The code<span if-docs="ts"> uses the [Angular http](guide/server-communication) client to retrieve data</span>:
|
The code<span if-docs="ts"> uses the [Angular http](guide/server-communication) client to retrieve data</span>:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="pipes/src/app/fetch-json.pipe.ts">
|
<code-example path="pipes/src/app/fetch-json.pipe.ts">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -465,12 +495,14 @@ Now demonstrate it in a harness component whose template defines two bindings to
|
|||||||
both requesting the heroes from the `heroes.json` file.
|
both requesting the heroes from the `heroes.json` file.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="pipes/src/app/hero-list.component.ts">
|
<code-example path="pipes/src/app/hero-list.component.ts">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
|
|
||||||
The component renders as the following:
|
The component renders as the following:
|
||||||
|
|
||||||
|
|
||||||
<figure class='image-display'>
|
<figure class='image-display'>
|
||||||
<img src='assets/images/devguide/pipes/hero-list.png' alt="Hero List"> </img>
|
<img src='assets/images/devguide/pipes/hero-list.png' alt="Hero List"> </img>
|
||||||
</figure>
|
</figure>
|
||||||
@ -489,6 +521,7 @@ It displays the same hero data in JSON format by chaining through to the built-i
|
|||||||
~~~ {.callout.is-helpful}
|
~~~ {.callout.is-helpful}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<header>
|
<header>
|
||||||
Debugging with the json pipe
|
Debugging with the json pipe
|
||||||
</header>
|
</header>
|
||||||
@ -550,6 +583,7 @@ by offering `filter` and `orderBy` in the first place.
|
|||||||
|
|
||||||
The minification hazard is also compelling, if less obvious. Imagine a sorting pipe applied to a list of heroes.
|
The minification hazard is also compelling, if less obvious. Imagine a sorting pipe applied to a list of heroes.
|
||||||
The list might be sorted by hero `name` and `planet` of origin properties in the following way:
|
The list might be sorted by hero `name` and `planet` of origin properties in the following way:
|
||||||
|
|
||||||
<code-example language="html">
|
<code-example language="html">
|
||||||
<!-- NOT REAL CODE! -->
|
<!-- NOT REAL CODE! -->
|
||||||
<div *ngFor="let hero of heroes | orderBy:'name,planet'"></div>
|
<div *ngFor="let hero of heroes | orderBy:'name,planet'"></div>
|
||||||
|
@ -159,6 +159,7 @@ You'll need a `hero` class and some hero data.
|
|||||||
Create a new `data-model.ts` file in the `app` directory and copy the content below into it.
|
Create a new `data-model.ts` file in the `app` directory and copy the content below into it.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="reactive-forms/src/app/data-model.ts" linenums="false">
|
<code-example path="reactive-forms/src/app/data-model.ts" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -175,6 +176,7 @@ Make a new file called
|
|||||||
`hero-detail.component.ts` in the `app` directory and import these symbols:
|
`hero-detail.component.ts` in the `app` directory and import these symbols:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="reactive-forms/src/app/hero-detail-1.component.ts" region="imports" linenums="false">
|
<code-example path="reactive-forms/src/app/hero-detail-1.component.ts" region="imports" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -182,6 +184,7 @@ Make a new file called
|
|||||||
Now enter the `@Component` decorator that specifies the `HeroDetailComponent` metadata:
|
Now enter the `@Component` decorator that specifies the `HeroDetailComponent` metadata:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="reactive-forms/src/app/hero-detail.component.ts" region="metadata" linenums="false">
|
<code-example path="reactive-forms/src/app/hero-detail.component.ts" region="metadata" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -192,6 +195,7 @@ a `FormControl` instance directly.
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="reactive-forms/src/app/hero-detail-1.component.ts" region="v1" linenums="false">
|
<code-example path="reactive-forms/src/app/hero-detail-1.component.ts" region="v1" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -223,6 +227,7 @@ read the [Form Validation](cookbook/form-validation) cookbook.
|
|||||||
Now create the component's template, `src/app/hero-detail.component.html`, with the following markup.
|
Now create the component's template, `src/app/hero-detail.component.html`, with the following markup.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="reactive-forms/src/app/hero-detail-1.component.html" region="simple-control" linenums="false">
|
<code-example path="reactive-forms/src/app/hero-detail-1.component.html" region="simple-control" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -259,6 +264,7 @@ the `ReactiveFormsModule` and the `HeroDetailComponent`.
|
|||||||
1. Add `HeroDetailComponent` to the declarations array.
|
1. Add `HeroDetailComponent` to the declarations array.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="reactive-forms/src/app/app.module.ts" region="v1" linenums="false">
|
<code-example path="reactive-forms/src/app/app.module.ts" region="v1" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -270,6 +276,7 @@ the `ReactiveFormsModule` and the `HeroDetailComponent`.
|
|||||||
## Display the _HeroDetailComponent_
|
## Display the _HeroDetailComponent_
|
||||||
Revise the `AppComponent` template so it displays the `HeroDetailComponent`.
|
Revise the `AppComponent` template so it displays the `HeroDetailComponent`.
|
||||||
|
|
||||||
|
|
||||||
<code-example path="reactive-forms/src/app/app.component.1.ts" linenums="false">
|
<code-example path="reactive-forms/src/app/app.component.1.ts" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -304,12 +311,14 @@ You used bootstrap CSS classes in the template HTML of both the `AppComponent` a
|
|||||||
Add the `bootstrap` _CSS stylesheet_ to the head of `index.html`:
|
Add the `bootstrap` _CSS stylesheet_ to the head of `index.html`:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="reactive-forms/src/index.html" region="bootstrap" linenums="false">
|
<code-example path="reactive-forms/src/index.html" region="bootstrap" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
|
|
||||||
Now that everything is wired up, the browser should display something like this:
|
Now that everything is wired up, the browser should display something like this:
|
||||||
|
|
||||||
|
|
||||||
<figure class='image-display'>
|
<figure class='image-display'>
|
||||||
<img src="assets/images/devguide/reactive-forms/just-formcontrol.png" width="400px" alt="Single FormControl"> </img>
|
<img src="assets/images/devguide/reactive-forms/just-formcontrol.png" width="400px" alt="Single FormControl"> </img>
|
||||||
</figure>
|
</figure>
|
||||||
@ -324,6 +333,7 @@ This is simple to do. To add a `FormGroup`, add it to the imports section
|
|||||||
of `hero-detail.component.ts`:
|
of `hero-detail.component.ts`:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="reactive-forms/src/app/hero-detail-2.component.ts" region="imports" linenums="false">
|
<code-example path="reactive-forms/src/app/hero-detail-2.component.ts" region="imports" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -331,6 +341,7 @@ of `hero-detail.component.ts`:
|
|||||||
In the class, wrap the `FormControl` in a `FormGroup` called `heroForm` as follows:
|
In the class, wrap the `FormControl` in a `FormGroup` called `heroForm` as follows:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="reactive-forms/src/app/hero-detail-2.component.ts" region="v2" linenums="false">
|
<code-example path="reactive-forms/src/app/hero-detail-2.component.ts" region="v2" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -339,6 +350,7 @@ Now that you've made changes in the class, they need to be reflected in the
|
|||||||
template. Update `hero-detail.component.html` by replacing it with the following.
|
template. Update `hero-detail.component.html` by replacing it with the following.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="reactive-forms/src/app/hero-detail-2.component.html" region="basic-form" linenums="false">
|
<code-example path="reactive-forms/src/app/hero-detail-2.component.html" region="basic-form" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -390,6 +402,7 @@ To see the form model, add the following line after the
|
|||||||
closing `form` tag in the `hero-detail.component.html`:
|
closing `form` tag in the `hero-detail.component.html`:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="reactive-forms/src/app/hero-detail-3.component.html" region="form-value-json" linenums="false">
|
<code-example path="reactive-forms/src/app/hero-detail-3.component.html" region="form-value-json" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -397,6 +410,7 @@ closing `form` tag in the `hero-detail.component.html`:
|
|||||||
The `heroForm.value` returns the _form model_.
|
The `heroForm.value` returns the _form model_.
|
||||||
Piping it through the `JsonPipe` renders the model as JSON in the browser:
|
Piping it through the `JsonPipe` renders the model as JSON in the browser:
|
||||||
|
|
||||||
|
|
||||||
<figure class='image-display'>
|
<figure class='image-display'>
|
||||||
<img src="assets/images/devguide/reactive-forms/json-output.png" width="400px" alt="JSON output"> </img>
|
<img src="assets/images/devguide/reactive-forms/json-output.png" width="400px" alt="JSON output"> </img>
|
||||||
</figure>
|
</figure>
|
||||||
@ -421,6 +435,7 @@ clutter by handling details of control creation for you.
|
|||||||
|
|
||||||
To use `FormBuilder`, you need to import it into `hero-detail.component.ts`:
|
To use `FormBuilder`, you need to import it into `hero-detail.component.ts`:
|
||||||
|
|
||||||
|
|
||||||
<code-example path="reactive-forms/src/app/hero-detail-3a.component.ts" region="imports" linenums="false">
|
<code-example path="reactive-forms/src/app/hero-detail-3a.component.ts" region="imports" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -435,6 +450,7 @@ by following this plan:
|
|||||||
|
|
||||||
The revised `HeroDetailComponent` looks like this:
|
The revised `HeroDetailComponent` looks like this:
|
||||||
|
|
||||||
|
|
||||||
<code-example path="reactive-forms/src/app/hero-detail-3a.component.ts" region="v3a" linenums="false">
|
<code-example path="reactive-forms/src/app/hero-detail-3a.component.ts" region="v3a" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -454,6 +470,7 @@ demonstrates the simplicity of using `Validators.required` in reactive forms.
|
|||||||
|
|
||||||
First, import the `Validators` symbol.
|
First, import the `Validators` symbol.
|
||||||
|
|
||||||
|
|
||||||
<code-example path="reactive-forms/src/app/hero-detail-3.component.ts" region="imports" linenums="false">
|
<code-example path="reactive-forms/src/app/hero-detail-3.component.ts" region="imports" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -464,6 +481,7 @@ The first item is the initial value for `name`;
|
|||||||
the second is the required validator, `Validators.required`.
|
the second is the required validator, `Validators.required`.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="reactive-forms/src/app/hero-detail-3.component.ts" region="required" linenums="false">
|
<code-example path="reactive-forms/src/app/hero-detail-3.component.ts" region="required" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -480,12 +498,14 @@ Configuring validation is harder in template-driven forms where you must wrap va
|
|||||||
Update the diagnostic message at the bottom of the template to display the form's validity status.
|
Update the diagnostic message at the bottom of the template to display the form's validity status.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="reactive-forms/src/app/hero-detail-3.component.html" region="form-value-json" linenums="false">
|
<code-example path="reactive-forms/src/app/hero-detail-3.component.html" region="form-value-json" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
|
|
||||||
The browser displays the following:
|
The browser displays the following:
|
||||||
|
|
||||||
|
|
||||||
<figure class='image-display'>
|
<figure class='image-display'>
|
||||||
<img src="assets/images/devguide/reactive-forms/validators-json-output.png" width="400px" alt="Single FormControl"> </img>
|
<img src="assets/images/devguide/reactive-forms/validators-json-output.png" width="400px" alt="Single FormControl"> </img>
|
||||||
</figure>
|
</figure>
|
||||||
@ -506,6 +526,7 @@ A hero has an address, a super power and sometimes a sidekick too.
|
|||||||
The address has a state property. The user will select a state with a `<select>` box and you'll populate
|
The address has a state property. The user will select a state with a `<select>` box and you'll populate
|
||||||
the `<option>` elements with states. So import `states` from `data-model.ts`.
|
the `<option>` elements with states. So import `states` from `data-model.ts`.
|
||||||
|
|
||||||
|
|
||||||
<code-example path="reactive-forms/src/app/hero-detail-4.component.ts" region="imports" linenums="false">
|
<code-example path="reactive-forms/src/app/hero-detail-4.component.ts" region="imports" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -513,6 +534,7 @@ the `<option>` elements with states. So import `states` from `data-model.ts`.
|
|||||||
Declare the `states` property and add some address `FormControls` to the `heroForm` as follows.
|
Declare the `states` property and add some address `FormControls` to the `heroForm` as follows.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="reactive-forms/src/app/hero-detail-4.component.ts" region="v4" linenums="false">
|
<code-example path="reactive-forms/src/app/hero-detail-4.component.ts" region="v4" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -521,6 +543,7 @@ Then add corresponding markup in `hero-detail.component.html`
|
|||||||
within the `form` element.
|
within the `form` element.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="reactive-forms/src/app/hero-detail-4.component.html" linenums="false">
|
<code-example path="reactive-forms/src/app/hero-detail-4.component.html" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -572,6 +595,7 @@ Let that be the parent `FormGroup`.
|
|||||||
Use `FormBuilder` again to create a child `FormGroup` that encapsulates the address controls;
|
Use `FormBuilder` again to create a child `FormGroup` that encapsulates the address controls;
|
||||||
assign the result to a new `address` property of the parent `FormGroup`.
|
assign the result to a new `address` property of the parent `FormGroup`.
|
||||||
|
|
||||||
|
|
||||||
<code-example path="reactive-forms/src/app/hero-detail-5.component.ts" region="v5" linenums="false">
|
<code-example path="reactive-forms/src/app/hero-detail-5.component.ts" region="v5" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -587,6 +611,7 @@ To make this change visually obvious, slip in an `<h4>` header near the top with
|
|||||||
The new _address_ HTML looks like this:
|
The new _address_ HTML looks like this:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="reactive-forms/src/app/hero-detail-5.component.html" region="add-group" linenums="false">
|
<code-example path="reactive-forms/src/app/hero-detail-5.component.html" region="add-group" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -594,6 +619,7 @@ The new _address_ HTML looks like this:
|
|||||||
After these changes, the JSON output in the browser shows the revised _form model_
|
After these changes, the JSON output in the browser shows the revised _form model_
|
||||||
with the nested address `FormGroup`:
|
with the nested address `FormGroup`:
|
||||||
|
|
||||||
|
|
||||||
<figure class='image-display'>
|
<figure class='image-display'>
|
||||||
<img src="assets/images/devguide/reactive-forms/address-group.png" width="400px" alt="JSON output"> </img>
|
<img src="assets/images/devguide/reactive-forms/address-group.png" width="400px" alt="JSON output"> </img>
|
||||||
</figure>
|
</figure>
|
||||||
@ -614,6 +640,7 @@ page by adding the following to the template,
|
|||||||
immediately after the `{{form.value | json}}` interpolation as follows:
|
immediately after the `{{form.value | json}}` interpolation as follows:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="reactive-forms/src/app/hero-detail-5.component.html" region="inspect-value" linenums="false">
|
<code-example path="reactive-forms/src/app/hero-detail-5.component.html" region="inspect-value" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -621,36 +648,44 @@ immediately after the `{{form.value | json}}` interpolation as follows:
|
|||||||
To get the state of a `FormControl` that’s inside a `FormGroup`, use dot notation to path to the control.
|
To get the state of a `FormControl` that’s inside a `FormGroup`, use dot notation to path to the control.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="reactive-forms/src/app/hero-detail-5.component.html" region="inspect-child-control" linenums="false">
|
<code-example path="reactive-forms/src/app/hero-detail-5.component.html" region="inspect-child-control" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
|
|
||||||
You can use this technique to display _any_ property of a `FormControl`
|
You can use this technique to display _any_ property of a `FormControl`
|
||||||
such as one of the following:
|
such as one of the following:
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
td, th {vertical-align: top}
|
td, th {vertical-align: top}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<table width="100%">
|
<table width="100%">
|
||||||
|
|
||||||
|
|
||||||
<col width="10%">
|
<col width="10%">
|
||||||
|
|
||||||
</col>
|
</col>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<col width="90%">
|
<col width="90%">
|
||||||
|
|
||||||
</col>
|
</col>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
|
|
||||||
|
|
||||||
<th>
|
<th>
|
||||||
Property
|
Property
|
||||||
</th>
|
</th>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<th>
|
<th>
|
||||||
Description
|
Description
|
||||||
</th>
|
</th>
|
||||||
@ -659,13 +694,16 @@ such as one of the following:
|
|||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
<code>myControl.value</code>
|
<code>myControl.value</code>
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
the value of a `FormControl`.
|
the value of a `FormControl`.
|
||||||
</td>
|
</td>
|
||||||
@ -674,13 +712,16 @@ such as one of the following:
|
|||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
<code>myControl.status</code>
|
<code>myControl.status</code>
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
the validity of a `FormControl`. Possible values: `VALID`,
|
the validity of a `FormControl`. Possible values: `VALID`,
|
||||||
`INVALID`, `PENDING`, or `DISABLED`.
|
`INVALID`, `PENDING`, or `DISABLED`.
|
||||||
@ -690,13 +731,16 @@ such as one of the following:
|
|||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
<code>myControl.pristine</code>
|
<code>myControl.pristine</code>
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
`true` if the user has _not_ changed the value in the UI.
|
`true` if the user has _not_ changed the value in the UI.
|
||||||
Its opposite is `myControl.dirty`.
|
Its opposite is `myControl.dirty`.
|
||||||
@ -706,13 +750,16 @@ such as one of the following:
|
|||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
<code>myControl.untouched</code>
|
<code>myControl.untouched</code>
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
`true` if the control user has not yet entered the HTML control
|
`true` if the control user has not yet entered the HTML control
|
||||||
and triggered its blur event. Its opposite is `myControl.touched`.
|
and triggered its blur event. Its opposite is `myControl.touched`.
|
||||||
@ -764,6 +811,7 @@ In this `HeroDetailComponent`, the two models are quite close.
|
|||||||
|
|
||||||
Recall the definition of `Hero` in `data-model.ts`:
|
Recall the definition of `Hero` in `data-model.ts`:
|
||||||
|
|
||||||
|
|
||||||
<code-example path="reactive-forms/src/app/data-model.ts" region="model-classes" linenums="false">
|
<code-example path="reactive-forms/src/app/data-model.ts" region="model-classes" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -771,6 +819,7 @@ Recall the definition of `Hero` in `data-model.ts`:
|
|||||||
Here, again, is the component's `FormGroup` definition.
|
Here, again, is the component's `FormGroup` definition.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="reactive-forms/src/app/hero-detail-6.component.ts" region="hero-form-model" linenums="false">
|
<code-example path="reactive-forms/src/app/hero-detail-6.component.ts" region="hero-form-model" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -786,12 +835,14 @@ Nonetheless, the two models are pretty close in shape and you'll see in a moment
|
|||||||
to the _form model_ with the `patchValue` and `setValue` methods.
|
to the _form model_ with the `patchValue` and `setValue` methods.
|
||||||
Take a moment to refactor the _address_ `FormGroup` definition for brevity and clarity as follows:
|
Take a moment to refactor the _address_ `FormGroup` definition for brevity and clarity as follows:
|
||||||
|
|
||||||
|
|
||||||
<code-example path="reactive-forms/src/app/hero-detail-7.component.ts" region="address-form-group" linenums="false">
|
<code-example path="reactive-forms/src/app/hero-detail-7.component.ts" region="address-form-group" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
|
|
||||||
Also be sure to update the import from `data-model` so you can reference the `Hero` and `Address` classes:
|
Also be sure to update the import from `data-model` so you can reference the `Hero` and `Address` classes:
|
||||||
|
|
||||||
|
|
||||||
<code-example path="reactive-forms/src/app/hero-detail-7.component.ts" region="import-address" linenums="false">
|
<code-example path="reactive-forms/src/app/hero-detail-7.component.ts" region="import-address" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -810,6 +861,7 @@ With **`setValue`**, you assign _every_ form control value _at once_
|
|||||||
by passing in a data object whose properties exactly match the _form model_ behind the `FormGroup`.
|
by passing in a data object whose properties exactly match the _form model_ behind the `FormGroup`.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="reactive-forms/src/app/hero-detail-7.component.ts" region="set-value" linenums="false">
|
<code-example path="reactive-forms/src/app/hero-detail-7.component.ts" region="set-value" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -830,6 +882,7 @@ because its shape is similar to the component's `FormGroup` structure.
|
|||||||
You can only show the hero's first address and you must account for the possibility that the `hero` has no addresses at all.
|
You can only show the hero's first address and you must account for the possibility that the `hero` has no addresses at all.
|
||||||
This explains the conditional setting of the `address` property in the data object argument:
|
This explains the conditional setting of the `address` property in the data object argument:
|
||||||
|
|
||||||
|
|
||||||
<code-example path="reactive-forms/src/app/hero-detail-7.component.ts" region="set-value-address" linenums="false">
|
<code-example path="reactive-forms/src/app/hero-detail-7.component.ts" region="set-value-address" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -840,6 +893,7 @@ by supplying an object of key/value pairs for just the controls of interest.
|
|||||||
|
|
||||||
This example sets only the form's `name` control.
|
This example sets only the form's `name` control.
|
||||||
|
|
||||||
|
|
||||||
<code-example path="reactive-forms/src/app/hero-detail-6.component.ts" region="patch-value" linenums="false">
|
<code-example path="reactive-forms/src/app/hero-detail-6.component.ts" region="patch-value" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -859,6 +913,7 @@ When the user clicks on a hero, the list component passes the selected hero into
|
|||||||
by binding to its `hero` input property.
|
by binding to its `hero` input property.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="reactive-forms/src/app/hero-list.component.1.html" linenums="false">
|
<code-example path="reactive-forms/src/app/hero-list.component.1.html" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -872,12 +927,14 @@ as the following steps demonstrate.
|
|||||||
First, import the `OnChanges` and `Input` symbols in `hero-detail.component.ts`.
|
First, import the `OnChanges` and `Input` symbols in `hero-detail.component.ts`.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="reactive-forms/src/app/hero-detail-6.component.ts" region="import-input" linenums="false">
|
<code-example path="reactive-forms/src/app/hero-detail-6.component.ts" region="import-input" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
|
|
||||||
Add the `hero` input property.
|
Add the `hero` input property.
|
||||||
|
|
||||||
|
|
||||||
<code-example path="reactive-forms/src/app/hero-detail-6.component.ts" region="hero" linenums="false">
|
<code-example path="reactive-forms/src/app/hero-detail-6.component.ts" region="hero" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -885,6 +942,7 @@ Add the `hero` input property.
|
|||||||
Add the `ngOnChanges` method to the class as follows:
|
Add the `ngOnChanges` method to the class as follows:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="reactive-forms/src/app/hero-detail-7.component.ts" region="ngOnChanges-1" linenums="false">
|
<code-example path="reactive-forms/src/app/hero-detail-7.component.ts" region="ngOnChanges-1" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -896,6 +954,7 @@ control values from the previous hero are cleared and
|
|||||||
status flags are restored to the _pristine_ state.
|
status flags are restored to the _pristine_ state.
|
||||||
You could call `reset` at the top of `ngOnChanges` like this.
|
You could call `reset` at the top of `ngOnChanges` like this.
|
||||||
|
|
||||||
|
|
||||||
<code-example path="reactive-forms/src/app/hero-detail-7.component.ts" region="reset" linenums="false">
|
<code-example path="reactive-forms/src/app/hero-detail-7.component.ts" region="reset" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -904,6 +963,7 @@ The `reset` method has an optional `state` value so you can reset the flags _and
|
|||||||
Internally, `reset` passes the argument to `setValue`.
|
Internally, `reset` passes the argument to `setValue`.
|
||||||
A little refactoring and `ngOnChanges` becomes this:
|
A little refactoring and `ngOnChanges` becomes this:
|
||||||
|
|
||||||
|
|
||||||
<code-example path="reactive-forms/src/app/hero-detail-7.component.ts" region="ngOnChanges" linenums="false">
|
<code-example path="reactive-forms/src/app/hero-detail-7.component.ts" region="ngOnChanges" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -916,6 +976,7 @@ A little refactoring and `ngOnChanges` becomes this:
|
|||||||
The `HeroDetailComponent` is a nested sub-component of the `HeroListComponent` in a _master/detail_ view.
|
The `HeroDetailComponent` is a nested sub-component of the `HeroListComponent` in a _master/detail_ view.
|
||||||
Together they look a bit like this:
|
Together they look a bit like this:
|
||||||
|
|
||||||
|
|
||||||
<figure class='image-display'>
|
<figure class='image-display'>
|
||||||
<img src="assets/images/devguide/reactive-forms/hero-list.png" width="420px" alt="HeroListComponent"> </img>
|
<img src="assets/images/devguide/reactive-forms/hero-list.png" width="420px" alt="HeroListComponent"> </img>
|
||||||
</figure>
|
</figure>
|
||||||
@ -962,6 +1023,7 @@ An Angular `FormArray` can display an array of _address_ `FormGroups`.
|
|||||||
|
|
||||||
To get access to the `FormArray` class, import it into `hero-detail.component.ts`:
|
To get access to the `FormArray` class, import it into `hero-detail.component.ts`:
|
||||||
|
|
||||||
|
|
||||||
<code-example path="reactive-forms/src/app/hero-detail-8.component.ts" region="imports" linenums="false">
|
<code-example path="reactive-forms/src/app/hero-detail-8.component.ts" region="imports" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -977,6 +1039,7 @@ let the user add or modify addresses (removing addresses is your homework).
|
|||||||
You’ll need to redefine the form model in the `HeroDetailComponent` constructor,
|
You’ll need to redefine the form model in the `HeroDetailComponent` constructor,
|
||||||
which currently only displays the first hero address in an _address_ `FormGroup`.
|
which currently only displays the first hero address in an _address_ `FormGroup`.
|
||||||
|
|
||||||
|
|
||||||
<code-example path="reactive-forms/src/app/hero-detail-7.component.ts" region="address-form-group" linenums="false">
|
<code-example path="reactive-forms/src/app/hero-detail-7.component.ts" region="address-form-group" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -987,6 +1050,7 @@ From the user's point of view, heroes don't have _addresses_.
|
|||||||
_Addresses_ are for mere mortals. Heroes have _secret lairs_!
|
_Addresses_ are for mere mortals. Heroes have _secret lairs_!
|
||||||
Replace the _address_ `FormGroup` definition with a _secretLairs_ `FormArray` definition:
|
Replace the _address_ `FormGroup` definition with a _secretLairs_ `FormArray` definition:
|
||||||
|
|
||||||
|
|
||||||
<code-example path="reactive-forms/src/app/hero-detail-8.component.ts" region="secretLairs-form-array" linenums="false">
|
<code-example path="reactive-forms/src/app/hero-detail-8.component.ts" region="secretLairs-form-array" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -1017,6 +1081,7 @@ the parent `HeroListComponent` sets the `HeroListComponent.hero` input property
|
|||||||
The following `setAddresses` method replaces the _secretLairs_ `FormArray` with a new `FormArray`,
|
The following `setAddresses` method replaces the _secretLairs_ `FormArray` with a new `FormArray`,
|
||||||
initialized by an array of hero address `FormGroups`.
|
initialized by an array of hero address `FormGroups`.
|
||||||
|
|
||||||
|
|
||||||
<code-example path="reactive-forms/src/app/hero-detail-8.component.ts" region="set-addresses" linenums="false">
|
<code-example path="reactive-forms/src/app/hero-detail-8.component.ts" region="set-addresses" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -1032,6 +1097,7 @@ The `HeroDetailComponent` should be able to display, add, and remove items from
|
|||||||
Use the `FormGroup.get` method to acquire a reference to that `FormArray`.
|
Use the `FormGroup.get` method to acquire a reference to that `FormArray`.
|
||||||
Wrap the expression in a `secretLairs` convenience property for clarity and re-use.
|
Wrap the expression in a `secretLairs` convenience property for clarity and re-use.
|
||||||
|
|
||||||
|
|
||||||
<code-example path="reactive-forms/src/app/hero-detail-8.component.ts" region="get-secret-lairs" linenums="false">
|
<code-example path="reactive-forms/src/app/hero-detail-8.component.ts" region="get-secret-lairs" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -1058,12 +1124,14 @@ You'll re-use that index to compose a unique label for each address.
|
|||||||
|
|
||||||
Here's the skeleton for the _secret lairs_ section of the HTML template:
|
Here's the skeleton for the _secret lairs_ section of the HTML template:
|
||||||
|
|
||||||
|
|
||||||
<code-example path="reactive-forms/src/app/hero-detail-8.component.html" region="form-array-skeleton" linenums="false">
|
<code-example path="reactive-forms/src/app/hero-detail-8.component.html" region="form-array-skeleton" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
|
|
||||||
Here's the complete template for the _secret lairs_ section:
|
Here's the complete template for the _secret lairs_ section:
|
||||||
|
|
||||||
|
|
||||||
<code-example path="reactive-forms/src/app/hero-detail-8.component.html" region="form-array">
|
<code-example path="reactive-forms/src/app/hero-detail-8.component.html" region="form-array">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -1072,6 +1140,7 @@ Here's the complete template for the _secret lairs_ section:
|
|||||||
|
|
||||||
Add an `addLair` method that gets the _secretLairs_ `FormArray` and appends a new _address_ `FormGroup` to it.
|
Add an `addLair` method that gets the _secretLairs_ `FormArray` and appends a new _address_ `FormGroup` to it.
|
||||||
|
|
||||||
|
|
||||||
<code-example path="reactive-forms/src/app/hero-detail-8.component.ts" region="add-lair" linenums="false">
|
<code-example path="reactive-forms/src/app/hero-detail-8.component.ts" region="add-lair" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -1079,6 +1148,7 @@ Add an `addLair` method that gets the _secretLairs_ `FormArray` and appends a ne
|
|||||||
Place a button on the form so the user can add a new _secret lair_ and wire it to the component's `addLair` method.
|
Place a button on the form so the user can add a new _secret lair_ and wire it to the component's `addLair` method.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="reactive-forms/src/app/hero-detail-8.component.html" region="add-lair" linenums="false">
|
<code-example path="reactive-forms/src/app/hero-detail-8.component.html" region="add-lair" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -1102,6 +1172,7 @@ You do not want to save changes when the user clicks the _Add a Secret Lair_ but
|
|||||||
Back in the browser, select the hero named "Magneta".
|
Back in the browser, select the hero named "Magneta".
|
||||||
"Magneta" doesn't have an address, as you can see in the diagnostic JSON at the bottom of the form.
|
"Magneta" doesn't have an address, as you can see in the diagnostic JSON at the bottom of the form.
|
||||||
|
|
||||||
|
|
||||||
<figure class='image-display'>
|
<figure class='image-display'>
|
||||||
<img src="assets/images/devguide/reactive-forms/addresses-array.png" width="400px" alt="JSON output of addresses array"> </img>
|
<img src="assets/images/devguide/reactive-forms/addresses-array.png" width="400px" alt="JSON output of addresses array"> </img>
|
||||||
</figure>
|
</figure>
|
||||||
@ -1131,12 +1202,14 @@ You don't need to know much about RxJS `Observable` to monitor form control valu
|
|||||||
|
|
||||||
Add the following method to log changes to the value of the _name_ `FormControl`.
|
Add the following method to log changes to the value of the _name_ `FormControl`.
|
||||||
|
|
||||||
|
|
||||||
<code-example path="reactive-forms/src/app/hero-detail.component.ts" region="log-name-change" linenums="false">
|
<code-example path="reactive-forms/src/app/hero-detail.component.ts" region="log-name-change" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
|
|
||||||
Call it in the constructor, after creating the form.
|
Call it in the constructor, after creating the form.
|
||||||
|
|
||||||
|
|
||||||
<code-example path="reactive-forms/src/app/hero-detail-8.component.ts" region="ctor" linenums="false">
|
<code-example path="reactive-forms/src/app/hero-detail-8.component.ts" region="ctor" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -1144,6 +1217,7 @@ Call it in the constructor, after creating the form.
|
|||||||
The `logNameChange` method pushes name-change values into a `nameChangeLog` array.
|
The `logNameChange` method pushes name-change values into a `nameChangeLog` array.
|
||||||
Display that array at the bottom of the component template with this `*ngFor` binding:
|
Display that array at the bottom of the component template with this `*ngFor` binding:
|
||||||
|
|
||||||
|
|
||||||
<code-example path="reactive-forms/src/app/hero-detail.component.html" region="name-change-log" linenums="false">
|
<code-example path="reactive-forms/src/app/hero-detail.component.html" region="name-change-log" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -1167,6 +1241,7 @@ In a real app, you'd probably save those hero changes.
|
|||||||
In a real app, you'd also be able to revert unsaved changes and resume editing.
|
In a real app, you'd also be able to revert unsaved changes and resume editing.
|
||||||
After you implement both features in this section, the form will look like this:
|
After you implement both features in this section, the form will look like this:
|
||||||
|
|
||||||
|
|
||||||
<figure class='image-display'>
|
<figure class='image-display'>
|
||||||
<img src="assets/images/devguide/reactive-forms/save-revert-buttons.png" width="389px" alt="Form with save & revert buttons"> </img>
|
<img src="assets/images/devguide/reactive-forms/save-revert-buttons.png" width="389px" alt="Form with save & revert buttons"> </img>
|
||||||
</figure>
|
</figure>
|
||||||
@ -1176,6 +1251,7 @@ In this sample application, when the user submits the form,
|
|||||||
the `HeroDetailComponent` will pass an instance of the hero _data model_
|
the `HeroDetailComponent` will pass an instance of the hero _data model_
|
||||||
to a save method on the injected `HeroService`.
|
to a save method on the injected `HeroService`.
|
||||||
|
|
||||||
|
|
||||||
<code-example path="reactive-forms/src/app/hero-detail.component.ts" region="on-submit" linenums="false">
|
<code-example path="reactive-forms/src/app/hero-detail.component.ts" region="on-submit" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -1185,6 +1261,7 @@ So you create a new `hero` from a combination of original hero values (the `hero
|
|||||||
and deep copies of the changed form model values, using the `prepareSaveHero` helper.
|
and deep copies of the changed form model values, using the `prepareSaveHero` helper.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="reactive-forms/src/app/hero-detail.component.ts" region="prepare-save-hero" linenums="false">
|
<code-example path="reactive-forms/src/app/hero-detail.component.ts" region="prepare-save-hero" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -1210,6 +1287,7 @@ The user cancels changes and reverts the form to the original state by pressing
|
|||||||
|
|
||||||
Reverting is easy. Simply re-execute the `ngOnChanges` method that built the _form model_ from the original, unchanged `hero` _data model_.
|
Reverting is easy. Simply re-execute the `ngOnChanges` method that built the _form model_ from the original, unchanged `hero` _data model_.
|
||||||
|
|
||||||
|
|
||||||
<code-example path="reactive-forms/src/app/hero-detail.component.ts" region="revert" linenums="false">
|
<code-example path="reactive-forms/src/app/hero-detail.component.ts" region="revert" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -1217,6 +1295,7 @@ Reverting is easy. Simply re-execute the `ngOnChanges` method that built the _fo
|
|||||||
### Buttons
|
### Buttons
|
||||||
Add the "Save" and "Revert" buttons near the top of the component's template:
|
Add the "Save" and "Revert" buttons near the top of the component's template:
|
||||||
|
|
||||||
|
|
||||||
<code-example path="reactive-forms/src/app/hero-detail.component.html" region="buttons" linenums="false">
|
<code-example path="reactive-forms/src/app/hero-detail.component.html" region="buttons" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -1249,43 +1328,52 @@ This page covered:
|
|||||||
The key files of the final version are as follows:
|
The key files of the final version are as follows:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-tabs>
|
<code-tabs>
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="src/app/app.component.ts" path="reactive-forms/src/app/app.component.ts">
|
<code-pane title="src/app/app.component.ts" path="reactive-forms/src/app/app.component.ts">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="src/app/app.module.ts" path="reactive-forms/src/app/app.module.ts">
|
<code-pane title="src/app/app.module.ts" path="reactive-forms/src/app/app.module.ts">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="src/app/hero-detail.component.ts" path="reactive-forms/src/app/hero-detail.component.ts">
|
<code-pane title="src/app/hero-detail.component.ts" path="reactive-forms/src/app/hero-detail.component.ts">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="src/app/hero-detail.component.html" path="reactive-forms/src/app/hero-detail.component.html">
|
<code-pane title="src/app/hero-detail.component.html" path="reactive-forms/src/app/hero-detail.component.html">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="src/app/hero-list.component.html" path="reactive-forms/src/app/hero-list.component.html">
|
<code-pane title="src/app/hero-list.component.html" path="reactive-forms/src/app/hero-list.component.html">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="src/app/hero-list.component.ts" path="reactive-forms/src/app/hero-list.component.ts">
|
<code-pane title="src/app/hero-list.component.ts" path="reactive-forms/src/app/hero-list.component.ts">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="src/app/data-model.ts" path="reactive-forms/src/app/data-model.ts">
|
<code-pane title="src/app/data-model.ts" path="reactive-forms/src/app/data-model.ts">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="src/app/hero.service.ts" path="reactive-forms/src/app/hero.service.ts">
|
<code-pane title="src/app/hero.service.ts" path="reactive-forms/src/app/hero.service.ts">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -15,6 +15,7 @@ For more information about the attacks and mitigations described below, see [OWA
|
|||||||
You can run the <live-example></live-example> in Plunker and download the code from there.
|
You can run the <live-example></live-example> in Plunker and download the code from there.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<h2 id='report-issues'>
|
<h2 id='report-issues'>
|
||||||
Reporting vulnerabilities
|
Reporting vulnerabilities
|
||||||
</h2>
|
</h2>
|
||||||
@ -25,6 +26,7 @@ For more information about how Google handles security issues, see [Google's sec
|
|||||||
philosophy](https://www.google.com/about/appsecurity/).
|
philosophy](https://www.google.com/about/appsecurity/).
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<h2 id='best-practices'>
|
<h2 id='best-practices'>
|
||||||
Best practices
|
Best practices
|
||||||
</h2>
|
</h2>
|
||||||
@ -43,6 +45,7 @@ community and make a pull request.
|
|||||||
For more information, see the [Trusting safe values](guide/security#bypass-security-apis) section of this page.
|
For more information, see the [Trusting safe values](guide/security#bypass-security-apis) section of this page.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<h2 id='xss'>
|
<h2 id='xss'>
|
||||||
Preventing cross-site scripting (XSS)
|
Preventing cross-site scripting (XSS)
|
||||||
</h2>
|
</h2>
|
||||||
@ -94,6 +97,7 @@ 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:
|
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 path="security/src/app/inner-html-binding.component.html">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -106,6 +110,7 @@ a value that an attacker might control into `innerHTML` normally causes an XSS
|
|||||||
vulnerability. For example, code contained in a `<script>` tag is executed:
|
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 path="security/src/app/inner-html-binding.component.ts" linenums="false" title="src/app/inner-html-binding.component.ts (class)" region="class">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -114,6 +119,7 @@ vulnerability. For example, code contained in a `<script>` tag is executed:
|
|||||||
Angular recognizes the value as unsafe and automatically sanitizes it, which removes the `<script>`
|
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.
|
tag but keeps safe content such as the text content of the `<script>` tag and the `<b>` element.
|
||||||
|
|
||||||
|
|
||||||
<figure class='image-display'>
|
<figure class='image-display'>
|
||||||
<img src='assets/images/devguide/security/binding-inner-html.png' alt='A screenshot showing interpolated and bound HTML values'> </img>
|
<img src='assets/images/devguide/security/binding-inner-html.png' alt='A screenshot showing interpolated and bound HTML values'> </img>
|
||||||
</figure>
|
</figure>
|
||||||
@ -154,6 +160,7 @@ carries a high risk of introducing template-injection vulnerabilities.
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<h2 id='bypass-security-apis'>
|
<h2 id='bypass-security-apis'>
|
||||||
Trusting safe values
|
Trusting safe values
|
||||||
</h2>
|
</h2>
|
||||||
@ -179,6 +186,7 @@ your intended use of the value. Imagine that the following template needs to bin
|
|||||||
`javascript:alert(...)` call:
|
`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 path="security/src/app/bypass-security.component.html" linenums="false" title="src/app/bypass-security.component.html (URL)" region="URL">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -188,11 +196,13 @@ in development mode, logs this action to the console. To prevent
|
|||||||
this, mark the URL value as a trusted URL using the `bypassSecurityTrustUrl` call:
|
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 path="security/src/app/bypass-security.component.ts" linenums="false" title="src/app/bypass-security.component.ts (trust-url)" region="trust-url">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<figure class='image-display'>
|
<figure class='image-display'>
|
||||||
<img src='assets/images/devguide/security/bypass-security-component.png' alt='A screenshot showing an alert box created from a trusted URL'> </img>
|
<img src='assets/images/devguide/security/bypass-security-component.png' alt='A screenshot showing an alert box created from a trusted URL'> </img>
|
||||||
</figure>
|
</figure>
|
||||||
@ -205,12 +215,14 @@ could execute. So call a method on the controller to construct a trusted video U
|
|||||||
Angular to allow binding into `<iframe src>`:
|
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 path="security/src/app/bypass-security.component.html" linenums="false" title="src/app/bypass-security.component.html (iframe)" region="iframe">
|
||||||
|
|
||||||
</code-example>
|
</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 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>
|
</code-example>
|
||||||
@ -218,6 +230,7 @@ Angular to allow binding into `<iframe src>`:
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<h2 id='http'>
|
<h2 id='http'>
|
||||||
HTTP-level vulnerabilities
|
HTTP-level vulnerabilities
|
||||||
</h2>
|
</h2>
|
||||||
@ -226,6 +239,7 @@ Angular has built-in support to help prevent two common HTTP vulnerabilities, cr
|
|||||||
forgery (CSRF or XSRF) and cross-site script inclusion (XSSI). Both of these must be mitigated primarily
|
forgery (CSRF or XSRF) and cross-site script inclusion (XSSI). Both of these must be mitigated primarily
|
||||||
on the server side, but Angular provides helpers to make integration on the client side easier.
|
on the server side, but Angular provides helpers to make integration on the client side easier.
|
||||||
|
|
||||||
|
|
||||||
<h3 id='xsrf'>
|
<h3 id='xsrf'>
|
||||||
Cross-site request forgery
|
Cross-site request forgery
|
||||||
</h3>
|
</h3>
|
||||||
@ -271,12 +285,14 @@ cryptographically secure random number generator, and expire in a day or two.
|
|||||||
|
|
||||||
Your server may use a different cookie or header name for this purpose.
|
Your server may use a different cookie or header name for this purpose.
|
||||||
An Angular application can customize cookie and header names by providing its own `CookieXSRFStrategy` values.
|
An Angular application can customize cookie and header names by providing its own `CookieXSRFStrategy` values.
|
||||||
|
|
||||||
<code-example language="typescript">
|
<code-example language="typescript">
|
||||||
{ provide: XSRFStrategy, useValue: new CookieXSRFStrategy('myCookieName', 'My-Header-Name') }
|
{ provide: XSRFStrategy, useValue: new CookieXSRFStrategy('myCookieName', 'My-Header-Name') }
|
||||||
</code-example>
|
</code-example>
|
||||||
|
|
||||||
Or you can implement and provide an entirely custom `XSRFStrategy`:
|
Or you can implement and provide an entirely custom `XSRFStrategy`:
|
||||||
|
|
||||||
|
|
||||||
<code-example language="typescript">
|
<code-example language="typescript">
|
||||||
{ provide: XSRFStrategy, useClass: MyXSRFStrategy }
|
{ provide: XSRFStrategy, useClass: MyXSRFStrategy }
|
||||||
|
|
||||||
@ -291,6 +307,7 @@ The Stanford University paper
|
|||||||
See also Dave Smith's easy-to-understand
|
See also Dave Smith's easy-to-understand
|
||||||
<a href="https://www.youtube.com/watch?v=9inczw6qtpY" target="_blank" title="Cross Site Request Funkery Securing Your Angular Apps From Evil Doers">talk on XSRF at AngularConnect 2016</a>.
|
<a href="https://www.youtube.com/watch?v=9inczw6qtpY" target="_blank" title="Cross Site Request Funkery Securing Your Angular Apps From Evil Doers">talk on XSRF at AngularConnect 2016</a>.
|
||||||
|
|
||||||
|
|
||||||
<h3 id='xssi'>
|
<h3 id='xssi'>
|
||||||
Cross-site script inclusion (XSSI)
|
Cross-site script inclusion (XSSI)
|
||||||
</h3>
|
</h3>
|
||||||
@ -310,6 +327,7 @@ For more information, see the XSSI section of this [Google web security blog
|
|||||||
post](https://security.googleblog.com/2011/05/website-security-for-webmasters.html).
|
post](https://security.googleblog.com/2011/05/website-security-for-webmasters.html).
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<h2 id='code-review'>
|
<h2 id='code-review'>
|
||||||
Auditing Angular applications
|
Auditing Angular applications
|
||||||
</h2>
|
</h2>
|
||||||
|
@ -75,6 +75,7 @@ This page describes server communication with the help of the following demos:
|
|||||||
- [More fun with Observables](guide/server-communication#more-observables).
|
- [More fun with Observables](guide/server-communication#more-observables).
|
||||||
The root `AppComponent` orchestrates these demos:
|
The root `AppComponent` orchestrates these demos:
|
||||||
|
|
||||||
|
|
||||||
<code-example path="server-communication/src/app/app.component.ts">
|
<code-example path="server-communication/src/app/app.component.ts">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -99,6 +100,7 @@ Read about providers in the [Dependency Injection](guide/dependency-injection) p
|
|||||||
Register providers by importing other NgModules to the root NgModule in `app.module.ts`.
|
Register providers by importing other NgModules to the root NgModule in `app.module.ts`.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="server-communication/src/app/app.module.1.ts" linenums="false">
|
<code-example path="server-communication/src/app/app.module.1.ts" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -126,12 +128,14 @@ This version gets some heroes from the server, displays them in a list, lets the
|
|||||||
The app uses the !{_Angular_Http} client to communicate via **XMLHttpRequest (XHR)**.
|
The app uses the !{_Angular_Http} client to communicate via **XMLHttpRequest (XHR)**.
|
||||||
|
|
||||||
It works like this:
|
It works like this:
|
||||||
|
|
||||||
<figure class='image-display'>
|
<figure class='image-display'>
|
||||||
<img src='assets/images/devguide/server-communication/http-toh.gif' alt="ToH mini app" width="250"> </img>
|
<img src='assets/images/devguide/server-communication/http-toh.gif' alt="ToH mini app" width="250"> </img>
|
||||||
</figure>
|
</figure>
|
||||||
|
|
||||||
This demo has a single component, the `HeroListComponent`. Here's its template:
|
This demo has a single component, the `HeroListComponent`. Here's its template:
|
||||||
|
|
||||||
|
|
||||||
<code-example path="server-communication/src/app/toh/hero-list.component.html">
|
<code-example path="server-communication/src/app/toh/hero-list.component.html">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -154,6 +158,7 @@ Below the button is an area for an error message.
|
|||||||
### The *HeroListComponent* class
|
### The *HeroListComponent* class
|
||||||
Here's the component class:
|
Here's the component class:
|
||||||
|
|
||||||
|
|
||||||
<code-example path="server-communication/src/app/toh/hero-list.component.ts" region="component">
|
<code-example path="server-communication/src/app/toh/hero-list.component.ts" region="component">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -197,12 +202,14 @@ With a basic understanding of the component, you're ready to look inside the `He
|
|||||||
In many of the previous samples the app faked the interaction with the server by
|
In many of the previous samples the app faked the interaction with the server by
|
||||||
returning mock heroes in a service like this one:
|
returning mock heroes in a service like this one:
|
||||||
|
|
||||||
|
|
||||||
<code-example path="toh-4/src/app/hero.service.ts" region="just-get-heroes" linenums="false">
|
<code-example path="toh-4/src/app/hero.service.ts" region="just-get-heroes" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
|
|
||||||
You can revise that `HeroService` to get the heroes from the server using the !{_Angular_Http} client service:
|
You can revise that `HeroService` to get the heroes from the server using the !{_Angular_Http} client service:
|
||||||
|
|
||||||
|
|
||||||
<code-example path="server-communication/src/app/toh/hero.service.ts" region="v1">
|
<code-example path="server-communication/src/app/toh/hero.service.ts" region="v1">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -210,12 +217,14 @@ You can revise that `HeroService` to get the heroes from the server using the !{
|
|||||||
Notice that the !{_Angular_Http} client service is
|
Notice that the !{_Angular_Http} client service is
|
||||||
[injected](guide/dependency-injection) into the `HeroService` constructor.
|
[injected](guide/dependency-injection) into the `HeroService` constructor.
|
||||||
|
|
||||||
|
|
||||||
<code-example path="server-communication/src/app/toh/hero.service.ts" region="ctor">
|
<code-example path="server-communication/src/app/toh/hero.service.ts" region="ctor">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
|
|
||||||
Look closely at how to call `!{_priv}http.get`:
|
Look closely at how to call `!{_priv}http.get`:
|
||||||
|
|
||||||
|
|
||||||
<code-example path="server-communication/src/app/toh/hero.service.ts" region="http-get" linenums="false">
|
<code-example path="server-communication/src/app/toh/hero.service.ts" region="http-get" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -229,6 +238,7 @@ The server returns heroes once you've set up the [in-memory web api](guide/serve
|
|||||||
described in the appendix below.
|
described in the appendix below.
|
||||||
Alternatively, you can temporarily target a JSON file by changing the endpoint URL:
|
Alternatively, you can temporarily target a JSON file by changing the endpoint URL:
|
||||||
|
|
||||||
|
|
||||||
<code-example path="server-communication/src/app/toh/hero.service.ts" region="endpoint-json" linenums="false">
|
<code-example path="server-communication/src/app/toh/hero.service.ts" region="endpoint-json" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -244,6 +254,7 @@ Alternatively, you can temporarily target a JSON file by changing the endpoint U
|
|||||||
## Process the response object
|
## 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:
|
||||||
|
|
||||||
|
|
||||||
<code-example path="server-communication/src/app/toh/hero.service.ts" region="extract-data" linenums="false">
|
<code-example path="server-communication/src/app/toh/hero.service.ts" region="extract-data" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -314,6 +325,7 @@ but only if it says something that the user can understand and act upon.
|
|||||||
This simple app conveys that idea, albeit imperfectly, in the way it handles a `getHeroes` error.
|
This simple app conveys that idea, albeit imperfectly, in the way it handles a `getHeroes` error.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="server-communication/src/app/toh/hero.service.ts" region="error-handling" linenums="false">
|
<code-example path="server-communication/src/app/toh/hero.service.ts" region="error-handling" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -329,6 +341,7 @@ logs it to the console, and returns the message in a new, failed Observable via
|
|||||||
|
|
||||||
{@a hero-list-component}
|
{@a hero-list-component}
|
||||||
|
|
||||||
|
|
||||||
<h3>
|
<h3>
|
||||||
<b> HeroListComponent </b> error handling
|
<b> HeroListComponent </b> error handling
|
||||||
</h3>
|
</h3>
|
||||||
@ -339,6 +352,7 @@ the `subscribe` function has a second function parameter to handle the error mes
|
|||||||
It sets an `errorMessage` variable that's bound conditionally in the `HeroListComponent` template.
|
It sets an `errorMessage` variable that's bound conditionally in the `HeroListComponent` template.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="server-communication/src/app/toh/hero-list.component.ts" region="getHeroes" linenums="false">
|
<code-example path="server-communication/src/app/toh/hero-list.component.ts" region="getHeroes" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -365,6 +379,7 @@ You'll write a method for the `HeroListComponent` to call, a `create()` method,
|
|||||||
just the name of a new hero and returns an `Observable` of `Hero`. It begins like this:
|
just the name of a new hero and returns an `Observable` of `Hero`. It begins like this:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="server-communication/src/app/toh/hero.service.ts" region="create-sig" linenums="false">
|
<code-example path="server-communication/src/app/toh/hero.service.ts" region="create-sig" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -378,6 +393,7 @@ It expects the new hero data to arrive in the body of the request,
|
|||||||
structured like a `Hero` entity but without the `id` property.
|
structured like a `Hero` entity but without the `id` property.
|
||||||
The body of the request should look like this:
|
The body of the request should look like this:
|
||||||
|
|
||||||
|
|
||||||
<code-example format="." language="javascript">
|
<code-example format="." language="javascript">
|
||||||
{ "name": "Windstorm" }
|
{ "name": "Windstorm" }
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -389,6 +405,7 @@ with its own `data` property.
|
|||||||
Now that you know how the API works, implement `create()` as follows:
|
Now that you know how the API works, implement `create()` as follows:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="server-communication/src/app/toh/hero.service.ts" linenums="false" title="src/app/toh/hero.service.ts (create)" region="create">
|
<code-example path="server-communication/src/app/toh/hero.service.ts" linenums="false" title="src/app/toh/hero.service.ts (create)" region="create">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -410,11 +427,13 @@ from the response.
|
|||||||
Back in the `HeroListComponent`, its `addHero()` method subscribes to the Observable returned by the service's `create()` method.
|
Back in the `HeroListComponent`, its `addHero()` method subscribes to the Observable returned by the service's `create()` method.
|
||||||
When the data arrive it pushes the new hero object into its `heroes` array for presentation to the user.
|
When the data arrive it pushes the new hero object into its `heroes` array for presentation to the user.
|
||||||
|
|
||||||
|
|
||||||
<code-example path="server-communication/src/app/toh/hero-list.component.ts" region="addHero" linenums="false">
|
<code-example path="server-communication/src/app/toh/hero-list.component.ts" region="addHero" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<h2 id='cors'>
|
<h2 id='cors'>
|
||||||
Cross-Origin Requests: Wikipedia example
|
Cross-Origin Requests: Wikipedia example
|
||||||
</h2>
|
</h2>
|
||||||
@ -453,6 +472,7 @@ This [Stack Overflow answer](http://stackoverflow.com/questions/2067472/what-is-
|
|||||||
Here is a simple search that shows suggestions from Wikipedia as the user
|
Here is a simple search that shows suggestions from Wikipedia as the user
|
||||||
types in a text box:
|
types in a text box:
|
||||||
|
|
||||||
|
|
||||||
<figure class='image-display'>
|
<figure class='image-display'>
|
||||||
<img src='assets/images/devguide/server-communication/wiki-1.gif' alt="Wikipedia search app (v.1)" width="250"> </img>
|
<img src='assets/images/devguide/server-communication/wiki-1.gif' alt="Wikipedia search app (v.1)" width="250"> </img>
|
||||||
</figure>
|
</figure>
|
||||||
@ -465,6 +485,7 @@ All other HTTP methods throw an error because `JSONP` is a read-only facility.
|
|||||||
As always, wrap the interaction with an Angular data access client service inside a dedicated service, here called `WikipediaService`.
|
As always, wrap the interaction with an Angular data access client service inside a dedicated service, here called `WikipediaService`.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="server-communication/src/app/wiki/wikipedia.service.ts">
|
<code-example path="server-communication/src/app/wiki/wikipedia.service.ts">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -489,18 +510,21 @@ All of this happens under the hood.
|
|||||||
|
|
||||||
If you're looking for articles with the word "Angular", you could construct the query string by hand and call `jsonp` like this:
|
If you're looking for articles with the word "Angular", you could construct the query string by hand and call `jsonp` like this:
|
||||||
|
|
||||||
|
|
||||||
<code-example path="server-communication/src/app/wiki/wikipedia.service.1.ts" region="query-string" linenums="false">
|
<code-example path="server-communication/src/app/wiki/wikipedia.service.1.ts" region="query-string" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
|
|
||||||
In more parameterized examples you could build the query string with the Angular `URLSearchParams` helper:
|
In more parameterized examples you could build the query string with the Angular `URLSearchParams` helper:
|
||||||
|
|
||||||
|
|
||||||
<code-example path="server-communication/src/app/wiki/wikipedia.service.ts" region="search-parameters" linenums="false">
|
<code-example path="server-communication/src/app/wiki/wikipedia.service.ts" region="search-parameters" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
|
|
||||||
This time you call `jsonp` with *two* arguments: the `wikiUrl` and an options object whose `search` property is the `params` object.
|
This time you call `jsonp` with *two* arguments: the `wikiUrl` and an options object whose `search` property is the `params` object.
|
||||||
|
|
||||||
|
|
||||||
<code-example path="server-communication/src/app/wiki/wikipedia.service.ts" region="call-jsonp" linenums="false">
|
<code-example path="server-communication/src/app/wiki/wikipedia.service.ts" region="call-jsonp" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -512,6 +536,7 @@ to the server.
|
|||||||
Now that you have a service that can query the Wikipedia API,
|
Now that you have a service that can query the Wikipedia API,
|
||||||
turn your attention to the component (template and class) that takes user input and displays search results.
|
turn your attention to the component (template and class) that takes user input and displays search results.
|
||||||
|
|
||||||
|
|
||||||
<code-example path="server-communication/src/app/wiki/wiki.component.ts">
|
<code-example path="server-communication/src/app/wiki/wiki.component.ts">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -547,6 +572,7 @@ It is inefficient and potentially expensive on mobile devices with limited data
|
|||||||
Presently, the code calls the server after every keystroke.
|
Presently, the code calls the server after every keystroke.
|
||||||
It should only make requests when the user *stops typing*.
|
It should only make requests when the user *stops typing*.
|
||||||
Here's how it will work after refactoring:
|
Here's how it will work after refactoring:
|
||||||
|
|
||||||
<figure class='image-display'>
|
<figure class='image-display'>
|
||||||
<img src='assets/images/devguide/server-communication/wiki-2.gif' alt="Wikipedia search app (v.2)" width="250"> </img>
|
<img src='assets/images/devguide/server-communication/wiki-2.gif' alt="Wikipedia search app (v.2)" width="250"> </img>
|
||||||
</figure>
|
</figure>
|
||||||
@ -580,13 +606,16 @@ with the help of some nifty Observable operators.
|
|||||||
Here's the `WikiSmartComponent`, shown next to the original `WikiComponent`:
|
Here's the `WikiSmartComponent`, shown next to the original `WikiComponent`:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-tabs>
|
<code-tabs>
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="src/app/wiki/wiki-smart.component.ts" path="server-communication/src/app/wiki/wiki-smart.component.ts">
|
<code-pane title="src/app/wiki/wiki-smart.component.ts" path="server-communication/src/app/wiki/wiki-smart.component.ts">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="src/app/wiki/wiki.component.ts" path="server-communication/src/app/wiki/wiki.component.ts">
|
<code-pane title="src/app/wiki/wiki.component.ts" path="server-communication/src/app/wiki/wiki.component.ts">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
@ -608,6 +637,7 @@ The `WikiComponent` passes a new search term directly to the `WikipediaService`
|
|||||||
The `WikiSmartComponent` class turns the user's keystrokes into an Observable _stream of search terms_
|
The `WikiSmartComponent` class turns the user's keystrokes into an Observable _stream of search terms_
|
||||||
with the help of a `Subject`, which you import from RxJS:
|
with the help of a `Subject`, which you import from RxJS:
|
||||||
|
|
||||||
|
|
||||||
<code-example path="server-communication/src/app/wiki/wiki-smart.component.ts" region="import-subject" linenums="false">
|
<code-example path="server-communication/src/app/wiki/wiki-smart.component.ts" region="import-subject" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -616,6 +646,7 @@ The component creates a `searchTermStream` as a `Subject` of type `string`.
|
|||||||
The `search()` method adds each new search box value to that stream via the subject's `next()` method.
|
The `search()` method adds each new search box value to that stream via the subject's `next()` method.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="server-communication/src/app/wiki/wiki-smart.component.ts" region="subject" linenums="false">
|
<code-example path="server-communication/src/app/wiki/wiki-smart.component.ts" region="subject" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -628,6 +659,7 @@ The `search()` method adds each new search box value to that stream via the subj
|
|||||||
The `WikiSmartComponent` listens to the *stream of search terms* and
|
The `WikiSmartComponent` listens to the *stream of search terms* and
|
||||||
processes that stream _before_ calling the service.
|
processes that stream _before_ calling the service.
|
||||||
|
|
||||||
|
|
||||||
<code-example path="server-communication/src/app/wiki/wiki-smart.component.ts" region="observable-operators" linenums="false">
|
<code-example path="server-communication/src/app/wiki/wiki-smart.component.ts" region="observable-operators" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -686,12 +718,14 @@ This sample creates a class that sets the default `Content-Type` header to JSON.
|
|||||||
It exports a constant with the necessary `RequestOptions` provider to simplify registration in `AppModule`.
|
It exports a constant with the necessary `RequestOptions` provider to simplify registration in `AppModule`.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="server-communication/src/app/default-request-options.service.ts" linenums="false">
|
<code-example path="server-communication/src/app/default-request-options.service.ts" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
|
|
||||||
Then it registers the provider in the root `AppModule`.
|
Then it registers the provider in the root `AppModule`.
|
||||||
|
|
||||||
|
|
||||||
<code-example path="server-communication/src/app/app.module.ts" region="provide-default-request-options" linenums="false">
|
<code-example path="server-communication/src/app/app.module.ts" region="provide-default-request-options" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -707,6 +741,7 @@ Remember to include this provider during setup when unit testing the app's HTTP
|
|||||||
After this change, the `header` option setting in `HeroService.create()` is no longer necessary,
|
After this change, the `header` option setting in `HeroService.create()` is no longer necessary,
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="server-communication/src/app/toh/hero.service.ts" linenums="false" title="src/app/toh/hero.service.ts (create)" region="create">
|
<code-example path="server-communication/src/app/toh/hero.service.ts" linenums="false" title="src/app/toh/hero.service.ts (create)" region="create">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -737,6 +772,7 @@ posed by top-level JSON arrays.
|
|||||||
|
|
||||||
You'd set the endpoint to the JSON file like this:
|
You'd set the endpoint to the JSON file like this:
|
||||||
|
|
||||||
|
|
||||||
<code-example path="server-communication/src/app/toh/hero.service.ts" region="endpoint-json" linenums="false">
|
<code-example path="server-communication/src/app/toh/hero.service.ts" region="endpoint-json" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -767,12 +803,14 @@ are !{_array}s of objects in those collections.
|
|||||||
|
|
||||||
Here's the class for this sample, based on the JSON data:
|
Here's the class for this sample, based on the JSON data:
|
||||||
|
|
||||||
|
|
||||||
<code-example path="server-communication/src/app/hero-data.ts" linenums="false">
|
<code-example path="server-communication/src/app/hero-data.ts" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
|
|
||||||
Ensure that the `HeroService` endpoint refers to the web API:
|
Ensure that the `HeroService` endpoint refers to the web API:
|
||||||
|
|
||||||
|
|
||||||
<code-example path="server-communication/src/app/toh/hero.service.ts" region="endpoint" linenums="false">
|
<code-example path="server-communication/src/app/toh/hero.service.ts" region="endpoint" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -782,6 +820,7 @@ Finally, redirect client HTTP requests to the in-memory web API by
|
|||||||
adding the `InMemoryWebApiModule` to the `AppModule.imports` list.
|
adding the `InMemoryWebApiModule` to the `AppModule.imports` list.
|
||||||
At the same time, call its `forRoot()` configuration method with the `HeroData` class.
|
At the same time, call its `forRoot()` configuration method with the `HeroData` class.
|
||||||
|
|
||||||
|
|
||||||
<code-example path="server-communication/src/app/app.module.ts" region="in-mem-web-api" linenums="false">
|
<code-example path="server-communication/src/app/app.module.ts" region="in-mem-web-api" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -805,6 +844,7 @@ while setting the metadata for the root `AppModule`. Don't call it again.
|
|||||||
Here is the final, revised version of <span ngio-ex>src/app/app.module.ts</span>, demonstrating these steps.
|
Here is the final, revised version of <span ngio-ex>src/app/app.module.ts</span>, demonstrating these steps.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="server-communication/src/app/app.module.ts" linenums="false" title="src/app/app.module.ts (excerpt)">
|
<code-example path="server-communication/src/app/app.module.ts" linenums="false" title="src/app/app.module.ts (excerpt)">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
|
@ -11,10 +11,13 @@ Setting the document or window title using the Title service.
|
|||||||
Our app should be able to make the browser title bar say whatever we want it to say.
|
Our app should be able to make the browser title bar say whatever we want it to say.
|
||||||
This cookbook explains how to do it.**See the <live-example name="cb-set-document-title"></live-example>**.
|
This cookbook explains how to do it.**See the <live-example name="cb-set-document-title"></live-example>**.
|
||||||
|
|
||||||
|
|
||||||
<table>
|
<table>
|
||||||
|
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
To see the browser title bar change in the live example,
|
To see the browser title bar change in the live example,
|
||||||
open it again in the Plunker editor by clicking the icon in the upper right,
|
open it again in the Plunker editor by clicking the icon in the upper right,
|
||||||
@ -22,6 +25,7 @@ This cookbook explains how to do it.**See the <live-example name="cb-set-documen
|
|||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
<img src='assets/images/devguide/plunker-switch-to-editor-button.png' width="200px" height="70px" alt="pop out the window" align="right"> </img> <br> </br> <img src='assets/images/devguide/plunker-separate-window-button.png' width="200px" height="47px" alt="pop out the window" align="right"> </img>
|
<img src='assets/images/devguide/plunker-switch-to-editor-button.png' width="200px" height="70px" alt="pop out the window" align="right"> </img> <br> </br> <img src='assets/images/devguide/plunker-separate-window-button.png' width="200px" height="47px" alt="pop out the window" align="right"> </img>
|
||||||
</td>
|
</td>
|
||||||
@ -35,6 +39,7 @@ This cookbook explains how to do it.**See the <live-example name="cb-set-documen
|
|||||||
## The problem with *<title>*
|
## The problem with *<title>*
|
||||||
|
|
||||||
The obvious approach is to bind a property of the component to the HTML `<title>` like this:
|
The obvious approach is to bind a property of the component to the HTML `<title>` like this:
|
||||||
|
|
||||||
<code-example format=''>
|
<code-example format=''>
|
||||||
<title>{{This_Does_Not_Work}}</title>
|
<title>{{This_Does_Not_Work}}</title>
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -67,11 +72,13 @@ for getting and setting the current HTML document title:
|
|||||||
Let's inject the `Title` service into the root `AppComponent` and expose a bindable `setTitle` method that calls it:
|
Let's inject the `Title` service into the root `AppComponent` and expose a bindable `setTitle` method that calls it:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="cb-set-document-title/src/app/app.component.ts" region="class" linenums="false">
|
<code-example path="cb-set-document-title/src/app/app.component.ts" region="class" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
|
|
||||||
We bind that method to three anchor tags and, voilà!
|
We bind that method to three anchor tags and, voilà!
|
||||||
|
|
||||||
<figure class='image-display'>
|
<figure class='image-display'>
|
||||||
<img src="assets/images/cookbooks/set-document-title/set-title-anim.gif" alt="Set title"> </img>
|
<img src="assets/images/cookbooks/set-document-title/set-title-anim.gif" alt="Set title"> </img>
|
||||||
</figure>
|
</figure>
|
||||||
@ -79,18 +86,22 @@ We bind that method to three anchor tags and, voilà!
|
|||||||
Here's the complete solution
|
Here's the complete solution
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-tabs>
|
<code-tabs>
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="src/main.ts" path="cb-set-document-title/src/main.ts">
|
<code-pane title="src/main.ts" path="cb-set-document-title/src/main.ts">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="src/app/app.module.ts" path="cb-set-document-title/src/app/app.module.ts">
|
<code-pane title="src/app/app.module.ts" path="cb-set-document-title/src/app/app.module.ts">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="src/app/app.component.ts" path="cb-set-document-title/src/app/app.component.ts">
|
<code-pane title="src/app/app.component.ts" path="cb-set-document-title/src/app/app.component.ts">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
|
@ -15,30 +15,37 @@ Files _outside_ those folders condition the development environment.
|
|||||||
They rarely change and you may never view or modify them.
|
They rarely change and you may never view or modify them.
|
||||||
If you do, this page can help you understand their purpose.
|
If you do, this page can help you understand their purpose.
|
||||||
|
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
td, th {vertical-align: top}
|
td, th {vertical-align: top}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<table width="100%">
|
<table width="100%">
|
||||||
|
|
||||||
|
|
||||||
<col width="10%">
|
<col width="10%">
|
||||||
|
|
||||||
</col>
|
</col>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<col width="90%">
|
<col width="90%">
|
||||||
|
|
||||||
</col>
|
</col>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
|
|
||||||
|
|
||||||
<th>
|
<th>
|
||||||
File
|
File
|
||||||
</th>
|
</th>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<th>
|
<th>
|
||||||
Purpose
|
Purpose
|
||||||
</th>
|
</th>
|
||||||
@ -47,13 +54,16 @@ If you do, this page can help you understand their purpose.
|
|||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
<code>src/app/</code>
|
<code>src/app/</code>
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
Angular application files go here.
|
Angular application files go here.
|
||||||
|
|
||||||
@ -70,13 +80,16 @@ If you do, this page can help you understand their purpose.
|
|||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
<code>e2e/</code>
|
<code>e2e/</code>
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
_End-to-end_ (e2e) tests of the application,
|
_End-to-end_ (e2e) tests of the application,
|
||||||
written in Jasmine and run by the
|
written in Jasmine and run by the
|
||||||
@ -90,13 +103,16 @@ If you do, this page can help you understand their purpose.
|
|||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
<code>node_modules/</code>
|
<code>node_modules/</code>
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
The _npm_ packages installed with the `npm install` command.
|
The _npm_ packages installed with the `npm install` command.
|
||||||
</td>
|
</td>
|
||||||
@ -105,8 +121,10 @@ If you do, this page can help you understand their purpose.
|
|||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
<code> .editorconfig<br>
|
<code> .editorconfig<br>
|
||||||
.git/<br>
|
.git/<br>
|
||||||
@ -115,6 +133,7 @@ If you do, this page can help you understand their purpose.
|
|||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
Tooling configuration files and folders.
|
Tooling configuration files and folders.
|
||||||
Ignore them until you have a compelling reason to do otherwise.
|
Ignore them until you have a compelling reason to do otherwise.
|
||||||
@ -124,13 +143,16 @@ If you do, this page can help you understand their purpose.
|
|||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
<code>CHANGELOG.md</code>
|
<code>CHANGELOG.md</code>
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
The history of changes to the _QuickStart_ repository.
|
The history of changes to the _QuickStart_ repository.
|
||||||
Delete or ignore.
|
Delete or ignore.
|
||||||
@ -140,13 +162,16 @@ If you do, this page can help you understand their purpose.
|
|||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
<code>favicon.ico</code>
|
<code>favicon.ico</code>
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
The application icon that appears in the browser tab.
|
The application icon that appears in the browser tab.
|
||||||
</td>
|
</td>
|
||||||
@ -155,13 +180,16 @@ If you do, this page can help you understand their purpose.
|
|||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
<code>index.html</code>
|
<code>index.html</code>
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
The application host page.
|
The application host page.
|
||||||
It loads a few essential scripts in a prescribed order.
|
It loads a few essential scripts in a prescribed order.
|
||||||
@ -175,13 +203,16 @@ If you do, this page can help you understand their purpose.
|
|||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
<code>karma.conf.js</code>
|
<code>karma.conf.js</code>
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
Configuration for the <a href="https://karma-runner.github.io/1.0/index.html" target="_blank" title="Karma unit test runner">karma</a>
|
Configuration for the <a href="https://karma-runner.github.io/1.0/index.html" target="_blank" title="Karma unit test runner">karma</a>
|
||||||
test runner described in the [Testing](guide/testing) guide.
|
test runner described in the [Testing](guide/testing) guide.
|
||||||
@ -191,13 +222,16 @@ If you do, this page can help you understand their purpose.
|
|||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
<code>karma-test-shim.js</code>
|
<code>karma-test-shim.js</code>
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
Script to run <a href="https://karma-runner.github.io/1.0/index.html" target="_blank" title="Karma unit test runner">karma</a>
|
Script to run <a href="https://karma-runner.github.io/1.0/index.html" target="_blank" title="Karma unit test runner">karma</a>
|
||||||
with SystemJS as described in the [Testing](guide/testing) guide.
|
with SystemJS as described in the [Testing](guide/testing) guide.
|
||||||
@ -207,13 +241,16 @@ If you do, this page can help you understand their purpose.
|
|||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
<code>non-essential-files.txt</code>
|
<code>non-essential-files.txt</code>
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
A list of files that you can delete if you want to purge your setup of the
|
A list of files that you can delete if you want to purge your setup of the
|
||||||
original QuickStart Seed testing and git maintainence artifacts.
|
original QuickStart Seed testing and git maintainence artifacts.
|
||||||
@ -226,13 +263,16 @@ If you do, this page can help you understand their purpose.
|
|||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
<code>LICENSE</code>
|
<code>LICENSE</code>
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
The open source MIT license to use this setup code in your application.
|
The open source MIT license to use this setup code in your application.
|
||||||
</td>
|
</td>
|
||||||
@ -241,13 +281,16 @@ If you do, this page can help you understand their purpose.
|
|||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
<code>package.json</code>
|
<code>package.json</code>
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
Identifies `npm `package dependencies for the project.
|
Identifies `npm `package dependencies for the project.
|
||||||
|
|
||||||
@ -261,13 +304,16 @@ If you do, this page can help you understand their purpose.
|
|||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
<code>protractor.config.js</code>
|
<code>protractor.config.js</code>
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
Configuration for the
|
Configuration for the
|
||||||
<a href="http://www.protractortest.org/" target="_blank" title="Protractor: end-to-end testing for Angular">protractor</a>
|
<a href="http://www.protractortest.org/" target="_blank" title="Protractor: end-to-end testing for Angular">protractor</a>
|
||||||
@ -278,13 +324,16 @@ If you do, this page can help you understand their purpose.
|
|||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
<code>README.md</code>
|
<code>README.md</code>
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
Instruction for using this git repository in your project.
|
Instruction for using this git repository in your project.
|
||||||
Worth reading before deleting.
|
Worth reading before deleting.
|
||||||
@ -294,13 +343,16 @@ If you do, this page can help you understand their purpose.
|
|||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
<code>styles.css</code>
|
<code>styles.css</code>
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
Global styles for the application. Initialized with an `<h1>` style for the QuickStart demo.
|
Global styles for the application. Initialized with an `<h1>` style for the QuickStart demo.
|
||||||
|
|
||||||
@ -310,16 +362,20 @@ If you do, this page can help you understand their purpose.
|
|||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
<code>systemjs<br>.config.js</code>
|
<code>systemjs<br>.config.js</code>
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
Tells the **SystemJS** module loader where to find modules
|
Tells the **SystemJS** module loader where to find modules
|
||||||
referenced in JavaScript `import` statements. For example:
|
referenced in JavaScript `import` statements. For example:
|
||||||
|
|
||||||
<code-example language="ts">
|
<code-example language="ts">
|
||||||
import { Component } from '@angular/core;
|
import { Component } from '@angular/core;
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -331,13 +387,16 @@ If you do, this page can help you understand their purpose.
|
|||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
<code>systemjs<br>.config.extras.js</code>
|
<code>systemjs<br>.config.extras.js</code>
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
Optional extra SystemJS configuration.
|
Optional extra SystemJS configuration.
|
||||||
A way to add SystemJS mappings, such as for appliation _barrels_,
|
A way to add SystemJS mappings, such as for appliation _barrels_,
|
||||||
@ -348,13 +407,16 @@ If you do, this page can help you understand their purpose.
|
|||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
<code>tsconfig.json</code>
|
<code>tsconfig.json</code>
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
Tells the TypeScript compiler how to transpile TypeScript source files
|
Tells the TypeScript compiler how to transpile TypeScript source files
|
||||||
into JavaScript files that run in all modern browsers.
|
into JavaScript files that run in all modern browsers.
|
||||||
@ -364,13 +426,16 @@ If you do, this page can help you understand their purpose.
|
|||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
<code>tslint.json</code>
|
<code>tslint.json</code>
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
The `npm` installed TypeScript linter inspects your TypeScript code
|
The `npm` installed TypeScript linter inspects your TypeScript code
|
||||||
and complains when you violate one of its rules.
|
and complains when you violate one of its rules.
|
||||||
|
@ -32,6 +32,7 @@ Then ...
|
|||||||
|
|
||||||
Perform the _clone-to-launch_ steps with these terminal commands.
|
Perform the _clone-to-launch_ steps with these terminal commands.
|
||||||
|
|
||||||
|
|
||||||
<code-example language="sh" class="code-shell">
|
<code-example language="sh" class="code-shell">
|
||||||
git clone .git quickstart
|
git clone .git quickstart
|
||||||
cd quickstart
|
cd quickstart
|
||||||
@ -56,6 +57,7 @@ Perform the _clone-to-launch_ steps with these terminal commands.
|
|||||||
<a href="!{_qsRepoZip}" title="Download the QuickStart seed repository">Download the QuickStart seed</a>
|
<a href="!{_qsRepoZip}" title="Download the QuickStart seed repository">Download the QuickStart seed</a>
|
||||||
and unzip it into your project folder. Then perform the remaining steps with these terminal commands.
|
and unzip it into your project folder. Then perform the remaining steps with these terminal commands.
|
||||||
|
|
||||||
|
|
||||||
<code-example language="sh" class="code-shell">
|
<code-example language="sh" class="code-shell">
|
||||||
cd quickstart
|
cd quickstart
|
||||||
|
|
||||||
@ -92,6 +94,7 @@ Do this only in the beginning to avoid accidentally deleting your own tests and
|
|||||||
Open a terminal window in the project folder and enter the following commands for your environment:
|
Open a terminal window in the project folder and enter the following commands for your environment:
|
||||||
|
|
||||||
### OS/X (bash)
|
### OS/X (bash)
|
||||||
|
|
||||||
<code-example language="sh" class="code-shell">
|
<code-example language="sh" class="code-shell">
|
||||||
xargs rm -rf < non-essential-files.osx.txt
|
xargs rm -rf < non-essential-files.osx.txt
|
||||||
rm src/app/*.spec*.ts
|
rm src/app/*.spec*.ts
|
||||||
@ -100,6 +103,7 @@ Open a terminal window in the project folder and enter the following commands fo
|
|||||||
</code-example>
|
</code-example>
|
||||||
|
|
||||||
### Windows
|
### Windows
|
||||||
|
|
||||||
<code-example language="sh" class="code-shell">
|
<code-example language="sh" class="code-shell">
|
||||||
for /f %i in (non-essential-files.txt) do del %i /F /S /Q
|
for /f %i in (non-essential-files.txt) do del %i /F /S /Q
|
||||||
rd .git /s /q
|
rd .git /s /q
|
||||||
@ -123,17 +127,22 @@ most of which you can [learn about later](guide/setup-systemjs-anatomy).
|
|||||||
{@a app-files}
|
{@a app-files}
|
||||||
Focus on the following three TypeScript (`.ts`) files in the **`/src`** folder.
|
Focus on the following three TypeScript (`.ts`) files in the **`/src`** folder.
|
||||||
|
|
||||||
|
|
||||||
<aio-filetree>
|
<aio-filetree>
|
||||||
|
|
||||||
|
|
||||||
<aio-folder>
|
<aio-folder>
|
||||||
src
|
src
|
||||||
|
|
||||||
<aio-folder>
|
<aio-folder>
|
||||||
app
|
app
|
||||||
|
|
||||||
<aio-file>
|
<aio-file>
|
||||||
app.component.ts
|
app.component.ts
|
||||||
</aio-file>
|
</aio-file>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<aio-file>
|
<aio-file>
|
||||||
app.module.ts
|
app.module.ts
|
||||||
</aio-file>
|
</aio-file>
|
||||||
@ -142,6 +151,7 @@ Focus on the following three TypeScript (`.ts`) files in the **`/src`** folder.
|
|||||||
</aio-folder>
|
</aio-folder>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<aio-file>
|
<aio-file>
|
||||||
main.ts
|
main.ts
|
||||||
</aio-file>
|
</aio-file>
|
||||||
@ -154,18 +164,22 @@ Focus on the following three TypeScript (`.ts`) files in the **`/src`** folder.
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-tabs>
|
<code-tabs>
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="src/app/app.component.ts" path="setup/src/app/app.component.ts">
|
<code-pane title="src/app/app.component.ts" path="setup/src/app/app.component.ts">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="src/app/app.module.ts" path="setup/src/app/app.module.ts">
|
<code-pane title="src/app/app.module.ts" path="setup/src/app/app.module.ts">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="src/main.ts" path="setup/src/main.ts">
|
<code-pane title="src/main.ts" path="setup/src/main.ts">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
@ -185,30 +199,37 @@ unless told to do otherwise.
|
|||||||
|
|
||||||
The following are all in `src/`
|
The following are all in `src/`
|
||||||
|
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
td, th {vertical-align: top}
|
td, th {vertical-align: top}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<table width="100%">
|
<table width="100%">
|
||||||
|
|
||||||
|
|
||||||
<col width="20%">
|
<col width="20%">
|
||||||
|
|
||||||
</col>
|
</col>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<col width="80%">
|
<col width="80%">
|
||||||
|
|
||||||
</col>
|
</col>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
|
|
||||||
|
|
||||||
<th>
|
<th>
|
||||||
File
|
File
|
||||||
</th>
|
</th>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<th>
|
<th>
|
||||||
Purpose
|
Purpose
|
||||||
</th>
|
</th>
|
||||||
@ -217,13 +238,16 @@ The following are all in `src/`
|
|||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
<ngio-ex>app/app.component.ts</ngio-ex>
|
<ngio-ex>app/app.component.ts</ngio-ex>
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
Defines the same `AppComponent` as the one in the QuickStart !{_playground}.
|
Defines the same `AppComponent` as the one in the QuickStart !{_playground}.
|
||||||
It is the **root** component of what will become a tree of nested components
|
It is the **root** component of what will become a tree of nested components
|
||||||
@ -234,13 +258,16 @@ The following are all in `src/`
|
|||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<tr if-docs="ts">
|
<tr if-docs="ts">
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
<code>app/app.module.ts</code>
|
<code>app/app.module.ts</code>
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
Defines `AppModule`, the [root module](guide/appmodule) that tells Angular how to assemble the application.
|
Defines `AppModule`, the [root module](guide/appmodule) that tells Angular how to assemble the application.
|
||||||
Right now it declares only the `AppComponent`.
|
Right now it declares only the `AppComponent`.
|
||||||
@ -251,13 +278,16 @@ The following are all in `src/`
|
|||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
<ngio-ex>main.ts</ngio-ex>
|
<ngio-ex>main.ts</ngio-ex>
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
Compiles the application with the [JIT compiler](glossary) and
|
Compiles the application with the [JIT compiler](glossary) and
|
||||||
[bootstraps](guide/appmodule)
|
[bootstraps](guide/appmodule)
|
||||||
|
@ -7,6 +7,7 @@ Angular has a powerful template engine that lets us easily manipulate the DOM st
|
|||||||
@description
|
@description
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
h4 {font-size: 17px !important; text-transform: none !important;}
|
h4 {font-size: 17px !important; text-transform: none !important;}
|
||||||
.syntax { font-family: Consolas, 'Lucida Sans', Courier, sans-serif; color: black; font-size: 85%; }
|
.syntax { font-family: Consolas, 'Lucida Sans', Courier, sans-serif; color: black; font-size: 85%; }
|
||||||
@ -49,6 +50,7 @@ Structural directives are easy to recognize.
|
|||||||
An asterisk (*) precedes the directive attribute name as in this example.
|
An asterisk (*) precedes the directive attribute name as in this example.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="structural-directives/src/app/app.component.html" linenums="false" title="src/app/app.component.html (ngif)" region="ngif">
|
<code-example path="structural-directives/src/app/app.component.html" linenums="false" title="src/app/app.component.html (ngif)" region="ngif">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -68,6 +70,7 @@ described in the [_Template Syntax_](guide/template-syntax) guide and seen in sa
|
|||||||
Here's an example of them in a template:
|
Here's an example of them in a template:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="structural-directives/src/app/app.component.html" linenums="false" title="src/app/app.component.html (built-in)" region="built-in">
|
<code-example path="structural-directives/src/app/app.component.html" linenums="false" title="src/app/app.component.html (built-in)" region="built-in">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -79,6 +82,7 @@ and how to [write your own](guide/structural-directives#unless) structural direc
|
|||||||
~~~ {.callout.is-helpful}
|
~~~ {.callout.is-helpful}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<header>
|
<header>
|
||||||
Directive spelling
|
Directive spelling
|
||||||
</header>
|
</header>
|
||||||
@ -128,6 +132,7 @@ You can [only apply one](guide/structural-directives#one-per-element) _structura
|
|||||||
It takes a boolean expression and makes an entire chunk of the DOM appear or disappear.
|
It takes a boolean expression and makes an entire chunk of the DOM appear or disappear.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="structural-directives/src/app/app.component.html" linenums="false" title="src/app/app.component.html (ngif-true)" region="ngif-true">
|
<code-example path="structural-directives/src/app/app.component.html" linenums="false" title="src/app/app.component.html (ngif-true)" region="ngif-true">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -135,6 +140,7 @@ It takes a boolean expression and makes an entire chunk of the DOM appear or dis
|
|||||||
The `ngIf` directive doesn't hide elements with CSS. It adds and removes them physically from the DOM.
|
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.
|
Confirm that fact using browser developer tools to inspect the DOM.
|
||||||
|
|
||||||
|
|
||||||
<figure class='image-display'>
|
<figure class='image-display'>
|
||||||
<img src='assets/images/devguide/structural-directives/element-not-in-dom.png' alt="ngIf=false element not in DOM"> </img>
|
<img src='assets/images/devguide/structural-directives/element-not-in-dom.png' alt="ngIf=false element not in DOM"> </img>
|
||||||
</figure>
|
</figure>
|
||||||
@ -152,12 +158,14 @@ The component and DOM nodes can be garbage-collected and free up memory.
|
|||||||
A directive could hide the unwanted paragraph instead by setting its `display` style to `none`.
|
A directive could hide the unwanted paragraph instead by setting its `display` style to `none`.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="structural-directives/src/app/app.component.html" linenums="false" title="src/app/app.component.html (display-none)" region="display-none">
|
<code-example path="structural-directives/src/app/app.component.html" linenums="false" title="src/app/app.component.html (display-none)" region="display-none">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
|
|
||||||
While invisible, the element remains in the DOM.
|
While invisible, the element remains in the DOM.
|
||||||
|
|
||||||
|
|
||||||
<figure class='image-display'>
|
<figure class='image-display'>
|
||||||
<img src='assets/images/devguide/structural-directives/element-display-in-dom.png' alt="hidden element still in DOM"> </img>
|
<img src='assets/images/devguide/structural-directives/element-display-in-dom.png' alt="hidden element still in DOM"> </img>
|
||||||
</figure>
|
</figure>
|
||||||
@ -196,6 +204,7 @@ and wondered why it is necessary and what it does.
|
|||||||
Here is `*ngIf` displaying the hero's name if `hero` exists.
|
Here is `*ngIf` displaying the hero's name if `hero` exists.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="structural-directives/src/app/app.component.html" linenums="false" title="src/app/app.component.html (asterisk)" region="asterisk">
|
<code-example path="structural-directives/src/app/app.component.html" linenums="false" title="src/app/app.component.html (asterisk)" region="asterisk">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -205,6 +214,7 @@ Internally, Angular desugars it in two stages.
|
|||||||
First, it translates the `*ngIf="..."` into a template _attribute_, `template="ngIf ..."`, like this.
|
First, it translates the `*ngIf="..."` into a template _attribute_, `template="ngIf ..."`, like this.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="structural-directives/src/app/app.component.html" linenums="false" title="src/app/app.component.html (ngif-template-attr)" region="ngif-template-attr">
|
<code-example path="structural-directives/src/app/app.component.html" linenums="false" title="src/app/app.component.html (ngif-template-attr)" region="ngif-template-attr">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -212,6 +222,7 @@ First, it translates the `*ngIf="..."` into a template _attribute_, `template="n
|
|||||||
Then it translates the template _attribute_ into a template _element_, wrapped around the host element, like this.
|
Then it translates the template _attribute_ into a template _element_, wrapped around the host element, like this.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="structural-directives/src/app/app.component.html" linenums="false" title="src/app/app.component.html (ngif-template)" region="ngif-template">
|
<code-example path="structural-directives/src/app/app.component.html" linenums="false" title="src/app/app.component.html (ngif-template)" region="ngif-template">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -222,6 +233,7 @@ Then it translates the template _attribute_ into a template _element_, wrapped a
|
|||||||
None of these forms are actually rendered.
|
None of these forms are actually rendered.
|
||||||
Only the finished product ends up in the DOM.
|
Only the finished product ends up in the DOM.
|
||||||
|
|
||||||
|
|
||||||
<figure class='image-display'>
|
<figure class='image-display'>
|
||||||
<img src='assets/images/devguide/structural-directives/hero-div-in-dom.png' alt="hero div in DOM"> </img>
|
<img src='assets/images/devguide/structural-directives/hero-div-in-dom.png' alt="hero div in DOM"> </img>
|
||||||
</figure>
|
</figure>
|
||||||
@ -242,6 +254,7 @@ template _attribute_ to template _element_.
|
|||||||
Here's a full-featured application of `NgFor`, written all three ways:
|
Here's a full-featured application of `NgFor`, written all three ways:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="structural-directives/src/app/app.component.html" linenums="false" title="src/app/app.component.html (inside-ngfor)" region="inside-ngfor">
|
<code-example path="structural-directives/src/app/app.component.html" linenums="false" title="src/app/app.component.html (inside-ngfor)" region="inside-ngfor">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -351,6 +364,7 @@ The Angular _NgSwitch_ is actually a set of cooperating directives: `NgSwitch`,
|
|||||||
Here's an example.
|
Here's an example.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="structural-directives/src/app/app.component.html" linenums="false" title="src/app/app.component.html (ngswitch)" region="ngswitch">
|
<code-example path="structural-directives/src/app/app.component.html" linenums="false" title="src/app/app.component.html (ngswitch)" region="ngswitch">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -381,6 +395,7 @@ As with other structural directives, the `NgSwitchCase` and `NgSwitchDefault`
|
|||||||
can be desugared into the template _attribute_ form.
|
can be desugared into the template _attribute_ form.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="structural-directives/src/app/app.component.html" linenums="false" title="src/app/app.component.html (ngswitch-template-attr)" region="ngswitch-template-attr">
|
<code-example path="structural-directives/src/app/app.component.html" linenums="false" title="src/app/app.component.html (ngswitch-template-attr)" region="ngswitch-template-attr">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -388,6 +403,7 @@ can be desugared into the template _attribute_ form.
|
|||||||
That, in turn, can be desugared into the `<template>` element form.
|
That, in turn, can be desugared into the `<template>` element form.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="structural-directives/src/app/app.component.html" linenums="false" title="src/app/app.component.html (ngswitch-template)" region="ngswitch-template">
|
<code-example path="structural-directives/src/app/app.component.html" linenums="false" title="src/app/app.component.html (ngswitch-template)" region="ngswitch-template">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -420,12 +436,14 @@ 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!".
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="structural-directives/src/app/app.component.html" linenums="false" title="src/app/app.component.html (template-tag)" region="template-tag">
|
<code-example path="structural-directives/src/app/app.component.html" linenums="false" title="src/app/app.component.html (template-tag)" region="template-tag">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
|
|
||||||
Angular erases the middle "Hip!", leaving the cheer a bit less enthusiastic.
|
Angular erases the middle "Hip!", leaving the cheer a bit less enthusiastic.
|
||||||
|
|
||||||
|
|
||||||
<figure class='image-display'>
|
<figure class='image-display'>
|
||||||
<img src='assets/images/devguide/structural-directives/template-rendering.png' width="350" alt="template tag rendering"> </img>
|
<img src='assets/images/devguide/structural-directives/template-rendering.png' width="350" alt="template tag rendering"> </img>
|
||||||
</figure>
|
</figure>
|
||||||
@ -445,6 +463,7 @@ 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.
|
The list element (`<li>`) is a typical host element of an `NgFor` repeater.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="structural-directives/src/app/app.component.html" linenums="false" title="src/app/app.component.html (ngfor-li)" region="ngfor-li">
|
<code-example path="structural-directives/src/app/app.component.html" linenums="false" title="src/app/app.component.html (ngfor-li)" region="ngfor-li">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -453,6 +472,7 @@ When there isn't a host element, you can usually wrap the content in a native HT
|
|||||||
such as a `<div>`, and attach the directive to that wrapper.
|
such as a `<div>`, and attach the directive to that wrapper.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="structural-directives/src/app/app.component.html" linenums="false" title="src/app/app.component.html (ngif)" region="ngif">
|
<code-example path="structural-directives/src/app/app.component.html" linenums="false" title="src/app/app.component.html (ngif)" region="ngif">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -466,6 +486,7 @@ neither expect nor accommodate the new layout.
|
|||||||
For example, suppose you have the following paragraph layout.
|
For example, suppose you have the following paragraph layout.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="structural-directives/src/app/app.component.html" linenums="false" title="src/app/app.component.html (ngif-span)" region="ngif-span">
|
<code-example path="structural-directives/src/app/app.component.html" linenums="false" title="src/app/app.component.html (ngif-span)" region="ngif-span">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -473,12 +494,14 @@ 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.
|
You also have a CSS style rule that happens to apply to a `<span>` within a `<p>`aragraph.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="structural-directives/src/app/app.component.css" linenums="false" title="src/app/app.component.css (p-span)" region="p-span">
|
<code-example path="structural-directives/src/app/app.component.css" linenums="false" title="src/app/app.component.css (p-span)" region="p-span">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
|
|
||||||
The constructed paragraph renders strangely.
|
The constructed paragraph renders strangely.
|
||||||
|
|
||||||
|
|
||||||
<figure class='image-display'>
|
<figure class='image-display'>
|
||||||
<img src='assets/images/devguide/structural-directives/bad-paragraph.png' alt="spanned paragraph with bad style"> </img>
|
<img src='assets/images/devguide/structural-directives/bad-paragraph.png' alt="spanned paragraph with bad style"> </img>
|
||||||
</figure>
|
</figure>
|
||||||
@ -492,12 +515,14 @@ You can't wrap the _options_ in a conditional `<div>` or a `<span>`.
|
|||||||
When you try this,
|
When you try this,
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="structural-directives/src/app/app.component.html" linenums="false" title="src/app/app.component.html (select-span)" region="select-span">
|
<code-example path="structural-directives/src/app/app.component.html" linenums="false" title="src/app/app.component.html (select-span)" region="select-span">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
|
|
||||||
the drop down is empty.
|
the drop down is empty.
|
||||||
|
|
||||||
|
|
||||||
<figure class='image-display'>
|
<figure class='image-display'>
|
||||||
<img src='assets/images/devguide/structural-directives/bad-select.png' alt="spanned options don't work"> </img>
|
<img src='assets/images/devguide/structural-directives/bad-select.png' alt="spanned options don't work"> </img>
|
||||||
</figure>
|
</figure>
|
||||||
@ -512,12 +537,14 @@ because Angular _doesn't put it in the DOM_.
|
|||||||
Here's the conditional paragraph again, this time using `<ng-container>`.
|
Here's the conditional paragraph again, this time using `<ng-container>`.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="structural-directives/src/app/app.component.html" linenums="false" title="src/app/app.component.html (ngif-ngcontainer)" region="ngif-ngcontainer">
|
<code-example path="structural-directives/src/app/app.component.html" linenums="false" title="src/app/app.component.html (ngif-ngcontainer)" region="ngif-ngcontainer">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
|
|
||||||
It renders properly.
|
It renders properly.
|
||||||
|
|
||||||
|
|
||||||
<figure class='image-display'>
|
<figure class='image-display'>
|
||||||
<img src='assets/images/devguide/structural-directives/good-paragraph.png' alt="ngcontainer paragraph with proper style"> </img>
|
<img src='assets/images/devguide/structural-directives/good-paragraph.png' alt="ngcontainer paragraph with proper style"> </img>
|
||||||
</figure>
|
</figure>
|
||||||
@ -525,12 +552,14 @@ It renders properly.
|
|||||||
Now conditionally exclude a _select_ `<option>` with `<ng-container>`.
|
Now conditionally exclude a _select_ `<option>` with `<ng-container>`.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="structural-directives/src/app/app.component.html" linenums="false" title="src/app/app.component.html (select-ngcontainer)" region="select-ngcontainer">
|
<code-example path="structural-directives/src/app/app.component.html" linenums="false" title="src/app/app.component.html (select-ngcontainer)" region="select-ngcontainer">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
|
|
||||||
The drop down works properly.
|
The drop down works properly.
|
||||||
|
|
||||||
|
|
||||||
<figure class='image-display'>
|
<figure class='image-display'>
|
||||||
<img src='assets/images/devguide/structural-directives/select-ngcontainer-anim.gif' alt="ngcontainer options work properly"> </img>
|
<img src='assets/images/devguide/structural-directives/select-ngcontainer-anim.gif' alt="ngcontainer options work properly"> </img>
|
||||||
</figure>
|
</figure>
|
||||||
@ -539,6 +568,7 @@ The `<ng-container>` is a syntax element recognized by the Angular parser.
|
|||||||
It's not a directive, component, class, or interface.
|
It's not a directive, component, class, or interface.
|
||||||
It's more like the curly braces in a JavaScript `if`-block:
|
It's more like the curly braces in a JavaScript `if`-block:
|
||||||
|
|
||||||
|
|
||||||
<code-example language="javascript">
|
<code-example language="javascript">
|
||||||
if (someCondition) {
|
if (someCondition) {
|
||||||
statement1;
|
statement1;
|
||||||
@ -563,6 +593,7 @@ that does the opposite of `NgIf`.
|
|||||||
`UnlessDirective` displays the content when the condition is ***false***.
|
`UnlessDirective` displays the content when the condition is ***false***.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="structural-directives/src/app/app.component.html" linenums="false" title="src/app/app.component.html (myUnless-1)" region="myUnless-1">
|
<code-example path="structural-directives/src/app/app.component.html" linenums="false" title="src/app/app.component.html (myUnless-1)" region="myUnless-1">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -580,6 +611,7 @@ Creating a directive is similar to creating a component.
|
|||||||
Here's how you might begin:
|
Here's how you might begin:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="structural-directives/src/app/unless.directive.ts" linenums="false" title="src/app/unless.directive.ts (skeleton)" region="skeleton">
|
<code-example path="structural-directives/src/app/unless.directive.ts" linenums="false" title="src/app/unless.directive.ts (skeleton)" region="skeleton">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -611,6 +643,7 @@ and access the _view container_ through a
|
|||||||
You inject both in the directive constructor as private variables of the class.
|
You inject both in the directive constructor as private variables of the class.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="structural-directives/src/app/unless.directive.ts" linenums="false" title="src/app/unless.directive.ts (ctor)" region="ctor">
|
<code-example path="structural-directives/src/app/unless.directive.ts" linenums="false" title="src/app/unless.directive.ts (ctor)" region="ctor">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -630,6 +663,7 @@ Read about `@Input` in the [_Template Syntax_](guide/template-syntax) guide.
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="structural-directives/src/app/unless.directive.ts" linenums="false" title="src/app/unless.directive.ts (set)" region="set">
|
<code-example path="structural-directives/src/app/unless.directive.ts" linenums="false" title="src/app/unless.directive.ts (set)" region="set">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -648,6 +682,7 @@ Nobody reads the `myUnless` property so it doesn't need a getter.
|
|||||||
The completed directive code looks like this:
|
The completed directive code looks like this:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="structural-directives/src/app/unless.directive.ts" linenums="false" title="src/app/unless.directive.ts (excerpt)" region="no-docs">
|
<code-example path="structural-directives/src/app/unless.directive.ts" linenums="false" title="src/app/unless.directive.ts (excerpt)" region="no-docs">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -657,6 +692,7 @@ Add this directive to the `!{_declsVsDirectives}` !{_array} of the !{_AppModuleV
|
|||||||
Then create some HTML to try it.
|
Then create some HTML to try it.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="structural-directives/src/app/app.component.html" linenums="false" title="src/app/app.component.html (myUnless)" region="myUnless">
|
<code-example path="structural-directives/src/app/app.component.html" linenums="false" title="src/app/app.component.html (myUnless)" region="myUnless">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -664,6 +700,7 @@ Then create some HTML to try it.
|
|||||||
When the `condition` is falsy, the top (A) paragraph appears and the bottom (B) paragraph disappears.
|
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.
|
When the `condition` is truthy, the top (A) paragraph is removed and the bottom (B) paragraph appears.
|
||||||
|
|
||||||
|
|
||||||
<figure class='image-display'>
|
<figure class='image-display'>
|
||||||
<img src='assets/images/devguide/structural-directives/unless-anim.gif' alt="UnlessDirective in action"> </img>
|
<img src='assets/images/devguide/structural-directives/unless-anim.gif' alt="UnlessDirective in action"> </img>
|
||||||
</figure>
|
</figure>
|
||||||
@ -679,38 +716,46 @@ You can both try and download the source code for this guide in the <live-exampl
|
|||||||
Here is the source from the `src/app/` folder.
|
Here is the source from the `src/app/` folder.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-tabs>
|
<code-tabs>
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="app.component.ts" path="structural-directives/src/app/app.component.ts">
|
<code-pane title="app.component.ts" path="structural-directives/src/app/app.component.ts">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="app.component.html" path="structural-directives/src/app/app.component.html">
|
<code-pane title="app.component.html" path="structural-directives/src/app/app.component.html">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="app.component.css" path="structural-directives/src/app/app.component.css">
|
<code-pane title="app.component.css" path="structural-directives/src/app/app.component.css">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="app.module.ts" path="structural-directives/src/app/app.module.ts">
|
<code-pane title="app.module.ts" path="structural-directives/src/app/app.module.ts">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="hero.ts" path="structural-directives/src/app/hero.ts">
|
<code-pane title="hero.ts" path="structural-directives/src/app/hero.ts">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="hero-switch.components.ts" path="structural-directives/src/app/hero-switch.components.ts">
|
<code-pane title="hero-switch.components.ts" path="structural-directives/src/app/hero-switch.components.ts">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="unless.directive.ts" path="structural-directives/src/app/unless.directive.ts">
|
<code-pane title="unless.directive.ts" path="structural-directives/src/app/unless.directive.ts">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
|
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
@ -86,23 +86,28 @@ through the global `ng` object.
|
|||||||
Anything you can import from `@angular` is a nested member of this `ng` object:
|
Anything you can import from `@angular` is a nested member of this `ng` object:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-tabs>
|
<code-tabs>
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="TypeScript" path="cb-ts-to-js/ts/src/app/app.module.ts" region="ng2import">
|
<code-pane title="TypeScript" path="cb-ts-to-js/ts/src/app/app.module.ts" region="ng2import">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="ES6 JavaScript with decorators" path="cb-ts-to-js/js-es6-decorators/src/app/app.module.es6" region="ng2import">
|
<code-pane title="ES6 JavaScript with decorators" path="cb-ts-to-js/js-es6-decorators/src/app/app.module.es6" region="ng2import">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="ES6 JavaScript" path="cb-ts-to-js/js-es6/src/app/app.module.es6" region="ng2import">
|
<code-pane title="ES6 JavaScript" path="cb-ts-to-js/js-es6/src/app/app.module.es6" region="ng2import">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="ES5 JavaScript" path="cb-ts-to-js/js/src/app/app.module.js" region="ng2import">
|
<code-pane title="ES5 JavaScript" path="cb-ts-to-js/js/src/app/app.module.js" region="ng2import">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
@ -138,23 +143,28 @@ to limit unintentional leaking of private symbols into the global scope.
|
|||||||
Here is a `HeroComponent` as it might be defined and "exported" in each of the four language variants.
|
Here is a `HeroComponent` as it might be defined and "exported" in each of the four language variants.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-tabs>
|
<code-tabs>
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="TypeScript" path="cb-ts-to-js/ts/src/app/hero.component.ts" region="appexport">
|
<code-pane title="TypeScript" path="cb-ts-to-js/ts/src/app/hero.component.ts" region="appexport">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="ES6 JavaScript with decorators" path="cb-ts-to-js/js-es6-decorators/src/app/hero.component.es6" region="appexport">
|
<code-pane title="ES6 JavaScript with decorators" path="cb-ts-to-js/js-es6-decorators/src/app/hero.component.es6" region="appexport">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="ES6 JavaScript" path="cb-ts-to-js/js-es6/src/app/hero.component.es6" region="appexport">
|
<code-pane title="ES6 JavaScript" path="cb-ts-to-js/js-es6/src/app/hero.component.es6" region="appexport">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="ES5 JavaScript" path="cb-ts-to-js/js/src/app/hero.component.js" region="appexport">
|
<code-pane title="ES5 JavaScript" path="cb-ts-to-js/js/src/app/hero.component.js" region="appexport">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
@ -169,23 +179,28 @@ In _TypeScript_ and _ES6_ apps, you `import` things that have been exported from
|
|||||||
In _ES5_ you use the shared namespace object to access "exported" entities from other files.
|
In _ES5_ you use the shared namespace object to access "exported" entities from other files.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-tabs>
|
<code-tabs>
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="TypeScript" path="cb-ts-to-js/ts/src/app/app.module.ts" region="appimport">
|
<code-pane title="TypeScript" path="cb-ts-to-js/ts/src/app/app.module.ts" region="appimport">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="ES6 JavaScript with decorators" path="cb-ts-to-js/js-es6-decorators/src/app/app.module.es6" region="appimport">
|
<code-pane title="ES6 JavaScript with decorators" path="cb-ts-to-js/js-es6-decorators/src/app/app.module.es6" region="appimport">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="ES6 JavaScript" path="cb-ts-to-js/js-es6/src/app/app.module.es6" region="appimport">
|
<code-pane title="ES6 JavaScript" path="cb-ts-to-js/js-es6/src/app/app.module.es6" region="appimport">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="ES5 JavaScript" path="cb-ts-to-js/js/src/app/app.module.js" region="appimport">
|
<code-pane title="ES5 JavaScript" path="cb-ts-to-js/js/src/app/app.module.js" region="appimport">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
@ -235,23 +250,28 @@ _ES5_ JavaScript has no classes.
|
|||||||
Use the constructor function pattern instead, adding methods to the prototype.
|
Use the constructor function pattern instead, adding methods to the prototype.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-tabs>
|
<code-tabs>
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="TypeScript" path="cb-ts-to-js/ts/src/app/hero.component.ts" region="class">
|
<code-pane title="TypeScript" path="cb-ts-to-js/ts/src/app/hero.component.ts" region="class">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="ES6 JavaScript with decorators" path="cb-ts-to-js/js-es6-decorators/src/app/hero.component.es6" region="class">
|
<code-pane title="ES6 JavaScript with decorators" path="cb-ts-to-js/js-es6-decorators/src/app/hero.component.es6" region="class">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="ES6 JavaScript" path="cb-ts-to-js/js-es6/src/app/hero.component.es6" region="class">
|
<code-pane title="ES6 JavaScript" path="cb-ts-to-js/js-es6/src/app/hero.component.es6" region="class">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="ES5 JavaScript" path="cb-ts-to-js/js/src/app/hero.component.js" region="constructorproto">
|
<code-pane title="ES5 JavaScript" path="cb-ts-to-js/js/src/app/hero.component.js" region="constructorproto">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
@ -275,23 +295,28 @@ In _ES5_, you also provide an `annotations` array but you attach it to the _cons
|
|||||||
See these variations side-by-side:
|
See these variations side-by-side:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-tabs>
|
<code-tabs>
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="TypeScript" path="cb-ts-to-js/ts/src/app/hero.component.ts" region="metadata">
|
<code-pane title="TypeScript" path="cb-ts-to-js/ts/src/app/hero.component.ts" region="metadata">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="ES6 JavaScript with decorators" path="cb-ts-to-js/js-es6-decorators/src/app/hero.component.es6" region="metadata">
|
<code-pane title="ES6 JavaScript with decorators" path="cb-ts-to-js/js-es6-decorators/src/app/hero.component.es6" region="metadata">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="ES6 JavaScript" path="cb-ts-to-js/js-es6/src/app/hero.component.es6" region="metadata">
|
<code-pane title="ES6 JavaScript" path="cb-ts-to-js/js-es6/src/app/hero.component.es6" region="metadata">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="ES5 JavaScript" path="cb-ts-to-js/js/src/app/hero.component.js" region="metadata">
|
<code-pane title="ES5 JavaScript" path="cb-ts-to-js/js/src/app/hero.component.js" region="metadata">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
@ -303,29 +328,35 @@ See these variations side-by-side:
|
|||||||
|
|
||||||
A large component template is often kept in a separate template file.
|
A large component template is often kept in a separate template file.
|
||||||
|
|
||||||
|
|
||||||
<code-example path="cb-ts-to-js/ts/src/app/hero-title.component.html" linenums="false">
|
<code-example path="cb-ts-to-js/ts/src/app/hero-title.component.html" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
|
|
||||||
The component (`HeroTitleComponent` in this case) then references the template file in its metadata `templateUrl` property:
|
The component (`HeroTitleComponent` in this case) then references the template file in its metadata `templateUrl` property:
|
||||||
|
|
||||||
|
|
||||||
<code-tabs>
|
<code-tabs>
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="TypeScript" path="cb-ts-to-js/ts/src/app/hero-title.component.ts" region="templateUrl">
|
<code-pane title="TypeScript" path="cb-ts-to-js/ts/src/app/hero-title.component.ts" region="templateUrl">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="ES6 JavaScript with decorators" path="cb-ts-to-js/js-es6-decorators/src/app/hero-title.component.es6" region="templateUrl">
|
<code-pane title="ES6 JavaScript with decorators" path="cb-ts-to-js/js-es6-decorators/src/app/hero-title.component.es6" region="templateUrl">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="ES6 JavaScript" path="cb-ts-to-js/js-es6/src/app/hero-title.component.es6" region="templateUrl">
|
<code-pane title="ES6 JavaScript" path="cb-ts-to-js/js-es6/src/app/hero-title.component.es6" region="templateUrl">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="ES5 JavaScript" path="cb-ts-to-js/js/src/app/hero-title.component.js" region="templateUrl">
|
<code-pane title="ES5 JavaScript" path="cb-ts-to-js/js/src/app/hero-title.component.js" region="templateUrl">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
@ -354,13 +385,16 @@ Here is an example of the `HeroComponent`, re-written with the DSL,
|
|||||||
next to the original _ES5_ version for comparison:
|
next to the original _ES5_ version for comparison:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-tabs>
|
<code-tabs>
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="ES5 JavaScript with DSL" path="cb-ts-to-js/js/src/app/hero.component.js" region="dsl">
|
<code-pane title="ES5 JavaScript with DSL" path="cb-ts-to-js/js/src/app/hero.component.js" region="dsl">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="ES5 JavaScript" path="cb-ts-to-js/js/src/app/hero.component.js">
|
<code-pane title="ES5 JavaScript" path="cb-ts-to-js/js/src/app/hero.component.js">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
@ -373,6 +407,7 @@ next to the original _ES5_ version for comparison:
|
|||||||
~~~ {.callout.is-helpful}
|
~~~ {.callout.is-helpful}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<header>
|
<header>
|
||||||
Name the constructor
|
Name the constructor
|
||||||
</header>
|
</header>
|
||||||
@ -391,6 +426,7 @@ _TypeScript_ and _ES6_ support with getters and setters.
|
|||||||
Here's an example of a read-only _TypeScript_ property with a getter
|
Here's an example of a read-only _TypeScript_ property with a getter
|
||||||
that prepares a toggle-button label for the next clicked state:
|
that prepares a toggle-button label for the next clicked state:
|
||||||
|
|
||||||
|
|
||||||
<code-example path="cb-ts-to-js/ts/src/app/hero-queries.component.ts" region="defined-property" linenums="false">
|
<code-example path="cb-ts-to-js/ts/src/app/hero-queries.component.ts" region="defined-property" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -402,6 +438,7 @@ The _ES5 DSL_ does not support _defined properties_ directly
|
|||||||
but you can still create them by extracting the "class" prototype and
|
but you can still create them by extracting the "class" prototype and
|
||||||
adding the _defined property_ in raw JavaScript like this:
|
adding the _defined property_ in raw JavaScript like this:
|
||||||
|
|
||||||
|
|
||||||
<code-example path="cb-ts-to-js/js/src/app/hero-queries.component.js" region="defined-property" linenums="false">
|
<code-example path="cb-ts-to-js/js/src/app/hero-queries.component.js" region="defined-property" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -410,6 +447,7 @@ adding the _defined property_ in raw JavaScript like this:
|
|||||||
There are similar DSLs for other decorated classes.
|
There are similar DSLs for other decorated classes.
|
||||||
You can define a directive with `ng.core.Directive`:
|
You can define a directive with `ng.core.Directive`:
|
||||||
|
|
||||||
|
|
||||||
<code-example>
|
<code-example>
|
||||||
app.MyDirective = ng.core.Directive({
|
app.MyDirective = ng.core.Directive({
|
||||||
selector: '[myDirective]'
|
selector: '[myDirective]'
|
||||||
@ -419,6 +457,7 @@ You can define a directive with `ng.core.Directive`:
|
|||||||
</code-example>
|
</code-example>
|
||||||
|
|
||||||
and a pipe with `ng.core.Pipe`:
|
and a pipe with `ng.core.Pipe`:
|
||||||
|
|
||||||
<code-example>
|
<code-example>
|
||||||
app.MyPipe = ng.core.Pipe({
|
app.MyPipe = ng.core.Pipe({
|
||||||
name: 'myPipe'
|
name: 'myPipe'
|
||||||
@ -444,28 +483,34 @@ They have no physical manifestation in the generated JavaScript code.
|
|||||||
Just implement the methods and ignore interfaces when translating code samples from _TypeScript_ to JavaScript.
|
Just implement the methods and ignore interfaces when translating code samples from _TypeScript_ to JavaScript.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-tabs>
|
<code-tabs>
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="TypeScript" path="cb-ts-to-js/ts/src/app/hero-lifecycle.component.ts">
|
<code-pane title="TypeScript" path="cb-ts-to-js/ts/src/app/hero-lifecycle.component.ts">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="ES6 JavaScript with decorators" path="cb-ts-to-js/js-es6-decorators/src/app/hero-lifecycle.component.es6">
|
<code-pane title="ES6 JavaScript with decorators" path="cb-ts-to-js/js-es6-decorators/src/app/hero-lifecycle.component.es6">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="ES6 JavaScript" path="cb-ts-to-js/js-es6/src/app/hero-lifecycle.component.es6">
|
<code-pane title="ES6 JavaScript" path="cb-ts-to-js/js-es6/src/app/hero-lifecycle.component.es6">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="ES5 JavaScript" path="cb-ts-to-js/js/src/app/hero-lifecycle.component.js">
|
<code-pane title="ES5 JavaScript" path="cb-ts-to-js/js/src/app/hero-lifecycle.component.js">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="ES5 JavaScript with DSL" path="cb-ts-to-js/js/src/app/hero-lifecycle.component.js" region="dsl">
|
<code-pane title="ES5 JavaScript with DSL" path="cb-ts-to-js/js/src/app/hero-lifecycle.component.js" region="dsl">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
@ -495,28 +540,34 @@ But note that what would have been _separate_ `@Input` and `@Output` property de
|
|||||||
combined in the metadata `inputs` and `outputs` _arrays_.
|
combined in the metadata `inputs` and `outputs` _arrays_.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-tabs>
|
<code-tabs>
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="TypeScript" path="cb-ts-to-js/ts/src/app/confirm.component.ts">
|
<code-pane title="TypeScript" path="cb-ts-to-js/ts/src/app/confirm.component.ts">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="ES6 JavaScript with decorators" path="cb-ts-to-js/js-es6-decorators/src/app/confirm.component.es6">
|
<code-pane title="ES6 JavaScript with decorators" path="cb-ts-to-js/js-es6-decorators/src/app/confirm.component.es6">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="ES6 JavaScript" path="cb-ts-to-js/js-es6/src/app/confirm.component.es6">
|
<code-pane title="ES6 JavaScript" path="cb-ts-to-js/js-es6/src/app/confirm.component.es6">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="ES5 JavaScript" path="cb-ts-to-js/js/src/app/confirm.component.js">
|
<code-pane title="ES5 JavaScript" path="cb-ts-to-js/js/src/app/confirm.component.js">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="ES5 JavaScript with DSL" path="cb-ts-to-js/js/src/app/confirm.component.js" region="dsl">
|
<code-pane title="ES5 JavaScript with DSL" path="cb-ts-to-js/js/src/app/confirm.component.js" region="dsl">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
@ -567,28 +618,34 @@ last parameter is the class constructor itself.
|
|||||||
This format should be familiar to AngularJS developers.
|
This format should be familiar to AngularJS developers.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-tabs>
|
<code-tabs>
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="TypeScript" path="cb-ts-to-js/ts/src/app/hero-di.component.ts">
|
<code-pane title="TypeScript" path="cb-ts-to-js/ts/src/app/hero-di.component.ts">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="ES6 JavaScript with decorators" path="cb-ts-to-js/js-es6-decorators/src/app/hero-di.component.es6">
|
<code-pane title="ES6 JavaScript with decorators" path="cb-ts-to-js/js-es6-decorators/src/app/hero-di.component.es6">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="ES6 JavaScript" path="cb-ts-to-js/js-es6/src/app/hero-di.component.es6">
|
<code-pane title="ES6 JavaScript" path="cb-ts-to-js/js-es6/src/app/hero-di.component.es6">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="ES5 JavaScript" path="cb-ts-to-js/js/src/app/hero-di.component.js">
|
<code-pane title="ES5 JavaScript" path="cb-ts-to-js/js/src/app/hero-di.component.js">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="ES5 JavaScript with DSL" path="cb-ts-to-js/js/src/app/hero-di.component.js" region="dsl">
|
<code-pane title="ES5 JavaScript with DSL" path="cb-ts-to-js/js/src/app/hero-di.component.js" region="dsl">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
@ -615,28 +672,34 @@ When writing with _ES5 DSL_, set the `Class.constructor` property to a function
|
|||||||
array as before. Create a new instance of `ng.core.Inject(token)` for each parameter.
|
array as before. Create a new instance of `ng.core.Inject(token)` for each parameter.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-tabs>
|
<code-tabs>
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="TypeScript" path="cb-ts-to-js/ts/src/app/hero-di-inject.component.ts">
|
<code-pane title="TypeScript" path="cb-ts-to-js/ts/src/app/hero-di-inject.component.ts">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="ES6 JavaScript with decorators" path="cb-ts-to-js/js-es6-decorators/src/app/hero-di-inject.component.es6">
|
<code-pane title="ES6 JavaScript with decorators" path="cb-ts-to-js/js-es6-decorators/src/app/hero-di-inject.component.es6">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="ES6 JavaScript" path="cb-ts-to-js/js-es6/src/app/hero-di-inject.component.es6">
|
<code-pane title="ES6 JavaScript" path="cb-ts-to-js/js-es6/src/app/hero-di-inject.component.es6">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="ES5 JavaScript" path="cb-ts-to-js/js/src/app/hero-di-inject.component.js">
|
<code-pane title="ES5 JavaScript" path="cb-ts-to-js/js/src/app/hero-di-inject.component.js">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="ES5 JavaScript with DSL" path="cb-ts-to-js/js/src/app/hero-di-inject.component.js" region="dsl">
|
<code-pane title="ES5 JavaScript with DSL" path="cb-ts-to-js/js/src/app/hero-di-inject.component.js" region="dsl">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
@ -665,28 +728,34 @@ When writing with _ES5 DSL_, set the `Class.constructor` property to a function
|
|||||||
array as before. Use a nested array to define a parameter's complete injection specification.
|
array as before. Use a nested array to define a parameter's complete injection specification.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-tabs>
|
<code-tabs>
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="TypeScript" path="cb-ts-to-js/ts/src/app/hero-title.component.ts">
|
<code-pane title="TypeScript" path="cb-ts-to-js/ts/src/app/hero-title.component.ts">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="ES6 JavaScript with decorators" path="cb-ts-to-js/js-es6-decorators/src/app/hero-title.component.es6">
|
<code-pane title="ES6 JavaScript with decorators" path="cb-ts-to-js/js-es6-decorators/src/app/hero-title.component.es6">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="ES6 JavaScript" path="cb-ts-to-js/js-es6/src/app/hero-title.component.es6">
|
<code-pane title="ES6 JavaScript" path="cb-ts-to-js/js-es6/src/app/hero-title.component.es6">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="ES5 JavaScript" path="cb-ts-to-js/js/src/app/hero-title.component.js">
|
<code-pane title="ES5 JavaScript" path="cb-ts-to-js/js/src/app/hero-title.component.js">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="ES5 JavaScript with DSL" path="cb-ts-to-js/js/src/app/hero-title.component.js" region="dsl">
|
<code-pane title="ES5 JavaScript with DSL" path="cb-ts-to-js/js/src/app/hero-title.component.js" region="dsl">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
@ -733,28 +802,34 @@ The `host` value is an object whose properties are host property and listener b
|
|||||||
* Each value identifies the corresponding component property or method.
|
* Each value identifies the corresponding component property or method.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-tabs>
|
<code-tabs>
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="TypeScript" path="cb-ts-to-js/ts/src/app/hero-host.component.ts">
|
<code-pane title="TypeScript" path="cb-ts-to-js/ts/src/app/hero-host.component.ts">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="ES6 JavaScript with decorators" path="cb-ts-to-js/js-es6-decorators/src/app/hero-host.component.es6">
|
<code-pane title="ES6 JavaScript with decorators" path="cb-ts-to-js/js-es6-decorators/src/app/hero-host.component.es6">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="ES6 JavaScript" path="cb-ts-to-js/js-es6/src/app/hero-host.component.es6">
|
<code-pane title="ES6 JavaScript" path="cb-ts-to-js/js-es6/src/app/hero-host.component.es6">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="ES5 JavaScript" path="cb-ts-to-js/js/src/app/hero-host.component.js">
|
<code-pane title="ES5 JavaScript" path="cb-ts-to-js/js/src/app/hero-host.component.js">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="ES5 JavaScript with DSL" path="cb-ts-to-js/js/src/app/hero-host.component.js" region="dsl">
|
<code-pane title="ES5 JavaScript with DSL" path="cb-ts-to-js/js/src/app/hero-host.component.js" region="dsl">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
@ -771,13 +846,16 @@ The following re-implementation of the `HeroComponent` reminds us that _any prop
|
|||||||
can be expressed as component or directive metadata in both _TypeScript_ and _ES6-with-decorators_.
|
can be expressed as component or directive metadata in both _TypeScript_ and _ES6-with-decorators_.
|
||||||
These particular _TypeScript_ and _ES6_ code snippets happen to be identical.
|
These particular _TypeScript_ and _ES6_ code snippets happen to be identical.
|
||||||
|
|
||||||
|
|
||||||
<code-tabs>
|
<code-tabs>
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="TypeScript" path="cb-ts-to-js/ts/src/app/hero-host-meta.component.ts">
|
<code-pane title="TypeScript" path="cb-ts-to-js/ts/src/app/hero-host-meta.component.ts">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="ES6 JavaScript with decorators" path="cb-ts-to-js/js-es6-decorators/src/app/hero-host-meta.component.es6">
|
<code-pane title="ES6 JavaScript with decorators" path="cb-ts-to-js/js-es6-decorators/src/app/hero-host-meta.component.es6">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
@ -815,23 +893,28 @@ The `queries` property value is a hash map.
|
|||||||
* each _value_ is a new instance of either `ViewChild` or `ViewChildren`.
|
* each _value_ is a new instance of either `ViewChild` or `ViewChildren`.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-tabs>
|
<code-tabs>
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="TypeScript" path="cb-ts-to-js/ts/src/app/hero-queries.component.ts" region="view">
|
<code-pane title="TypeScript" path="cb-ts-to-js/ts/src/app/hero-queries.component.ts" region="view">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="ES6 JavaScript with decorators" path="cb-ts-to-js/js-es6-decorators/src/app/hero-queries.component.es6" region="view">
|
<code-pane title="ES6 JavaScript with decorators" path="cb-ts-to-js/js-es6-decorators/src/app/hero-queries.component.es6" region="view">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="ES6 JavaScript" path="cb-ts-to-js/js-es6/src/app/hero-queries.component.es6" region="view">
|
<code-pane title="ES6 JavaScript" path="cb-ts-to-js/js-es6/src/app/hero-queries.component.es6" region="view">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="ES5 JavaScript with DSL" path="cb-ts-to-js/js/src/app/hero-queries.component.js" region="view">
|
<code-pane title="ES5 JavaScript with DSL" path="cb-ts-to-js/js/src/app/hero-queries.component.js" region="view">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
@ -848,23 +931,28 @@ They can be added in the same way as [`@ViewChild`](api/core/index/ViewChild-dec
|
|||||||
[`@ViewChildren`](api/core/index/ViewChildren-decorator).
|
[`@ViewChildren`](api/core/index/ViewChildren-decorator).
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-tabs>
|
<code-tabs>
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="TypeScript" path="cb-ts-to-js/ts/src/app/hero-queries.component.ts" region="content">
|
<code-pane title="TypeScript" path="cb-ts-to-js/ts/src/app/hero-queries.component.ts" region="content">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="ES6 JavaScript with decorators" path="cb-ts-to-js/js-es6-decorators/src/app/hero-queries.component.es6" region="content">
|
<code-pane title="ES6 JavaScript with decorators" path="cb-ts-to-js/js-es6-decorators/src/app/hero-queries.component.es6" region="content">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="ES6 JavaScript" path="cb-ts-to-js/js-es6/src/app/hero-queries.component.es6" region="content">
|
<code-pane title="ES6 JavaScript" path="cb-ts-to-js/js-es6/src/app/hero-queries.component.es6" region="content">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="ES5 JavaScript with DSL" path="cb-ts-to-js/js/src/app/hero-queries.component.js" region="content">
|
<code-pane title="ES5 JavaScript with DSL" path="cb-ts-to-js/js/src/app/hero-queries.component.js" region="content">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
|
@ -55,6 +55,7 @@ You can set a variable's type to `any` even when the `noImplicitAny` flag is `tr
|
|||||||
When the `noImplicitAny` flag is `true`, you may get *implicit index errors* as well.
|
When the `noImplicitAny` flag is `true`, you may get *implicit index errors* as well.
|
||||||
Most developers feel that *this particular error* is more annoying than helpful.
|
Most developers feel that *this particular error* is more annoying than helpful.
|
||||||
You can suppress them with the following additional flag:
|
You can suppress them with the following additional flag:
|
||||||
|
|
||||||
<code-example format=".">
|
<code-example format=".">
|
||||||
"suppressImplicitAnyIndexErrors":true
|
"suppressImplicitAnyIndexErrors":true
|
||||||
|
|
||||||
@ -92,6 +93,7 @@ like `Promise` if the target is `es6`.
|
|||||||
Since the QuickStart is targeting `es5`, you can override the
|
Since the QuickStart is targeting `es5`, you can override the
|
||||||
list of declaration files to be included:
|
list of declaration files to be included:
|
||||||
|
|
||||||
|
|
||||||
<code-example format=".">
|
<code-example format=".">
|
||||||
"lib": ["es2015", "dom"]
|
"lib": ["es2015", "dom"]
|
||||||
|
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -23,6 +23,7 @@ To bind to a DOM event, surround the DOM event name in parentheses and assign a
|
|||||||
|
|
||||||
The following example shows an event binding that implements a click handler:
|
The following example shows an event binding that implements a click handler:
|
||||||
|
|
||||||
|
|
||||||
<code-example path="user-input/src/app/click-me.component.ts" region="click-me-button" linenums="false">
|
<code-example path="user-input/src/app/click-me.component.ts" region="click-me-button" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -38,6 +39,7 @@ usually the Angular component controlling the template.
|
|||||||
The example above shows a single line of HTML, but that HTML belongs to a larger component:
|
The example above shows a single line of HTML, but that HTML belongs to a larger component:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="user-input/src/app/click-me.component.ts" region="click-me-component" linenums="false">
|
<code-example path="user-input/src/app/click-me.component.ts" region="click-me-component" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -50,6 +52,7 @@ This section shows how to bind to the `keyup` event of an input box to get the u
|
|||||||
|
|
||||||
The following code listens to the `keyup` event and passes the entire event payload (`$event`) to the component event handler.
|
The following code listens to the `keyup` event and passes the entire event payload (`$event`) to the component event handler.
|
||||||
|
|
||||||
|
|
||||||
<code-example path="user-input/src/app/keyup.components.ts" region="key-up-component-1-template" linenums="false">
|
<code-example path="user-input/src/app/keyup.components.ts" region="key-up-component-1-template" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -57,6 +60,7 @@ The following code listens to the `keyup` event and passes the entire event payl
|
|||||||
When a user presses and releases a key, the `keyup` event occurs, and Angular provides a corresponding
|
When a user presses and releases a key, the `keyup` event occurs, and Angular provides a corresponding
|
||||||
DOM event object in the `$event` variable which this code passes as a parameter to the component's `onKey()` method.
|
DOM event object in the `$event` variable which this code passes as a parameter to the component's `onKey()` method.
|
||||||
|
|
||||||
|
|
||||||
<code-example path="user-input/src/app/keyup.components.ts" region="key-up-component-1-class-no-type" linenums="false">
|
<code-example path="user-input/src/app/keyup.components.ts" region="key-up-component-1-class-no-type" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -76,11 +80,13 @@ displays the accumulating input box changes from the `values` property.
|
|||||||
|
|
||||||
Suppose the user enters the letters "abc", and then backspaces to remove them one by one.
|
Suppose the user enters the letters "abc", and then backspaces to remove them one by one.
|
||||||
Here's what the UI displays:
|
Here's what the UI displays:
|
||||||
|
|
||||||
<code-example>
|
<code-example>
|
||||||
a | ab | abc | ab | a | |
|
a | ab | abc | ab | a | |
|
||||||
</code-example>
|
</code-example>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<figure class='image-display'>
|
<figure class='image-display'>
|
||||||
<img src='assets/images/devguide/user-input/keyup1-anim.gif' alt="key up 1"> </img>
|
<img src='assets/images/devguide/user-input/keyup1-anim.gif' alt="key up 1"> </img>
|
||||||
</figure>
|
</figure>
|
||||||
@ -91,6 +97,7 @@ Here's what the UI displays:
|
|||||||
|
|
||||||
Alternatively, you could accumulate the individual keys themselves by substituting `event.key`
|
Alternatively, you could accumulate the individual keys themselves by substituting `event.key`
|
||||||
for `event.target.value` in which case the same user input would produce:
|
for `event.target.value` in which case the same user input would produce:
|
||||||
|
|
||||||
<code-example>
|
<code-example>
|
||||||
a | b | c | backspace | backspace | backspace |
|
a | b | c | backspace | backspace | backspace |
|
||||||
|
|
||||||
@ -112,6 +119,7 @@ that could reveal properties of the event object and prevent silly mistakes.
|
|||||||
|
|
||||||
The following example rewrites the method with types:
|
The following example rewrites the method with types:
|
||||||
|
|
||||||
|
|
||||||
<code-example path="user-input/src/app/keyup.components.ts" region="key-up-component-1-class" linenums="false">
|
<code-example path="user-input/src/app/keyup.components.ts" region="key-up-component-1-class" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -138,6 +146,7 @@ To declare a template reference variable, precede an identifier with a hash (or
|
|||||||
The following example uses a template reference variable
|
The following example uses a template reference variable
|
||||||
to implement a keystroke loopback in a simple template.
|
to implement a keystroke loopback in a simple template.
|
||||||
|
|
||||||
|
|
||||||
<code-example path="user-input/src/app/loop-back.component.ts" region="loop-back-component" linenums="false">
|
<code-example path="user-input/src/app/loop-back.component.ts" region="loop-back-component" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -152,6 +161,7 @@ and the component does nothing.
|
|||||||
|
|
||||||
Type something in the input box, and watch the display update with each keystroke.
|
Type something in the input box, and watch the display update with each keystroke.
|
||||||
|
|
||||||
|
|
||||||
<figure class='image-display'>
|
<figure class='image-display'>
|
||||||
<img src='assets/images/devguide/user-input/keyup-loop-back-anim.gif' alt="loop back"> </img>
|
<img src='assets/images/devguide/user-input/keyup-loop-back-anim.gif' alt="loop back"> </img>
|
||||||
</figure>
|
</figure>
|
||||||
@ -175,6 +185,7 @@ It's easier to get to the input box with the template reference
|
|||||||
variable than to go through the `$event` object. Here's a rewrite of the previous
|
variable than to go through the `$event` object. Here's a rewrite of the previous
|
||||||
`keyup` example that uses a template reference variable to get the user's input.
|
`keyup` example that uses a template reference variable to get the user's input.
|
||||||
|
|
||||||
|
|
||||||
<code-example path="user-input/src/app/keyup.components.ts" region="key-up-component-2" linenums="false">
|
<code-example path="user-input/src/app/keyup.components.ts" region="key-up-component-2" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -190,11 +201,13 @@ One way to reduce the noise would be to examine every `$event.keyCode` and take
|
|||||||
There's an easier way: bind to Angular's `keyup.enter` pseudo-event.
|
There's an easier way: bind to Angular's `keyup.enter` pseudo-event.
|
||||||
Then Angular calls the event handler only when the user presses _Enter_.
|
Then Angular calls the event handler only when the user presses _Enter_.
|
||||||
|
|
||||||
|
|
||||||
<code-example path="user-input/src/app/keyup.components.ts" region="key-up-component-3" linenums="false">
|
<code-example path="user-input/src/app/keyup.components.ts" region="key-up-component-3" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
|
|
||||||
Here's how it works.
|
Here's how it works.
|
||||||
|
|
||||||
<figure class='image-display'>
|
<figure class='image-display'>
|
||||||
<img src='assets/images/devguide/user-input/keyup3-anim.gif' alt="key up 3"> </img>
|
<img src='assets/images/devguide/user-input/keyup3-anim.gif' alt="key up 3"> </img>
|
||||||
</figure>
|
</figure>
|
||||||
@ -210,6 +223,7 @@ The component's `value` property is updated only when the user presses _Enter_.
|
|||||||
To fix this issue, listen to both the _Enter_ key and the _blur_ event.
|
To fix this issue, listen to both the _Enter_ key and the _blur_ event.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="user-input/src/app/keyup.components.ts" region="key-up-component-4" linenums="false">
|
<code-example path="user-input/src/app/keyup.components.ts" region="key-up-component-4" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -224,6 +238,7 @@ that can display a list of heroes and add new heroes to the list.
|
|||||||
The user can add a hero by typing the hero's name in the input box and
|
The user can add a hero by typing the hero's name in the input box and
|
||||||
clicking **Add**.
|
clicking **Add**.
|
||||||
|
|
||||||
|
|
||||||
<figure class='image-display'>
|
<figure class='image-display'>
|
||||||
<img src='assets/images/devguide/user-input/little-tour-anim.gif' alt="Little Tour of Heroes"> </img>
|
<img src='assets/images/devguide/user-input/little-tour-anim.gif' alt="Little Tour of Heroes"> </img>
|
||||||
</figure>
|
</figure>
|
||||||
@ -231,6 +246,7 @@ clicking **Add**.
|
|||||||
Below is the "Little Tour of Heroes" component.
|
Below is the "Little Tour of Heroes" component.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="user-input/src/app/little-tour.component.ts" region="little-tour" linenums="false">
|
<code-example path="user-input/src/app/little-tour.component.ts" region="little-tour" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -254,23 +270,28 @@ clears the input box after a new hero is added to the list.
|
|||||||
|
|
||||||
Following is all the code discussed in this page.
|
Following is all the code discussed in this page.
|
||||||
|
|
||||||
|
|
||||||
<code-tabs>
|
<code-tabs>
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="click-me.component.ts" path="user-input/src/app/click-me.component.ts">
|
<code-pane title="click-me.component.ts" path="user-input/src/app/click-me.component.ts">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="keyup.components.ts" path="user-input/src/app/keyup.components.ts">
|
<code-pane title="keyup.components.ts" path="user-input/src/app/keyup.components.ts">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="loop-back.component.ts" path="user-input/src/app/loop-back.component.ts">
|
<code-pane title="loop-back.component.ts" path="user-input/src/app/loop-back.component.ts">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="little-tour.component.ts" path="user-input/src/app/little-tour.component.ts">
|
<code-pane title="little-tour.component.ts" path="user-input/src/app/little-tour.component.ts">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
|
@ -46,6 +46,7 @@ The steps are as follows:
|
|||||||
- [Step 5](guide/visual-studio-2015#build-and-run): Build and run the app
|
- [Step 5](guide/visual-studio-2015#build-and-run): Build and run the app
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<h2 id='prereq1'>
|
<h2 id='prereq1'>
|
||||||
Prerequisite: Node.js
|
Prerequisite: Node.js
|
||||||
</h2>
|
</h2>
|
||||||
@ -64,6 +65,7 @@ Older versions produce errors.
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<h2 id='prereq2'>
|
<h2 id='prereq2'>
|
||||||
Prerequisite: Visual Studio 2015 Update 3
|
Prerequisite: Visual Studio 2015 Update 3
|
||||||
</h2>
|
</h2>
|
||||||
@ -76,6 +78,7 @@ If you don't have it, install **[Visual Studio 2015 Update 3](https://www.visual
|
|||||||
Or use `Tools | Extensions and Updates` to update to Update 3 directly from Visual Studio 2015.
|
Or use `Tools | Extensions and Updates` to update to Update 3 directly from Visual Studio 2015.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<h2 id='prereq3'>
|
<h2 id='prereq3'>
|
||||||
Prerequisite: Configure External Web tools
|
Prerequisite: Configure External Web tools
|
||||||
</h2>
|
</h2>
|
||||||
@ -94,6 +97,7 @@ if not found then look in the global path and if it is not found there, Visual S
|
|||||||
will use its own versions of the tools.
|
will use its own versions of the tools.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<h2 id='prereq4'>
|
<h2 id='prereq4'>
|
||||||
Prerequisite: Install TypeScript 2 for Visual Studio 2015
|
Prerequisite: Install TypeScript 2 for Visual Studio 2015
|
||||||
</h2>
|
</h2>
|
||||||
@ -111,6 +115,7 @@ At this point, Visual Studio is ready. It’s a good idea to close Visual Studio
|
|||||||
restart it to make sure everything is clean.
|
restart it to make sure everything is clean.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<h2 id='download'>
|
<h2 id='download'>
|
||||||
Step 1: Download the QuickStart files
|
Step 1: Download the QuickStart files
|
||||||
</h2>
|
</h2>
|
||||||
@ -119,6 +124,7 @@ restart it to make sure everything is clean.
|
|||||||
from github. If you downloaded as a zip file, extract the files.
|
from github. If you downloaded as a zip file, extract the files.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<h2 id='create-project'>
|
<h2 id='create-project'>
|
||||||
Step 2: Create the Visual Studio ASP.NET project
|
Step 2: Create the Visual Studio ASP.NET project
|
||||||
</h2>
|
</h2>
|
||||||
@ -141,6 +147,7 @@ no authentication and no hosting. Pick the template and options appropriate for
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<h2 id='copy'>
|
<h2 id='copy'>
|
||||||
Step 3: Copy the QuickStart files into the ASP.NET project folder
|
Step 3: Copy the QuickStart files into the ASP.NET project folder
|
||||||
</h2>
|
</h2>
|
||||||
@ -158,6 +165,7 @@ Include the files in the Visual Studio project as follows:
|
|||||||
* tsconfig.json
|
* tsconfig.json
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<h2 id='restore'>
|
<h2 id='restore'>
|
||||||
Step 4: Restore the required packages
|
Step 4: Restore the required packages
|
||||||
</h2>
|
</h2>
|
||||||
@ -174,6 +182,7 @@ Restore the packages required for an Angular application as follows:
|
|||||||
* **Do not** include the `node_modules` folder in the project. Let it be a hidden project folder.
|
* **Do not** include the `node_modules` folder in the project. Let it be a hidden project folder.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<h2 id='build-and-run'>
|
<h2 id='build-and-run'>
|
||||||
Step 5: Build and run the app
|
Step 5: Build and run the app
|
||||||
</h2>
|
</h2>
|
||||||
@ -195,6 +204,7 @@ Try editing any of the project files. *Save* and refresh the browser to
|
|||||||
see the changes.
|
see the changes.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<h2 id='routing'>
|
<h2 id='routing'>
|
||||||
Note on Routing Applications
|
Note on Routing Applications
|
||||||
</h2>
|
</h2>
|
||||||
|
@ -6,6 +6,7 @@ Create Angular applications with a Webpack based tooling.
|
|||||||
|
|
||||||
@description
|
@description
|
||||||
|
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
h4 {font-size: 17px !important; text-transform: none !important;}
|
h4 {font-size: 17px !important; text-transform: none !important;}
|
||||||
.syntax { font-family: Consolas, 'Lucida Sans', Courier, sans-serif; color: black; font-size: 85%; }
|
.syntax { font-family: Consolas, 'Lucida Sans', Courier, sans-serif; color: black; font-size: 85%; }
|
||||||
@ -69,6 +70,7 @@ You supply Webpack with one or more *entry* files and let it find and incorporat
|
|||||||
The one entry point file in this example is the application's root file, `src/main.ts`:
|
The one entry point file in this example is the application's root file, `src/main.ts`:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="webpack/config/webpack.common.js" region="one-entry" linenums="false">
|
<code-example path="webpack/config/webpack.common.js" region="one-entry" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -76,6 +78,7 @@ The one entry point file in this example is the application's root file, `src/ma
|
|||||||
Webpack inspects that file and traverses its `import` dependencies recursively.
|
Webpack inspects that file and traverses its `import` dependencies recursively.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="webpack/src/app/app.component.ts" region="component" linenums="false">
|
<code-example path="webpack/src/app/app.component.ts" region="component" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -85,8 +88,10 @@ It opens the `@angular/core` file and follows _its_ network of `import` statemen
|
|||||||
|
|
||||||
Then it **outputs** these files to the `app.js` _bundle file_ designated in configuration:
|
Then it **outputs** these files to the `app.js` _bundle file_ designated in configuration:
|
||||||
|
|
||||||
|
|
||||||
<div class='code-example'>
|
<div class='code-example'>
|
||||||
|
|
||||||
|
|
||||||
<code-example name="webpack.config.js (single output)" language="javascript">
|
<code-example name="webpack.config.js (single output)" language="javascript">
|
||||||
output: {
|
output: {
|
||||||
filename: 'app.js'
|
filename: 'app.js'
|
||||||
@ -108,8 +113,10 @@ It's preferable to separate the volatile application app code from comparatively
|
|||||||
|
|
||||||
Change the configuration so that it has two entry points, `main.ts` and `vendor.ts`:
|
Change the configuration so that it has two entry points, `main.ts` and `vendor.ts`:
|
||||||
|
|
||||||
|
|
||||||
<div class='code-example'>
|
<div class='code-example'>
|
||||||
|
|
||||||
|
|
||||||
<code-example language="javascript">
|
<code-example language="javascript">
|
||||||
entry: {
|
entry: {
|
||||||
app: 'src/app.ts',
|
app: 'src/app.ts',
|
||||||
@ -141,6 +148,7 @@ The `[name]` in the output name is a *placeholder* that a Webpack plugin replace
|
|||||||
To tell Webpack what belongs in the vendor bundle,
|
To tell Webpack what belongs in the vendor bundle,
|
||||||
add a `vendor.ts` file that only imports the application's third-party modules:
|
add a `vendor.ts` file that only imports the application's third-party modules:
|
||||||
|
|
||||||
|
|
||||||
<code-example path="webpack/src/vendor.ts" linenums="false">
|
<code-example path="webpack/src/vendor.ts" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -156,8 +164,10 @@ Webpack _itself_ only understands JavaScript files.
|
|||||||
Teach it to transform non-JavaScript file into their JavaScript equivalents with *loaders*.
|
Teach it to transform non-JavaScript file into their JavaScript equivalents with *loaders*.
|
||||||
Configure loaders for TypeScript and CSS as follows.
|
Configure loaders for TypeScript and CSS as follows.
|
||||||
|
|
||||||
|
|
||||||
<div class='code-example'>
|
<div class='code-example'>
|
||||||
|
|
||||||
|
|
||||||
<code-example language="javascript">
|
<code-example language="javascript">
|
||||||
rules: [
|
rules: [
|
||||||
{
|
{
|
||||||
@ -178,8 +188,10 @@ Configure loaders for TypeScript and CSS as follows.
|
|||||||
When Webpack encounters `import` statements like the following,
|
When Webpack encounters `import` statements like the following,
|
||||||
it applies the `test` RegEx patterns.
|
it applies the `test` RegEx patterns.
|
||||||
|
|
||||||
|
|
||||||
<div class='code-example'>
|
<div class='code-example'>
|
||||||
|
|
||||||
|
|
||||||
<code-example language="typescript">
|
<code-example language="typescript">
|
||||||
import { AppComponent } from './app.component.ts';
|
import { AppComponent } from './app.component.ts';
|
||||||
|
|
||||||
@ -208,8 +220,10 @@ Then it applies the `style` loader to append the css inside `<style>` elements o
|
|||||||
Webpack has a build pipeline with well-defined phases.
|
Webpack has a build pipeline with well-defined phases.
|
||||||
Tap into that pipeline with plugins such as the `uglify` minification plugin:
|
Tap into that pipeline with plugins such as the `uglify` minification plugin:
|
||||||
|
|
||||||
|
|
||||||
<div class='code-example'>
|
<div class='code-example'>
|
||||||
|
|
||||||
|
|
||||||
<code-example language="javascript">
|
<code-example language="javascript">
|
||||||
plugins: [
|
plugins: [
|
||||||
new webpack.optimize.UglifyJsPlugin()
|
new webpack.optimize.UglifyJsPlugin()
|
||||||
@ -231,6 +245,7 @@ After that brief orientation, you are ready to build your own Webpack configurat
|
|||||||
Begin by setting up the development environment.
|
Begin by setting up the development environment.
|
||||||
|
|
||||||
Create a new project folder.
|
Create a new project folder.
|
||||||
|
|
||||||
<code-example language="sh" class="code-shell">
|
<code-example language="sh" class="code-shell">
|
||||||
mkdir angular-webpack
|
mkdir angular-webpack
|
||||||
cd angular-webpack
|
cd angular-webpack
|
||||||
@ -240,28 +255,34 @@ Create a new project folder.
|
|||||||
Add these files:
|
Add these files:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-tabs>
|
<code-tabs>
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="package.json" path="webpack/package.webpack.json">
|
<code-pane title="package.json" path="webpack/package.webpack.json">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="src/tsconfig.json" path="webpack/src/tsconfig.1.json">
|
<code-pane title="src/tsconfig.json" path="webpack/src/tsconfig.1.json">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="webpack.config.js" path="webpack/webpack.config.js">
|
<code-pane title="webpack.config.js" path="webpack/webpack.config.js">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="karma.conf.js" path="webpack/karma.webpack.conf.js">
|
<code-pane title="karma.conf.js" path="webpack/karma.webpack.conf.js">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="config/helpers.js" path="webpack/config/helpers.js">
|
<code-pane title="config/helpers.js" path="webpack/config/helpers.js">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
@ -284,6 +305,7 @@ They are listed in the updated `packages.json`.
|
|||||||
~~~
|
~~~
|
||||||
|
|
||||||
Open a terminal window and install the npm packages.
|
Open a terminal window and install the npm packages.
|
||||||
|
|
||||||
<code-example language="sh" class="code-shell">
|
<code-example language="sh" class="code-shell">
|
||||||
npm install
|
npm install
|
||||||
|
|
||||||
@ -302,6 +324,7 @@ Polyfills should be bundled separately from the application and vendor bundles.
|
|||||||
Add a `polyfills.ts` like this one to the `src/` folder.
|
Add a `polyfills.ts` like this one to the `src/` folder.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="webpack/src/polyfills.ts" linenums="false">
|
<code-example path="webpack/src/polyfills.ts" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -311,6 +334,7 @@ Add a `polyfills.ts` like this one to the `src/` folder.
|
|||||||
~~~ {.callout.is-critical}
|
~~~ {.callout.is-critical}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<header>
|
<header>
|
||||||
Loading polyfills
|
Loading polyfills
|
||||||
</header>
|
</header>
|
||||||
@ -334,6 +358,7 @@ All three have a lot of configuration in common.
|
|||||||
Gather the common configuration in a file called `webpack.common.js`.
|
Gather the common configuration in a file called `webpack.common.js`.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="webpack/config/webpack.common.js" linenums="false">
|
<code-example path="webpack/config/webpack.common.js" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -359,6 +384,7 @@ and exports several objects as properties of a `module.exports` object.
|
|||||||
The first export is the `entry` object:
|
The first export is the `entry` object:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="webpack/config/webpack.common.js" region="entries" linenums="false">
|
<code-example path="webpack/config/webpack.common.js" region="entries" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -376,8 +402,10 @@ This `entry` object defines the three bundles:
|
|||||||
The app will `import` dozens if not hundreds of JavaScript and TypeScript files.
|
The app will `import` dozens if not hundreds of JavaScript and TypeScript files.
|
||||||
You could write `import` statements with explicit extensions like this example:
|
You could write `import` statements with explicit extensions like this example:
|
||||||
|
|
||||||
|
|
||||||
<div class='code-example'>
|
<div class='code-example'>
|
||||||
|
|
||||||
|
|
||||||
<code-example language="typescript">
|
<code-example language="typescript">
|
||||||
import { AppComponent } from './app.component.ts';
|
import { AppComponent } from './app.component.ts';
|
||||||
|
|
||||||
@ -391,6 +419,7 @@ Tell Webpack to resolve extension-less file requests by looking for matching fil
|
|||||||
`.ts` extension or `.js` extension (for regular JavaScript files and pre-compiled TypeScript files).
|
`.ts` extension or `.js` extension (for regular JavaScript files and pre-compiled TypeScript files).
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="webpack/config/webpack.common.js" region="resolve" linenums="false">
|
<code-example path="webpack/config/webpack.common.js" region="resolve" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -412,6 +441,7 @@ add `.css` and `.html` to the list.
|
|||||||
Rules tell Webpack which loaders to use for each file, or module:
|
Rules tell Webpack which loaders to use for each file, or module:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="webpack/config/webpack.common.js" region="loaders" linenums="false">
|
<code-example path="webpack/config/webpack.common.js" region="loaders" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -451,6 +481,7 @@ Multiple loaders can be chained using the array notation.
|
|||||||
Finally, create instances of three plugins:
|
Finally, create instances of three plugins:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="webpack/config/webpack.common.js" region="plugins" linenums="false">
|
<code-example path="webpack/config/webpack.common.js" region="plugins" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -503,6 +534,7 @@ These files tend to be short and simple.
|
|||||||
Here is the `webpack.dev.js` development configuration file.
|
Here is the `webpack.dev.js` development configuration file.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="webpack/config/webpack.dev.js" linenums="false">
|
<code-example path="webpack/config/webpack.dev.js" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -525,6 +557,7 @@ other configuration options in this file.
|
|||||||
|
|
||||||
Grab the app code at the end of this guide and try:
|
Grab the app code at the end of this guide and try:
|
||||||
|
|
||||||
|
|
||||||
<code-example language="sh" class="code-shell">
|
<code-example language="sh" class="code-shell">
|
||||||
npm start
|
npm start
|
||||||
|
|
||||||
@ -539,6 +572,7 @@ Grab the app code at the end of this guide and try:
|
|||||||
Configuration of a *production* build resembles *development* configuration with a few key changes.
|
Configuration of a *production* build resembles *development* configuration with a few key changes.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="webpack/config/webpack.prod.js" linenums="false">
|
<code-example path="webpack/config/webpack.prod.js" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -562,12 +596,14 @@ There are additional plugins:
|
|||||||
Thanks to the `DefinePlugin` and the `ENV` variable defined at top, you can enable Angular production mode like this:
|
Thanks to the `DefinePlugin` and the `ENV` variable defined at top, you can enable Angular production mode like this:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="webpack/src/main.ts" region="enable-prod" linenums="false">
|
<code-example path="webpack/src/main.ts" region="enable-prod" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
|
|
||||||
Grab the app code at the end of this guide and try:
|
Grab the app code at the end of this guide and try:
|
||||||
|
|
||||||
|
|
||||||
<code-example language="sh" class="code-shell">
|
<code-example language="sh" class="code-shell">
|
||||||
npm run build
|
npm run build
|
||||||
|
|
||||||
@ -588,6 +624,7 @@ You could merge the test configuration into the `webpack.common` configuration a
|
|||||||
But it might be simpler to start over with a completely fresh configuration.
|
But it might be simpler to start over with a completely fresh configuration.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="webpack/config/webpack.test.js" linenums="false">
|
<code-example path="webpack/config/webpack.test.js" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -595,6 +632,7 @@ But it might be simpler to start over with a completely fresh configuration.
|
|||||||
Reconfigure [Karma](https://karma-runner.github.io/1.0/index.html) to use Webpack to run the tests:
|
Reconfigure [Karma](https://karma-runner.github.io/1.0/index.html) to use Webpack to run the tests:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="webpack/config/karma.conf.js" linenums="false">
|
<code-example path="webpack/config/karma.conf.js" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -606,6 +644,7 @@ The `karma-test-shim` tells Karma what files to pre-load and
|
|||||||
primes the Angular test framework with test versions of the providers that every app expects to be pre-loaded.
|
primes the Angular test framework with test versions of the providers that every app expects to be pre-loaded.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="webpack/config/karma-test-shim.js" linenums="false">
|
<code-example path="webpack/config/karma-test-shim.js" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -616,6 +655,7 @@ Each spec file imports all—and only—the application source code that
|
|||||||
Webpack loads just _those_ specific application files and ignores the other files that you aren't testing.
|
Webpack loads just _those_ specific application files and ignores the other files that you aren't testing.
|
||||||
Grab the app code at the end of this guide and try:
|
Grab the app code at the end of this guide and try:
|
||||||
|
|
||||||
|
|
||||||
<code-example language="sh" class="code-shell">
|
<code-example language="sh" class="code-shell">
|
||||||
npm test
|
npm test
|
||||||
|
|
||||||
@ -627,18 +667,22 @@ Here is the source code for a small application that bundles with the
|
|||||||
Webpack techniques covered in this guide.
|
Webpack techniques covered in this guide.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-tabs>
|
<code-tabs>
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="src/index.html" path="webpack/src/index.html">
|
<code-pane title="src/index.html" path="webpack/src/index.html">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="src/main.ts" path="webpack/src/main.ts">
|
<code-pane title="src/main.ts" path="webpack/src/main.ts">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="src/assets/css/styles.css" path="webpack/src/assets/css/styles.css">
|
<code-pane title="src/assets/css/styles.css" path="webpack/src/assets/css/styles.css">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
@ -648,28 +692,34 @@ Webpack techniques covered in this guide.
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-tabs>
|
<code-tabs>
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="src/app/app.component.ts" path="webpack/src/app/app.component.ts">
|
<code-pane title="src/app/app.component.ts" path="webpack/src/app/app.component.ts">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="src/app/app.component.html" path="webpack/src/app/app.component.html">
|
<code-pane title="src/app/app.component.html" path="webpack/src/app/app.component.html">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="src/app/app.component.css" path="webpack/src/app/app.component.css">
|
<code-pane title="src/app/app.component.css" path="webpack/src/app/app.component.css">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="src/app/app.component.spec.ts" path="webpack/src/app/app.component.spec.ts">
|
<code-pane title="src/app/app.component.spec.ts" path="webpack/src/app/app.component.spec.ts">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="src/app/app.module.ts" path="webpack/src/app/app.module.ts">
|
<code-pane title="src/app/app.module.ts" path="webpack/src/app/app.module.ts">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
@ -687,13 +737,16 @@ on the image and download it to that folder.
|
|||||||
{@a bundle-ts}
|
{@a bundle-ts}
|
||||||
Here again are the TypeScript entry-point files that define the `polyfills` and `vendor` bundles.
|
Here again are the TypeScript entry-point files that define the `polyfills` and `vendor` bundles.
|
||||||
|
|
||||||
|
|
||||||
<code-tabs>
|
<code-tabs>
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="src/polyfills.ts" path="webpack/src/polyfills.ts">
|
<code-pane title="src/polyfills.ts" path="webpack/src/polyfills.ts">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="src/vendor.ts" path="webpack/src/vendor.ts">
|
<code-pane title="src/vendor.ts" path="webpack/src/vendor.ts">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
|
@ -1,19 +1,24 @@
|
|||||||
@description
|
@description
|
||||||
|
|
||||||
|
|
||||||
<div flex=true>
|
<div flex=true>
|
||||||
|
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
What's your question about?
|
What's your question about?
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<select id='feedback-dropdown' name="Angular Version">
|
<select id='feedback-dropdown' name="Angular Version">
|
||||||
|
|
||||||
|
|
||||||
<option value="Angular">
|
<option value="Angular">
|
||||||
Angular
|
Angular
|
||||||
</option>
|
</option>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<option value="AngularJS">
|
<option value="AngularJS">
|
||||||
AngularJS
|
AngularJS
|
||||||
</option>
|
</option>
|
||||||
@ -22,6 +27,7 @@
|
|||||||
</select>
|
</select>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<button id='feedback-btn'>
|
<button id='feedback-btn'>
|
||||||
Submit
|
Submit
|
||||||
</button>
|
</button>
|
||||||
|
@ -1,47 +1,57 @@
|
|||||||
@description
|
@description
|
||||||
|
|
||||||
|
|
||||||
<div class='clearfix'>
|
<div class='clearfix'>
|
||||||
<a class='card' class='c4' href="/docs/#{lang}/#{vers}/quickstart.html">
|
<a class='card' class='c4' href="/docs/#{lang}/#{vers}/quickstart.html">
|
||||||
|
|
||||||
<h2 class='text-headline' class='text-uppercase'>
|
<h2 class='text-headline' class='text-uppercase'>
|
||||||
Quickstart
|
Quickstart
|
||||||
</h2>
|
</h2>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
A short beginner guide explaining the basic concepts of Angular
|
A short beginner guide explaining the basic concepts of Angular
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<footer>
|
<footer>
|
||||||
View Quickstart
|
View Quickstart
|
||||||
</footer>
|
</footer>
|
||||||
|
|
||||||
</a> <a class='card' class='c4' href="/docs/#{lang}/#{vers}/guide/">
|
</a> <a class='card' class='c4' href="/docs/#{lang}/#{vers}/guide/">
|
||||||
|
|
||||||
<h2 class='text-headline' class='text-uppercase'>
|
<h2 class='text-headline' class='text-uppercase'>
|
||||||
Developer Guide
|
Developer Guide
|
||||||
</h2>
|
</h2>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
An intermediate development guide covering all major features of Angular
|
An intermediate development guide covering all major features of Angular
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<footer>
|
<footer>
|
||||||
View Guide
|
View Guide
|
||||||
</footer>
|
</footer>
|
||||||
|
|
||||||
</a> <a class='card' class='c4' href="/docs/#{lang}/#{vers}/api/">
|
</a> <a class='card' class='c4' href="/docs/#{lang}/#{vers}/api/">
|
||||||
|
|
||||||
<h2 class='text-headline' class='text-uppercase'>
|
<h2 class='text-headline' class='text-uppercase'>
|
||||||
API Reference
|
API Reference
|
||||||
</h2>
|
</h2>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
An advanced reference of all Angular Classes, Methods, etc.
|
An advanced reference of all Angular Classes, Methods, etc.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<footer>
|
<footer>
|
||||||
View API
|
View API
|
||||||
</footer>
|
</footer>
|
||||||
@ -50,40 +60,49 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<div class='c4' class='secondary-content-list'>
|
<div class='c4' class='secondary-content-list'>
|
||||||
|
|
||||||
|
|
||||||
<h4>
|
<h4>
|
||||||
Advanced Documentation
|
Advanced Documentation
|
||||||
</h4>
|
</h4>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<ul>
|
<ul>
|
||||||
|
|
||||||
|
|
||||||
<li>
|
<li>
|
||||||
<a href="/docs/#{lang}/#{vers}/guide/animations.html"> Animations </a>
|
<a href="/docs/#{lang}/#{vers}/guide/animations.html"> Animations </a>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<li>
|
<li>
|
||||||
<a href="/docs/#{lang}/#{vers}/guide/attribute-directives.html"> Attribute Directives </a>
|
<a href="/docs/#{lang}/#{vers}/guide/attribute-directives.html"> Attribute Directives </a>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<li>
|
<li>
|
||||||
<a href="/docs/#{lang}/#{vers}/guide/browser-support.html"> Browser Support </a>
|
<a href="/docs/#{lang}/#{vers}/guide/browser-support.html"> Browser Support </a>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<li>
|
<li>
|
||||||
<a href="/docs/#{lang}/#{vers}/guide/component-styles.html"> Component Styles </a>
|
<a href="/docs/#{lang}/#{vers}/guide/component-styles.html"> Component Styles </a>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<li>
|
<li>
|
||||||
<a href="/docs/#{lang}/#{vers}/guide/deployment.html"> Deployment </a>
|
<a href="/docs/#{lang}/#{vers}/guide/deployment.html"> Deployment </a>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<li>
|
<li>
|
||||||
<a href="/docs/#{lang}/#{vers}/guide/animations.html"> View All... </a>
|
<a href="/docs/#{lang}/#{vers}/guide/animations.html"> View All... </a>
|
||||||
</li>
|
</li>
|
||||||
@ -95,35 +114,43 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<div class='c4' class='secondary-content-list'>
|
<div class='c4' class='secondary-content-list'>
|
||||||
|
|
||||||
|
|
||||||
<h4>
|
<h4>
|
||||||
Cookbook
|
Cookbook
|
||||||
</h4>
|
</h4>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<ul>
|
<ul>
|
||||||
|
|
||||||
|
|
||||||
<li>
|
<li>
|
||||||
<a href="/docs/#{lang}/#{vers}/cookbook/aot-compiler.html"> Ahead-of-time Compilation </a>
|
<a href="/docs/#{lang}/#{vers}/cookbook/aot-compiler.html"> Ahead-of-time Compilation </a>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<li>
|
<li>
|
||||||
<a href="/docs/#{lang}/#{vers}/cookbook/ajs-quick-reference.html"> AngularJS to Angular </a>
|
<a href="/docs/#{lang}/#{vers}/cookbook/ajs-quick-reference.html"> AngularJS to Angular </a>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<li>
|
<li>
|
||||||
<a href="/docs/#{lang}/#{vers}/cookbook/component-communication.html"> Component Interaction </a>
|
<a href="/docs/#{lang}/#{vers}/cookbook/component-communication.html"> Component Interaction </a>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<li>
|
<li>
|
||||||
<a href="/docs/#{lang}/#{vers}/cookbook/dependency-injection.html"> Dependency Injection </a>
|
<a href="/docs/#{lang}/#{vers}/cookbook/dependency-injection.html"> Dependency Injection </a>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<li>
|
<li>
|
||||||
<a href="/docs/#{lang}/#{vers}/cookbook/"> View All... </a>
|
<a href="/docs/#{lang}/#{vers}/cookbook/"> View All... </a>
|
||||||
</li>
|
</li>
|
||||||
@ -135,40 +162,49 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<div class='c4' class='secondary-content-list'>
|
<div class='c4' class='secondary-content-list'>
|
||||||
|
|
||||||
|
|
||||||
<h4>
|
<h4>
|
||||||
Tools & Libraries
|
Tools & Libraries
|
||||||
</h4>
|
</h4>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<ul>
|
<ul>
|
||||||
|
|
||||||
|
|
||||||
<li>
|
<li>
|
||||||
<a target="_blank" href="https://github.com/angular/universal"> Angular Universal </a>
|
<a target="_blank" href="https://github.com/angular/universal"> Angular Universal </a>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<li>
|
<li>
|
||||||
<a target="_blank" href="https://augury.angular.io/"> Augury </a>
|
<a target="_blank" href="https://augury.angular.io/"> Augury </a>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<li>
|
<li>
|
||||||
<a target="_blank" href="https://github.com/jaxio/celerio-angular-quickstart"> Celerio Angular Quickstart </a>
|
<a target="_blank" href="https://github.com/jaxio/celerio-angular-quickstart"> Celerio Angular Quickstart </a>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<li>
|
<li>
|
||||||
<a target="_blank" href="https://github.com/mgechev/codelyzer"> Codelyzer </a>
|
<a target="_blank" href="https://github.com/mgechev/codelyzer"> Codelyzer </a>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<li>
|
<li>
|
||||||
<a target="_blank" href="https://github.com/johnpapa/lite-server"> Lite-server </a>
|
<a target="_blank" href="https://github.com/johnpapa/lite-server"> Lite-server </a>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<li>
|
<li>
|
||||||
<a target="_blank" href="/resources/"> View All... </a>
|
<a target="_blank" href="/resources/"> View All... </a>
|
||||||
</li>
|
</li>
|
||||||
|
@ -4,6 +4,7 @@ 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:
|
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 path="quickstart/src/app/app.component.ts" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -26,6 +27,7 @@ Every component begins with an `@Component` [!{_decorator}](glossary)
|
|||||||
|
|
||||||
The `selector` property tells Angular to display the component inside a custom `<my-app>` tag in the `index.html`.
|
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 path="quickstart/src/index.html" region="my-app" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
|
@ -1,38 +1,46 @@
|
|||||||
@description
|
@description
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<h2>
|
<h2>
|
||||||
Victor Savkin's Blog Posts
|
Victor Savkin's Blog Posts
|
||||||
</h2>
|
</h2>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<ul>
|
<ul>
|
||||||
|
|
||||||
|
|
||||||
<li>
|
<li>
|
||||||
<a href="http://victorsavkin.com/post/137821436516/managing-state-in-angular-2-applications"> Managing State in Angular 2 Applications </a>
|
<a href="http://victorsavkin.com/post/137821436516/managing-state-in-angular-2-applications"> Managing State in Angular 2 Applications </a>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<li>
|
<li>
|
||||||
<a href="http://victorsavkin.com/post/114168430846/two-phases-of-angular-2-applications">Two Phases of Angular 2 Applications</a>
|
<a href="http://victorsavkin.com/post/114168430846/two-phases-of-angular-2-applications">Two Phases of Angular 2 Applications</a>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<li>
|
<li>
|
||||||
<a href="http://angularjs.blogspot.com/2015/03/forms-in-angular-2.html">Forms in Angular 2</a>
|
<a href="http://angularjs.blogspot.com/2015/03/forms-in-angular-2.html">Forms in Angular 2</a>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<li>
|
<li>
|
||||||
<a href="http://victorsavkin.com/post/110170125256/change-detection-in-angular-2">Change detection</a>
|
<a href="http://victorsavkin.com/post/110170125256/change-detection-in-angular-2">Change detection</a>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<li>
|
<li>
|
||||||
<a href="http://victorsavkin.com/post/108837493941/better-support-for-functional-programming-in">Functional programming </a>
|
<a href="http://victorsavkin.com/post/108837493941/better-support-for-functional-programming-in">Functional programming </a>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<li>
|
<li>
|
||||||
<a href="http://victorsavkin.com/post/102965317996/angular-2-bits-unified-dependency-injection">Dependency injection</a>
|
<a href="http://victorsavkin.com/post/102965317996/angular-2-bits-unified-dependency-injection">Dependency injection</a>
|
||||||
</li>
|
</li>
|
||||||
@ -42,23 +50,28 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<h2>
|
<h2>
|
||||||
<span class="icon-play-circle-outline"></span> Videos
|
<span class="icon-play-circle-outline"></span> Videos
|
||||||
</h2>
|
</h2>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<h4>
|
<h4>
|
||||||
Intro Videos
|
Intro Videos
|
||||||
</h4>
|
</h4>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<ul>
|
<ul>
|
||||||
|
|
||||||
|
|
||||||
<li>
|
<li>
|
||||||
<a href="https://www.youtube.com/watch?v=uD6Okha_Yj0">Building a Todo App</a> by David East
|
<a href="https://www.youtube.com/watch?v=uD6Okha_Yj0">Building a Todo App</a> by David East
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<li>
|
<li>
|
||||||
<a href="https://www.youtube.com/watch?v=4C4bmDOV5hk">Angular 2 Forms</a> by David East
|
<a href="https://www.youtube.com/watch?v=4C4bmDOV5hk">Angular 2 Forms</a> by David East
|
||||||
</li>
|
</li>
|
||||||
@ -67,33 +80,40 @@
|
|||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<h4>
|
<h4>
|
||||||
ng-conf
|
ng-conf
|
||||||
</h4>
|
</h4>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<ul>
|
<ul>
|
||||||
|
|
||||||
|
|
||||||
<li>
|
<li>
|
||||||
Playlist <a href="https://www.youtube.com/watch?v=QHulaj5ZxbI&index=1&list=PLOETEcp3DkCoNnlhE-7fovYvqwVPrRiY7">of ng-conf 2015 videos</a>.
|
Playlist <a href="https://www.youtube.com/watch?v=QHulaj5ZxbI&index=1&list=PLOETEcp3DkCoNnlhE-7fovYvqwVPrRiY7">of ng-conf 2015 videos</a>.
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<li>
|
<li>
|
||||||
<a href="https://www.youtube.com/watch?v=QHulaj5ZxbI&list=PLOETEcp3DkCoNnlhE-7fovYvqwVPrRiY7">Day 1 Keynote</a>: a broad overview of Angular 2, migration, and where we are headed.
|
<a href="https://www.youtube.com/watch?v=QHulaj5ZxbI&list=PLOETEcp3DkCoNnlhE-7fovYvqwVPrRiY7">Day 1 Keynote</a>: a broad overview of Angular 2, migration, and where we are headed.
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<li>
|
<li>
|
||||||
<a href="https://www.youtube.com/watch?v=-dMBcqwvYA0&index=21&list=PLOETEcp3DkCoNnlhE-7fovYvqwVPrRiY7">Day 2 Keynote</a>: Misko and Rado do a deep-dive on Angular 2 details.
|
<a href="https://www.youtube.com/watch?v=-dMBcqwvYA0&index=21&list=PLOETEcp3DkCoNnlhE-7fovYvqwVPrRiY7">Day 2 Keynote</a>: Misko and Rado do a deep-dive on Angular 2 details.
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<li>
|
<li>
|
||||||
<a href="https://www.youtube.com/watch?v=AbunztfV5vU&index=6&list=PLOETEcp3DkCoNnlhE-7fovYvqwVPrRiY7">Creating Container Components with Web Components in Angular</a>: Kara Erickson & Rachael L Moore.
|
<a href="https://www.youtube.com/watch?v=AbunztfV5vU&index=6&list=PLOETEcp3DkCoNnlhE-7fovYvqwVPrRiY7">Creating Container Components with Web Components in Angular</a>: Kara Erickson & Rachael L Moore.
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<li>
|
<li>
|
||||||
<a href="https://www.youtube.com/watch?v=jvKGQSFQf10&index=31&list=PLOETEcp3DkCoNnlhE-7fovYvqwVPrRiY7">Change Detection Reinvented</a>: Why Angular 2 change detection is fast out of the box and options for developers to make it even faster.
|
<a href="https://www.youtube.com/watch?v=jvKGQSFQf10&index=31&list=PLOETEcp3DkCoNnlhE-7fovYvqwVPrRiY7">Change Detection Reinvented</a>: Why Angular 2 change detection is fast out of the box and options for developers to make it even faster.
|
||||||
</li>
|
</li>
|
||||||
@ -102,13 +122,16 @@
|
|||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<h4>
|
<h4>
|
||||||
ng-europe
|
ng-europe
|
||||||
</h4>
|
</h4>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<ul>
|
<ul>
|
||||||
|
|
||||||
|
|
||||||
<li>
|
<li>
|
||||||
Oct 2014 <a href="https://www.youtube.com/watch?v=lGdnh8QSPPk&list=PLhc_bKwZngxW_ZlY0NkaGkvKpiA_pzcZ-">playlist of ng-europe videos on Angular 2</a> and the future of Angular.
|
Oct 2014 <a href="https://www.youtube.com/watch?v=lGdnh8QSPPk&list=PLhc_bKwZngxW_ZlY0NkaGkvKpiA_pzcZ-">playlist of ng-europe videos on Angular 2</a> and the future of Angular.
|
||||||
</li>
|
</li>
|
||||||
@ -118,33 +141,40 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<h2>
|
<h2>
|
||||||
<span class="icon-content-copy"></span> API Design Docs & Notes
|
<span class="icon-content-copy"></span> API Design Docs & Notes
|
||||||
</h2>
|
</h2>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<ul>
|
<ul>
|
||||||
|
|
||||||
|
|
||||||
<li>
|
<li>
|
||||||
<a href="https://drive.google.com/open?id=0B7GYXx6a6d8QR3lTT1J3MEpRSlE&authuser=0">Best Practices</a>
|
<a href="https://drive.google.com/open?id=0B7GYXx6a6d8QR3lTT1J3MEpRSlE&authuser=0">Best Practices</a>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<li>
|
<li>
|
||||||
<a href="https://drive.google.com/open?id=0BxgtL8yFJbacUnUxc3l5aTZrbVk&authuser=0">API Design Docs</a>
|
<a href="https://drive.google.com/open?id=0BxgtL8yFJbacUnUxc3l5aTZrbVk&authuser=0">API Design Docs</a>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<li>
|
<li>
|
||||||
<a href="https://drive.google.com/open?id=0BxgtL8yFJbacMEZDc2NtWS1VZ1k&authuser=0">Meeting Notes</a>
|
<a href="https://drive.google.com/open?id=0BxgtL8yFJbacMEZDc2NtWS1VZ1k&authuser=0">Meeting Notes</a>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<li>
|
<li>
|
||||||
<a href="https://drive.google.com/open?id=0BxgtL8yFJbaceGc2dlhGQnMzYXc&authuser=0">Presentations</a>
|
<a href="https://drive.google.com/open?id=0BxgtL8yFJbaceGc2dlhGQnMzYXc&authuser=0">Presentations</a>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<li>
|
<li>
|
||||||
<a href="http://goo.gl/sj0Nk1">More...</a>
|
<a href="http://goo.gl/sj0Nk1">More...</a>
|
||||||
</li>
|
</li>
|
||||||
|
@ -35,6 +35,7 @@ When you're done with this tutorial, the app will look like this <live-example n
|
|||||||
Here's a visual idea of where this tutorial leads, beginning with the "Dashboard"
|
Here's a visual idea of where this tutorial leads, beginning with the "Dashboard"
|
||||||
view and the most heroic heroes:
|
view and the most heroic heroes:
|
||||||
|
|
||||||
|
|
||||||
<figure class='image-display'>
|
<figure class='image-display'>
|
||||||
<img src='assets/images/devguide/toh/heroes-dashboard-1.png' alt="Output of heroes dashboard"> </img>
|
<img src='assets/images/devguide/toh/heroes-dashboard-1.png' alt="Output of heroes dashboard"> </img>
|
||||||
</figure>
|
</figure>
|
||||||
@ -45,6 +46,7 @@ to navigate between this Dashboard view and a Heroes view.
|
|||||||
If you click the dashboard hero "Magneta," the router opens a "Hero Details" view
|
If you click the dashboard hero "Magneta," the router opens a "Hero Details" view
|
||||||
where you can change the hero's name.
|
where you can change the hero's name.
|
||||||
|
|
||||||
|
|
||||||
<figure class='image-display'>
|
<figure class='image-display'>
|
||||||
<img src='assets/images/devguide/toh/hero-details-1.png' alt="Details of hero in app"> </img>
|
<img src='assets/images/devguide/toh/hero-details-1.png' alt="Details of hero in app"> </img>
|
||||||
</figure>
|
</figure>
|
||||||
@ -53,6 +55,7 @@ Clicking the "Back" button returns you to the Dashboard.
|
|||||||
Links at the top take you to either of the main views.
|
Links at the top take you to either of the main views.
|
||||||
If you click "Heroes," the app displays the "Heroes" master list view.
|
If you click "Heroes," the app displays the "Heroes" master list view.
|
||||||
|
|
||||||
|
|
||||||
<figure class='image-display'>
|
<figure class='image-display'>
|
||||||
<img src='assets/images/devguide/toh/heroes-list-2.png' alt="Output of heroes list app"> </img>
|
<img src='assets/images/devguide/toh/heroes-list-2.png' alt="Output of heroes list app"> </img>
|
||||||
</figure>
|
</figure>
|
||||||
@ -64,12 +67,14 @@ editable details of the selected hero.
|
|||||||
|
|
||||||
The following diagram captures all of the navigation options.
|
The following diagram captures all of the navigation options.
|
||||||
|
|
||||||
|
|
||||||
<figure class='image-display'>
|
<figure class='image-display'>
|
||||||
<img src='assets/images/devguide/toh/nav-diagram.png' alt="View navigations"> </img>
|
<img src='assets/images/devguide/toh/nav-diagram.png' alt="View navigations"> </img>
|
||||||
</figure>
|
</figure>
|
||||||
|
|
||||||
Here's the app in action:
|
Here's the app in action:
|
||||||
|
|
||||||
|
|
||||||
<figure class='image-display'>
|
<figure class='image-display'>
|
||||||
<img src='assets/images/devguide/toh/toh-anim.gif' alt="Tour of Heroes in Action"> </img>
|
<img src='assets/images/devguide/toh/toh-anim.gif' alt="Tour of Heroes in Action"> </img>
|
||||||
</figure>
|
</figure>
|
||||||
|
@ -11,19 +11,25 @@ named <ngio-ex path="angular-tour-of-heroes"></ngio-ex>.
|
|||||||
|
|
||||||
The file structure should look like this:
|
The file structure should look like this:
|
||||||
|
|
||||||
|
|
||||||
<aio-filetree>
|
<aio-filetree>
|
||||||
|
|
||||||
|
|
||||||
<aio-folder>
|
<aio-folder>
|
||||||
angular-tour-of-heroes
|
angular-tour-of-heroes
|
||||||
|
|
||||||
<aio-folder>
|
<aio-folder>
|
||||||
src
|
src
|
||||||
|
|
||||||
<aio-folder>
|
<aio-folder>
|
||||||
app
|
app
|
||||||
|
|
||||||
<aio-file>
|
<aio-file>
|
||||||
app.component.ts
|
app.component.ts
|
||||||
</aio-file>
|
</aio-file>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<aio-file>
|
<aio-file>
|
||||||
app.module.ts
|
app.module.ts
|
||||||
</aio-file>
|
</aio-file>
|
||||||
@ -32,26 +38,31 @@ The file structure should look like this:
|
|||||||
</aio-folder>
|
</aio-folder>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<aio-file>
|
<aio-file>
|
||||||
main.ts
|
main.ts
|
||||||
</aio-file>
|
</aio-file>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<aio-file>
|
<aio-file>
|
||||||
index.html
|
index.html
|
||||||
</aio-file>
|
</aio-file>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<aio-file>
|
<aio-file>
|
||||||
styles.css
|
styles.css
|
||||||
</aio-file>
|
</aio-file>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<aio-file>
|
<aio-file>
|
||||||
systemjs.config.js
|
systemjs.config.js
|
||||||
</aio-file>
|
</aio-file>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<aio-file>
|
<aio-file>
|
||||||
tsconfig.json
|
tsconfig.json
|
||||||
</aio-file>
|
</aio-file>
|
||||||
@ -60,11 +71,13 @@ The file structure should look like this:
|
|||||||
</aio-folder>
|
</aio-folder>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<aio-file>
|
<aio-file>
|
||||||
node_modules ...
|
node_modules ...
|
||||||
</aio-file>
|
</aio-file>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<aio-file>
|
<aio-file>
|
||||||
package.json
|
package.json
|
||||||
</aio-file>
|
</aio-file>
|
||||||
@ -82,6 +95,7 @@ When you're done with this page, the app should look like this <live-example></l
|
|||||||
## Keep the app transpiling and running
|
## Keep the app transpiling and running
|
||||||
Enter the following command in the terminal window:
|
Enter the following command in the terminal window:
|
||||||
|
|
||||||
|
|
||||||
<code-example language="sh" class="code-shell">
|
<code-example language="sh" class="code-shell">
|
||||||
npm start
|
npm start
|
||||||
|
|
||||||
@ -97,6 +111,7 @@ Add two properties to the `AppComponent`: a `title` property for the app name an
|
|||||||
for a hero named "Windstorm."
|
for a hero named "Windstorm."
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="toh-1/app/app.component.1.ts" region="app-component-1" linenums="false">
|
<code-example path="toh-1/app/app.component.1.ts" region="app-component-1" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -104,6 +119,7 @@ for a hero named "Windstorm."
|
|||||||
Now update the template in the `@Component` decorator with data bindings to these new properties.
|
Now update the template in the `@Component` decorator with data bindings to these new properties.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="toh-1/app/app.component.1.ts" region="show-hero" linenums="false">
|
<code-example path="toh-1/app/app.component.1.ts" region="show-hero" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -131,6 +147,7 @@ Create a `Hero` class with `id` and `name` properties.
|
|||||||
Add these properties near the top of the `app.component.ts` file, just below the import statement.
|
Add these properties near the top of the `app.component.ts` file, just below the import statement.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="toh-1/src/app/app.component.ts" region="hero-class-1" linenums="false">
|
<code-example path="toh-1/src/app/app.component.ts" region="hero-class-1" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -139,6 +156,7 @@ In the `Hero` class, refactor the component's `hero` property to be of type `Her
|
|||||||
then initialize it with an `id` of `1` and the name `Windstorm`.
|
then initialize it with an `id` of `1` and the name `Windstorm`.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="toh-1/src/app/app.component.ts" region="hero-property-1" linenums="false">
|
<code-example path="toh-1/src/app/app.component.ts" region="hero-property-1" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -147,6 +165,7 @@ Because you changed the hero from a string to an object,
|
|||||||
update the binding in the template to refer to the hero's `name` property.
|
update the binding in the template to refer to the hero's `name` property.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="toh-1/app/app.component.1.ts" region="show-hero-2">
|
<code-example path="toh-1/app/app.component.1.ts" region="show-hero-2">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -165,6 +184,7 @@ thanks to the <i>template literals</i> feature in ES2015 and TypeScript. For mor
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="toh-1/app/app.component.1.ts" region="multi-line-strings" linenums="false">
|
<code-example path="toh-1/app/app.component.1.ts" region="multi-line-strings" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -182,6 +202,7 @@ You need a two-way binding between the `<input>` form element and the `hero.name
|
|||||||
|
|
||||||
Refactor the hero name in the template so it looks like this:
|
Refactor the hero name in the template so it looks like this:
|
||||||
|
|
||||||
|
|
||||||
<code-example path="toh-1/app/app.component.1.ts" region="name-input" linenums="false">
|
<code-example path="toh-1/app/app.component.1.ts" region="name-input" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -207,6 +228,7 @@ of external modules that the app uses.
|
|||||||
|
|
||||||
The updated `AppModule` looks like this:
|
The updated `AppModule` looks like this:
|
||||||
|
|
||||||
|
|
||||||
<code-example path="toh-1/src/app/app.module.ts">
|
<code-example path="toh-1/src/app/app.module.ts">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -242,6 +264,7 @@ Your app should look like this <live-example></live-example>.
|
|||||||
Here's the complete `app.component.ts` as it stands now:
|
Here's the complete `app.component.ts` as it stands now:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="toh-1/src/app/app.component.ts">
|
<code-example path="toh-1/src/app/app.component.ts">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
|
@ -15,19 +15,25 @@ Before you continue with this page of the Tour of Heroes,
|
|||||||
verify that you have the following structure after [The Hero Editor](tutorial/toh-pt1) page.
|
verify that you have the following structure after [The Hero Editor](tutorial/toh-pt1) page.
|
||||||
If your structure doesn't match, go back to that page to figure out what you missed.
|
If your structure doesn't match, go back to that page to figure out what you missed.
|
||||||
|
|
||||||
|
|
||||||
<aio-filetree>
|
<aio-filetree>
|
||||||
|
|
||||||
|
|
||||||
<aio-folder>
|
<aio-folder>
|
||||||
angular-tour-of-heroes
|
angular-tour-of-heroes
|
||||||
|
|
||||||
<aio-folder>
|
<aio-folder>
|
||||||
src
|
src
|
||||||
|
|
||||||
<aio-folder>
|
<aio-folder>
|
||||||
app
|
app
|
||||||
|
|
||||||
<aio-file>
|
<aio-file>
|
||||||
app.component.ts
|
app.component.ts
|
||||||
</aio-file>
|
</aio-file>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<aio-file>
|
<aio-file>
|
||||||
app.module.ts
|
app.module.ts
|
||||||
</aio-file>
|
</aio-file>
|
||||||
@ -36,26 +42,31 @@ If your structure doesn't match, go back to that page to figure out what you mis
|
|||||||
</aio-folder>
|
</aio-folder>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<aio-file>
|
<aio-file>
|
||||||
main.ts
|
main.ts
|
||||||
</aio-file>
|
</aio-file>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<aio-file>
|
<aio-file>
|
||||||
index.html
|
index.html
|
||||||
</aio-file>
|
</aio-file>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<aio-file>
|
<aio-file>
|
||||||
styles.css
|
styles.css
|
||||||
</aio-file>
|
</aio-file>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<aio-file>
|
<aio-file>
|
||||||
systemjs.config.js
|
systemjs.config.js
|
||||||
</aio-file>
|
</aio-file>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<aio-file>
|
<aio-file>
|
||||||
tsconfig.json
|
tsconfig.json
|
||||||
</aio-file>
|
</aio-file>
|
||||||
@ -64,11 +75,13 @@ If your structure doesn't match, go back to that page to figure out what you mis
|
|||||||
</aio-folder>
|
</aio-folder>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<aio-file>
|
<aio-file>
|
||||||
node_modules ...
|
node_modules ...
|
||||||
</aio-file>
|
</aio-file>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<aio-file>
|
<aio-file>
|
||||||
package.json
|
package.json
|
||||||
</aio-file>
|
</aio-file>
|
||||||
@ -82,6 +95,7 @@ If your structure doesn't match, go back to that page to figure out what you mis
|
|||||||
## Keep the app transpiling and running
|
## Keep the app transpiling and running
|
||||||
Enter the following command in the terminal window:
|
Enter the following command in the terminal window:
|
||||||
|
|
||||||
|
|
||||||
<code-example language="sh" class="code-shell">
|
<code-example language="sh" class="code-shell">
|
||||||
npm start
|
npm start
|
||||||
|
|
||||||
@ -99,6 +113,7 @@ To display a list of heroes, you'll add heroes to the view's template.
|
|||||||
Create an array of ten heroes.
|
Create an array of ten heroes.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="toh-2/src/app/app.component.ts" region="hero-array">
|
<code-example path="toh-2/src/app/app.component.ts" region="hero-array">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -112,6 +127,7 @@ Create a public property in `AppComponent` that exposes the heroes for binding.
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="toh-2/app/app.component.1.html" region="hero-array-1">
|
<code-example path="toh-2/app/app.component.1.html" region="hero-array-1">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -133,6 +149,7 @@ insert the following chunk of HTML below the title and above the hero details.
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="toh-2/app/app.component.1.html" region="heroes-template-1" linenums="false">
|
<code-example path="toh-2/app/app.component.1.html" region="heroes-template-1" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -147,6 +164,7 @@ and display them individually.
|
|||||||
Modify the `<li>` tag by adding the built-in directive `*ngFor`.
|
Modify the `<li>` tag by adding the built-in directive `*ngFor`.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="toh-2/app/app.component.1.html" region="heroes-ngfor-1">
|
<code-example path="toh-2/app/app.component.1.html" region="heroes-ngfor-1">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -180,6 +198,7 @@ that uses the `hero` template variable to display the hero's properties.
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="toh-2/app/app.component.1.html" region="ng-for" linenums="false">
|
<code-example path="toh-2/app/app.component.1.html" region="ng-for" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -193,6 +212,7 @@ To add styles to your component, set the `styles` property on the `@Component` d
|
|||||||
to the following CSS classes:
|
to the following CSS classes:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="toh-2/src/app/app.component.ts" region="styles" linenums="false">
|
<code-example path="toh-2/src/app/app.component.ts" region="styles" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -208,6 +228,7 @@ The template for displaying heroes should look like this:
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="toh-2/app/app.component.1.html" region="heroes-styled" linenums="false">
|
<code-example path="toh-2/app/app.component.1.html" region="heroes-styled" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -228,6 +249,7 @@ Add a click event binding to the `<li>` like this:
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="toh-2/app/app.component.1.html" region="selectedHero-click" linenums="false">
|
<code-example path="toh-2/app/app.component.1.html" region="selectedHero-click" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -253,6 +275,7 @@ But the user will be able to select one of the heroes by clicking on it.
|
|||||||
So replace the `hero` property with this simple `selectedHero` property:
|
So replace the `hero` property with this simple `selectedHero` property:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="toh-2/src/app/app.component.ts" region="selected-hero">
|
<code-example path="toh-2/src/app/app.component.ts" region="selected-hero">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -262,6 +285,7 @@ you won't initialize the `selectedHero` as you did with `hero`.
|
|||||||
|
|
||||||
Add an `onSelect` method that sets the `selectedHero` property to the `hero` that the user clicks.
|
Add an `onSelect` method that sets the `selectedHero` property to the `hero` that the user clicks.
|
||||||
|
|
||||||
|
|
||||||
<code-example path="toh-2/src/app/app.component.ts" region="on-select" linenums="false">
|
<code-example path="toh-2/src/app/app.component.ts" region="on-select" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -271,6 +295,7 @@ Bind to the new selectedHero property instead as follows:
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="toh-2/app/app.component.1.html" region="selectedHero-details" linenums="false">
|
<code-example path="toh-2/app/app.component.1.html" region="selectedHero-details" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -281,6 +306,7 @@ When the app loads, the `selectedHero` is undefined and won't be defined until y
|
|||||||
Angular can't display properties of the undefined `selectedHero` and throws the following error,
|
Angular can't display properties of the undefined `selectedHero` and throws the following error,
|
||||||
visible in the browser's console:
|
visible in the browser's console:
|
||||||
|
|
||||||
|
|
||||||
<code-example format="nocode">
|
<code-example format="nocode">
|
||||||
EXCEPTION: TypeError: Cannot read property 'name' of undefined in [null]
|
EXCEPTION: TypeError: Cannot read property 'name' of undefined in [null]
|
||||||
|
|
||||||
@ -293,6 +319,7 @@ Wrap the HTML hero detail content of the template with a `<div>`.
|
|||||||
Then add the `ngIf` built-in directive and set it to the `selectedHero` property of the component.
|
Then add the `ngIf` built-in directive and set it to the `selectedHero` property of the component.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="toh-2/app/app.component.1.html" region="ng-if" linenums="false">
|
<code-example path="toh-2/app/app.component.1.html" region="ng-if" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -334,12 +361,14 @@ To make the selected hero more visible, you'll apply this `selected` class to th
|
|||||||
For example, when the user clicks "Magneta", it should render with a distinctive but subtle background color
|
For example, when the user clicks "Magneta", it should render with a distinctive but subtle background color
|
||||||
like this:
|
like this:
|
||||||
|
|
||||||
|
|
||||||
<figure class='image-display'>
|
<figure class='image-display'>
|
||||||
<img src='assets/images/devguide/toh/heroes-list-selected.png' alt="Selected hero"> </img>
|
<img src='assets/images/devguide/toh/heroes-list-selected.png' alt="Selected hero"> </img>
|
||||||
</figure>
|
</figure>
|
||||||
|
|
||||||
In the template, add the following `[class.selected]` binding to the `<li>`:
|
In the template, add the following `[class.selected]` binding to the `<li>`:
|
||||||
|
|
||||||
|
|
||||||
<code-example path="toh-2/app/app.component.1.html" region="class-selected-1" linenums="false">
|
<code-example path="toh-2/app/app.component.1.html" region="class-selected-1" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -358,12 +387,14 @@ Read more about the `[class]` binding in the [Template Syntax](guide/template-sy
|
|||||||
|
|
||||||
The final version of the `<li>` looks like this:
|
The final version of the `<li>` looks like this:
|
||||||
|
|
||||||
|
|
||||||
<code-example path="toh-2/app/app.component.1.html" region="class-selected-2" linenums="false">
|
<code-example path="toh-2/app/app.component.1.html" region="class-selected-2" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
|
|
||||||
After clicking "Magneta", the list should look like this:
|
After clicking "Magneta", the list should look like this:
|
||||||
|
|
||||||
|
|
||||||
<figure class='image-display'>
|
<figure class='image-display'>
|
||||||
<img src='assets/images/devguide/toh/heroes-list-1.png' alt="Output of heroes list app"> </img>
|
<img src='assets/images/devguide/toh/heroes-list-1.png' alt="Output of heroes list app"> </img>
|
||||||
</figure>
|
</figure>
|
||||||
@ -371,6 +402,7 @@ After clicking "Magneta", the list should look like this:
|
|||||||
Here's the complete `app.component.ts` as of now:
|
Here's the complete `app.component.ts` as of now:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="toh-2/src/app/app.component.ts">
|
<code-example path="toh-2/src/app/app.component.ts">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
|
@ -21,19 +21,25 @@ When you're done, the app should look like this <live-example></live-example>.
|
|||||||
Before getting started on this page, verify that you have the following structure from earlier in the Tour of Heroes.
|
Before getting started on this page, verify that you have the following structure from earlier in the Tour of Heroes.
|
||||||
If not, go back to the previous pages.
|
If not, go back to the previous pages.
|
||||||
|
|
||||||
|
|
||||||
<aio-filetree>
|
<aio-filetree>
|
||||||
|
|
||||||
|
|
||||||
<aio-folder>
|
<aio-folder>
|
||||||
angular-tour-of-heroes
|
angular-tour-of-heroes
|
||||||
|
|
||||||
<aio-folder>
|
<aio-folder>
|
||||||
src
|
src
|
||||||
|
|
||||||
<aio-folder>
|
<aio-folder>
|
||||||
app
|
app
|
||||||
|
|
||||||
<aio-file>
|
<aio-file>
|
||||||
app.component.ts
|
app.component.ts
|
||||||
</aio-file>
|
</aio-file>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<aio-file>
|
<aio-file>
|
||||||
app.module.ts
|
app.module.ts
|
||||||
</aio-file>
|
</aio-file>
|
||||||
@ -42,26 +48,31 @@ If not, go back to the previous pages.
|
|||||||
</aio-folder>
|
</aio-folder>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<aio-file>
|
<aio-file>
|
||||||
main.ts
|
main.ts
|
||||||
</aio-file>
|
</aio-file>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<aio-file>
|
<aio-file>
|
||||||
index.html
|
index.html
|
||||||
</aio-file>
|
</aio-file>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<aio-file>
|
<aio-file>
|
||||||
styles.css
|
styles.css
|
||||||
</aio-file>
|
</aio-file>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<aio-file>
|
<aio-file>
|
||||||
systemjs.config.js
|
systemjs.config.js
|
||||||
</aio-file>
|
</aio-file>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<aio-file>
|
<aio-file>
|
||||||
tsconfig.json
|
tsconfig.json
|
||||||
</aio-file>
|
</aio-file>
|
||||||
@ -70,11 +81,13 @@ If not, go back to the previous pages.
|
|||||||
</aio-folder>
|
</aio-folder>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<aio-file>
|
<aio-file>
|
||||||
node_modules ...
|
node_modules ...
|
||||||
</aio-file>
|
</aio-file>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<aio-file>
|
<aio-file>
|
||||||
package.json
|
package.json
|
||||||
</aio-file>
|
</aio-file>
|
||||||
@ -106,6 +119,7 @@ The `HeroDetailComponent` class goes in the `hero-detail.component.ts` file.
|
|||||||
Start writing the `HeroDetailComponent` as follows:
|
Start writing the `HeroDetailComponent` as follows:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="toh-3/app/hero-detail.component.1.ts" region="v1" linenums="false">
|
<code-example path="toh-3/app/hero-detail.component.1.ts" region="v1" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -131,6 +145,7 @@ Replace the word, "selectedHero", with the word, "hero", everywhere in the templ
|
|||||||
When you're done, the new template should look like this:
|
When you're done, the new template should look like this:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="toh-3/src/app/hero-detail.component.ts" region="template" linenums="false">
|
<code-example path="toh-3/src/app/hero-detail.component.ts" region="template" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -140,6 +155,7 @@ When you're done, the new template should look like this:
|
|||||||
The `HeroDetailComponent` template binds to the component's `hero` property.
|
The `HeroDetailComponent` template binds to the component's `hero` property.
|
||||||
Add that property to the `HeroDetailComponent` class like this:
|
Add that property to the `HeroDetailComponent` class like this:
|
||||||
|
|
||||||
|
|
||||||
<code-example path="toh-3/app/hero-detail.component.1.ts" region="hero">
|
<code-example path="toh-3/app/hero-detail.component.1.ts" region="hero">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -152,6 +168,7 @@ The Angular [style guide](guide/style-guide) recommends one class per file anywa
|
|||||||
Move the `Hero` class from `app.component.ts` to its own `hero.ts` file.
|
Move the `Hero` class from `app.component.ts` to its own `hero.ts` file.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="toh-3/src/app/hero.ts" linenums="false">
|
<code-example path="toh-3/src/app/hero.ts" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -159,6 +176,7 @@ Move the `Hero` class from `app.component.ts` to its own `hero.ts` file.
|
|||||||
Now that the `Hero` class is in its own file, the `AppComponent` and the `HeroDetailComponent` have to import it.
|
Now that the `Hero` class is in its own file, the `AppComponent` and the `HeroDetailComponent` have to import it.
|
||||||
Add the following `import` statement near the top of _both_ the `app.component.ts` and the `hero-detail.component.ts` files.
|
Add the following `import` statement near the top of _both_ the `app.component.ts` and the `hero-detail.component.ts` files.
|
||||||
|
|
||||||
|
|
||||||
<code-example path="toh-3/app/hero-detail.component.1.ts" region="hero-import">
|
<code-example path="toh-3/app/hero-detail.component.1.ts" region="hero-import">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -170,6 +188,7 @@ the parent `AppComponent` will tell the child `HeroDetailComponent` which hero t
|
|||||||
by binding its `selectedHero` to the `hero` property of the `HeroDetailComponent`.
|
by binding its `selectedHero` to the `hero` property of the `HeroDetailComponent`.
|
||||||
The binding will look like this:
|
The binding will look like this:
|
||||||
|
|
||||||
|
|
||||||
<code-example path="toh-3/app/app.component.1.html" region="hero-detail-binding" linenums="false">
|
<code-example path="toh-3/app/app.component.1.html" region="hero-detail-binding" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -181,6 +200,7 @@ Otherwise, Angular rejects the binding and throws an error.
|
|||||||
|
|
||||||
First, amend the `@angular/core` import statement to include the `Input` symbol.
|
First, amend the `@angular/core` import statement to include the `Input` symbol.
|
||||||
|
|
||||||
|
|
||||||
<code-example path="toh-3/src/app/hero-detail.component.ts" region="import-input" linenums="false">
|
<code-example path="toh-3/src/app/hero-detail.component.ts" region="import-input" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -188,6 +208,7 @@ First, amend the `@angular/core` import statement to include the `Input` symbol.
|
|||||||
Then declare that `hero` is an *input* property by
|
Then declare that `hero` is an *input* property by
|
||||||
preceding it with the `@Input` decorator that you imported earlier.
|
preceding it with the `@Input` decorator that you imported earlier.
|
||||||
|
|
||||||
|
|
||||||
<code-example path="toh-3/src/app/hero-detail.component.ts" region="hero" linenums="false">
|
<code-example path="toh-3/src/app/hero-detail.component.ts" region="hero" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -204,6 +225,7 @@ Read more about _input_ properties in the
|
|||||||
|
|
||||||
That's it. The `hero` property is the only thing in the `HeroDetailComponent` class.
|
That's it. The `hero` property is the only thing in the `HeroDetailComponent` class.
|
||||||
|
|
||||||
|
|
||||||
<code-example path="toh-3/src/app/hero-detail.component.ts" region="class" linenums="false">
|
<code-example path="toh-3/src/app/hero-detail.component.ts" region="class" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -212,6 +234,7 @@ All it does is receive a hero object through its `hero` input property and then
|
|||||||
|
|
||||||
Here's the complete `HeroDetailComponent`.
|
Here's the complete `HeroDetailComponent`.
|
||||||
|
|
||||||
|
|
||||||
<code-example path="toh-3/src/app/hero-detail.component.ts">
|
<code-example path="toh-3/src/app/hero-detail.component.ts">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -222,6 +245,7 @@ Every component must be declared in one—and only one—Angular module.
|
|||||||
|
|
||||||
Open `app.module.ts` in your editor and import the `HeroDetailComponent` so you can refer to it.
|
Open `app.module.ts` in your editor and import the `HeroDetailComponent` so you can refer to it.
|
||||||
|
|
||||||
|
|
||||||
<code-example path="toh-3/src/app/app.module.ts" region="hero-detail-import">
|
<code-example path="toh-3/src/app/app.module.ts" region="hero-detail-import">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -229,6 +253,7 @@ Open `app.module.ts` in your editor and import the `HeroDetailComponent` so you
|
|||||||
Add `HeroDetailComponent` to the module's `declarations` array.
|
Add `HeroDetailComponent` to the module's `declarations` array.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="toh-3/src/app/app.module.ts" region="declarations" linenums="false">
|
<code-example path="toh-3/src/app/app.module.ts" region="declarations" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -264,6 +289,7 @@ Coordinate the master `AppComponent` with the `HeroDetailComponent`
|
|||||||
by binding the `selectedHero` property of the `AppComponent`
|
by binding the `selectedHero` property of the `AppComponent`
|
||||||
to the `hero` property of the `HeroDetailComponent`.
|
to the `hero` property of the `HeroDetailComponent`.
|
||||||
|
|
||||||
|
|
||||||
<code-example path="toh-3/app/app.component.1.html" region="hero-detail-binding" linenums="false">
|
<code-example path="toh-3/app/app.component.1.html" region="hero-detail-binding" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -273,6 +299,7 @@ Now every time the `selectedHero` changes, the `HeroDetailComponent` gets a new
|
|||||||
The revised `AppComponent` template should look like this:
|
The revised `AppComponent` template should look like this:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="toh-3/src/app/app.component.ts" region="hero-detail-template" linenums="false">
|
<code-example path="toh-3/src/app/app.component.ts" region="hero-detail-template" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -297,29 +324,37 @@ without touching the parent `AppComponent`.
|
|||||||
### Review the app structure
|
### Review the app structure
|
||||||
Verify that you have the following structure:
|
Verify that you have the following structure:
|
||||||
|
|
||||||
|
|
||||||
<aio-filetree>
|
<aio-filetree>
|
||||||
|
|
||||||
|
|
||||||
<aio-folder>
|
<aio-folder>
|
||||||
angular-tour-of-heroes
|
angular-tour-of-heroes
|
||||||
|
|
||||||
<aio-folder>
|
<aio-folder>
|
||||||
src
|
src
|
||||||
|
|
||||||
<aio-folder>
|
<aio-folder>
|
||||||
app
|
app
|
||||||
|
|
||||||
<aio-file>
|
<aio-file>
|
||||||
app.component.ts
|
app.component.ts
|
||||||
</aio-file>
|
</aio-file>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<aio-file>
|
<aio-file>
|
||||||
app.module.ts
|
app.module.ts
|
||||||
</aio-file>
|
</aio-file>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<aio-file>
|
<aio-file>
|
||||||
hero.ts
|
hero.ts
|
||||||
</aio-file>
|
</aio-file>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<aio-file>
|
<aio-file>
|
||||||
hero-detail.component.ts
|
hero-detail.component.ts
|
||||||
</aio-file>
|
</aio-file>
|
||||||
@ -328,26 +363,31 @@ Verify that you have the following structure:
|
|||||||
</aio-folder>
|
</aio-folder>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<aio-file>
|
<aio-file>
|
||||||
main.ts
|
main.ts
|
||||||
</aio-file>
|
</aio-file>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<aio-file>
|
<aio-file>
|
||||||
index.html
|
index.html
|
||||||
</aio-file>
|
</aio-file>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<aio-file>
|
<aio-file>
|
||||||
styles.css
|
styles.css
|
||||||
</aio-file>
|
</aio-file>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<aio-file>
|
<aio-file>
|
||||||
systemjs.config.js
|
systemjs.config.js
|
||||||
</aio-file>
|
</aio-file>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<aio-file>
|
<aio-file>
|
||||||
tsconfig.json
|
tsconfig.json
|
||||||
</aio-file>
|
</aio-file>
|
||||||
@ -356,11 +396,13 @@ Verify that you have the following structure:
|
|||||||
</aio-folder>
|
</aio-folder>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<aio-file>
|
<aio-file>
|
||||||
node_modules ...
|
node_modules ...
|
||||||
</aio-file>
|
</aio-file>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<aio-file>
|
<aio-file>
|
||||||
package.json
|
package.json
|
||||||
</aio-file>
|
</aio-file>
|
||||||
@ -374,23 +416,28 @@ Verify that you have the following structure:
|
|||||||
Here are the code files discussed in this page.
|
Here are the code files discussed in this page.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-tabs>
|
<code-tabs>
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="src/app/hero-detail.component.ts" path="toh-3/src/app/hero-detail.component.ts">
|
<code-pane title="src/app/hero-detail.component.ts" path="toh-3/src/app/hero-detail.component.ts">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="src/app/app.component.ts" path="toh-3/src/app/app.component.ts">
|
<code-pane title="src/app/app.component.ts" path="toh-3/src/app/app.component.ts">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="src/app/hero.ts" path="toh-3/src/app/hero.ts">
|
<code-pane title="src/app/hero.ts" path="toh-3/src/app/hero.ts">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="src/app/app.module.ts" path="toh-3/src/app/app.module.ts">
|
<code-pane title="src/app/app.module.ts" path="toh-3/src/app/app.module.ts">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
|
@ -22,29 +22,37 @@ When you're done with this page, the app should look like this <live-example></l
|
|||||||
Before continuing with the Tour of Heroes, verify that you have the following structure.
|
Before continuing with the Tour of Heroes, verify that you have the following structure.
|
||||||
If not, go back to the previous pages.
|
If not, go back to the previous pages.
|
||||||
|
|
||||||
|
|
||||||
<aio-filetree>
|
<aio-filetree>
|
||||||
|
|
||||||
|
|
||||||
<aio-folder>
|
<aio-folder>
|
||||||
angular-tour-of-heroes
|
angular-tour-of-heroes
|
||||||
|
|
||||||
<aio-folder>
|
<aio-folder>
|
||||||
src
|
src
|
||||||
|
|
||||||
<aio-folder>
|
<aio-folder>
|
||||||
app
|
app
|
||||||
|
|
||||||
<aio-file>
|
<aio-file>
|
||||||
app.component.ts
|
app.component.ts
|
||||||
</aio-file>
|
</aio-file>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<aio-file>
|
<aio-file>
|
||||||
app.module.ts
|
app.module.ts
|
||||||
</aio-file>
|
</aio-file>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<aio-file>
|
<aio-file>
|
||||||
hero.ts
|
hero.ts
|
||||||
</aio-file>
|
</aio-file>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<aio-file>
|
<aio-file>
|
||||||
hero-detail.component.ts
|
hero-detail.component.ts
|
||||||
</aio-file>
|
</aio-file>
|
||||||
@ -53,26 +61,31 @@ If not, go back to the previous pages.
|
|||||||
</aio-folder>
|
</aio-folder>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<aio-file>
|
<aio-file>
|
||||||
main.ts
|
main.ts
|
||||||
</aio-file>
|
</aio-file>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<aio-file>
|
<aio-file>
|
||||||
index.html
|
index.html
|
||||||
</aio-file>
|
</aio-file>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<aio-file>
|
<aio-file>
|
||||||
styles.css
|
styles.css
|
||||||
</aio-file>
|
</aio-file>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<aio-file>
|
<aio-file>
|
||||||
systemjs.config.js
|
systemjs.config.js
|
||||||
</aio-file>
|
</aio-file>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<aio-file>
|
<aio-file>
|
||||||
tsconfig.json
|
tsconfig.json
|
||||||
</aio-file>
|
</aio-file>
|
||||||
@ -81,11 +94,13 @@ If not, go back to the previous pages.
|
|||||||
</aio-folder>
|
</aio-folder>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<aio-file>
|
<aio-file>
|
||||||
node_modules ...
|
node_modules ...
|
||||||
</aio-file>
|
</aio-file>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<aio-file>
|
<aio-file>
|
||||||
package.json
|
package.json
|
||||||
</aio-file>
|
</aio-file>
|
||||||
@ -99,6 +114,7 @@ If not, go back to the previous pages.
|
|||||||
## Keep the app transpiling and running
|
## Keep the app transpiling and running
|
||||||
Enter the following command in the terminal window:
|
Enter the following command in the terminal window:
|
||||||
|
|
||||||
|
|
||||||
<code-example language="sh" class="code-shell">
|
<code-example language="sh" class="code-shell">
|
||||||
npm start
|
npm start
|
||||||
|
|
||||||
@ -135,6 +151,7 @@ For example, the filename for `SpecialSuperHeroService` is `special-super-hero.s
|
|||||||
Name the class `HeroService` and export it for others to import.
|
Name the class `HeroService` and export it for others to import.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="toh-4/src/app/hero.service.1.ts" region="empty-class" linenums="false">
|
<code-example path="toh-4/src/app/hero.service.1.ts" region="empty-class" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -158,6 +175,7 @@ consistency and future-proofing.
|
|||||||
Add a `getHeroes()` method stub.
|
Add a `getHeroes()` method stub.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="toh-4/src/app/hero.service.1.ts" region="getHeroes-stub" linenums="false">
|
<code-example path="toh-4/src/app/hero.service.1.ts" region="getHeroes-stub" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -173,6 +191,7 @@ Cut the `HEROES` array from `app.component.ts` and paste it to a new file in the
|
|||||||
Additionally, copy the `import {Hero} ...` statement because the heroes array uses the `Hero` class.
|
Additionally, copy the `import {Hero} ...` statement because the heroes array uses the `Hero` class.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="toh-4/src/app/mock-heroes.ts">
|
<code-example path="toh-4/src/app/mock-heroes.ts">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -182,6 +201,7 @@ The `HEROES` constant is exported so it can be imported elsewhere, such as the `
|
|||||||
In `app.component.ts`, where you cut the `HEROES` array,
|
In `app.component.ts`, where you cut the `HEROES` array,
|
||||||
add an uninitialized `heroes` property:
|
add an uninitialized `heroes` property:
|
||||||
|
|
||||||
|
|
||||||
<code-example path="toh-4/src/app/app.component.1.ts" region="heroes-prop" linenums="false">
|
<code-example path="toh-4/src/app/app.component.1.ts" region="heroes-prop" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -190,6 +210,7 @@ add an uninitialized `heroes` property:
|
|||||||
Back in the `HeroService`, import the mock `HEROES` and return it from the `getHeroes()` method.
|
Back in the `HeroService`, import the mock `HEROES` and return it from the `getHeroes()` method.
|
||||||
The `HeroService` looks like this:
|
The `HeroService` looks like this:
|
||||||
|
|
||||||
|
|
||||||
<code-example path="toh-4/src/app/hero.service.1.ts" region="full" linenums="false">
|
<code-example path="toh-4/src/app/hero.service.1.ts" region="full" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -199,6 +220,7 @@ You're ready to use the `HeroService` in other components, starting with `AppCom
|
|||||||
|
|
||||||
Import the `HeroService` so that you can reference it in the code.
|
Import the `HeroService` so that you can reference it in the code.
|
||||||
|
|
||||||
|
|
||||||
<code-example path="toh-4/src/app/app.component.ts" linenums="false" title="toh-4/ts/src/app/app.component.ts (hero-service-import)" region="hero-service-import">
|
<code-example path="toh-4/src/app/app.component.ts" linenums="false" title="toh-4/ts/src/app/app.component.ts (hero-service-import)" region="hero-service-import">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -208,6 +230,7 @@ How should the `AppComponent` acquire a runtime concrete `HeroService` instance?
|
|||||||
|
|
||||||
You could create a new instance of the `HeroService` with `new` like this:
|
You could create a new instance of the `HeroService` with `new` like this:
|
||||||
|
|
||||||
|
|
||||||
<code-example path="toh-4/src/app/app.component.1.ts" region="new-service" linenums="false">
|
<code-example path="toh-4/src/app/app.component.1.ts" region="new-service" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -234,6 +257,7 @@ Instead of using the *new* line, you'll add two lines.
|
|||||||
|
|
||||||
Add the constructor:
|
Add the constructor:
|
||||||
|
|
||||||
|
|
||||||
<code-example path="toh-4/src/app/app.component.1.ts" region="ctor">
|
<code-example path="toh-4/src/app/app.component.1.ts" region="ctor">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -250,6 +274,7 @@ Read more about dependency injection in the [Dependency Injection](guide/depende
|
|||||||
|
|
||||||
The *injector* doesn't know yet how to create a `HeroService`.
|
The *injector* doesn't know yet how to create a `HeroService`.
|
||||||
If you ran the code now, Angular would fail with this error:
|
If you ran the code now, Angular would fail with this error:
|
||||||
|
|
||||||
<code-example format="nocode">
|
<code-example format="nocode">
|
||||||
EXCEPTION: No provider for HeroService! (AppComponent -> HeroService)
|
EXCEPTION: No provider for HeroService! (AppComponent -> HeroService)
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -260,6 +285,7 @@ in the `@Component` call.
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="toh-4/src/app/app.component.1.ts" linenums="false" title="toh-4/ts/src/app/app.component.ts (providers)" region="providers">
|
<code-example path="toh-4/src/app/app.component.1.ts" linenums="false" title="toh-4/ts/src/app/app.component.ts (providers)" region="providers">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -273,6 +299,7 @@ The service is in a `heroService` private variable.
|
|||||||
|
|
||||||
You could call the service and get the data in one line.
|
You could call the service and get the data in one line.
|
||||||
|
|
||||||
|
|
||||||
<code-example path="toh-4/src/app/app.component.1.ts" region="get-heroes" linenums="false">
|
<code-example path="toh-4/src/app/app.component.1.ts" region="get-heroes" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -280,6 +307,7 @@ You could call the service and get the data in one line.
|
|||||||
You don't really need a dedicated method to wrap one line. Write it anyway:
|
You don't really need a dedicated method to wrap one line. Write it anyway:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="toh-4/src/app/app.component.1.ts" linenums="false" title="toh-4/ts/src/app/app.component.ts (getHeroes)" region="getHeroes">
|
<code-example path="toh-4/src/app/app.component.1.ts" linenums="false" title="toh-4/ts/src/app/app.component.ts (getHeroes)" region="getHeroes">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -306,11 +334,13 @@ Read more about lifecycle hooks in the [Lifecycle Hooks](guide/lifecycle-hooks)
|
|||||||
|
|
||||||
Here's the essential outline for the `OnInit` interface (don't copy this into your code):
|
Here's the essential outline for the `OnInit` interface (don't copy this into your code):
|
||||||
|
|
||||||
|
|
||||||
<code-example path="toh-4/src/app/app.component.1.ts" region="on-init" linenums="false">
|
<code-example path="toh-4/src/app/app.component.1.ts" region="on-init" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
|
|
||||||
Add the implementation for the `OnInit` interface to your export statement:
|
Add the implementation for the `OnInit` interface to your export statement:
|
||||||
|
|
||||||
<code-example format="nocode">
|
<code-example format="nocode">
|
||||||
export class AppComponent implements OnInit {}
|
export class AppComponent implements OnInit {}
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -318,6 +348,7 @@ Add the implementation for the `OnInit` interface to your export statement:
|
|||||||
Write an `ngOnInit` method with the initialization logic inside. Angular will call it
|
Write an `ngOnInit` method with the initialization logic inside. Angular will call it
|
||||||
at the right time. In this case, initialize by calling `getHeroes()`.
|
at the right time. In this case, initialize by calling `getHeroes()`.
|
||||||
|
|
||||||
|
|
||||||
<code-example path="toh-4/src/app/app.component.1.ts" linenums="false" title="toh-4/ts/src/app/app.component.ts (ng-on-init)" region="ng-on-init">
|
<code-example path="toh-4/src/app/app.component.1.ts" linenums="false" title="toh-4/ts/src/app/app.component.ts (ng-on-init)" region="ng-on-init">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -328,6 +359,7 @@ when you click on a hero name.
|
|||||||
The `HeroService` returns a list of mock heroes immediately;
|
The `HeroService` returns a list of mock heroes immediately;
|
||||||
its `getHeroes()` signature is synchronous.
|
its `getHeroes()` signature is synchronous.
|
||||||
|
|
||||||
|
|
||||||
<code-example path="toh-4/src/app/app.component.1.ts" region="get-heroes" linenums="false">
|
<code-example path="toh-4/src/app/app.component.1.ts" region="get-heroes" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -356,6 +388,7 @@ This is a simplified explanation. Read more about ES2015 Promises in the
|
|||||||
|
|
||||||
Update the `HeroService` with this !{_Promise}-returning `getHeroes()` method:
|
Update the `HeroService` with this !{_Promise}-returning `getHeroes()` method:
|
||||||
|
|
||||||
|
|
||||||
<code-example path="toh-4/src/app/hero.service.ts" region="get-heroes" linenums="false">
|
<code-example path="toh-4/src/app/hero.service.ts" region="get-heroes" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -367,6 +400,7 @@ by returning an *immediately resolved !{_Promise}* with the mock heroes as the r
|
|||||||
|
|
||||||
As a result of the change to `HeroService`, `this.heroes` is now set to a !{_Promise} rather than an array of heroes.
|
As a result of the change to `HeroService`, `this.heroes` is now set to a !{_Promise} rather than an array of heroes.
|
||||||
|
|
||||||
|
|
||||||
<code-example path="toh-4/src/app/app.component.1.ts" region="getHeroes" linenums="false">
|
<code-example path="toh-4/src/app/app.component.1.ts" region="getHeroes" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -376,6 +410,7 @@ When the !{_Promise} resolves successfully, you'll have heroes to display.
|
|||||||
|
|
||||||
Pass the callback function as an argument to the !{_Promise}'s `then()` method:
|
Pass the callback function as an argument to the !{_Promise}'s `then()` method:
|
||||||
|
|
||||||
|
|
||||||
<code-example path="toh-4/src/app/app.component.ts" region="get-heroes" linenums="false">
|
<code-example path="toh-4/src/app/app.component.ts" region="get-heroes" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -404,39 +439,49 @@ At the end of this page, [Appendix: take it slow](tutorial/toh-pt4#slow) describ
|
|||||||
## Review the app structure
|
## Review the app structure
|
||||||
Verify that you have the following structure after all of your refactoring:
|
Verify that you have the following structure after all of your refactoring:
|
||||||
|
|
||||||
|
|
||||||
<aio-filetree>
|
<aio-filetree>
|
||||||
|
|
||||||
|
|
||||||
<aio-folder>
|
<aio-folder>
|
||||||
angular-tour-of-heroes
|
angular-tour-of-heroes
|
||||||
|
|
||||||
<aio-folder>
|
<aio-folder>
|
||||||
src
|
src
|
||||||
|
|
||||||
<aio-folder>
|
<aio-folder>
|
||||||
app
|
app
|
||||||
|
|
||||||
<aio-file>
|
<aio-file>
|
||||||
app.component.ts
|
app.component.ts
|
||||||
</aio-file>
|
</aio-file>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<aio-file>
|
<aio-file>
|
||||||
app.module.ts
|
app.module.ts
|
||||||
</aio-file>
|
</aio-file>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<aio-file>
|
<aio-file>
|
||||||
hero.ts
|
hero.ts
|
||||||
</aio-file>
|
</aio-file>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<aio-file>
|
<aio-file>
|
||||||
hero-detail.component.ts
|
hero-detail.component.ts
|
||||||
</aio-file>
|
</aio-file>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<aio-file>
|
<aio-file>
|
||||||
hero.service.ts
|
hero.service.ts
|
||||||
</aio-file>
|
</aio-file>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<aio-file>
|
<aio-file>
|
||||||
mock-heroes.ts
|
mock-heroes.ts
|
||||||
</aio-file>
|
</aio-file>
|
||||||
@ -445,26 +490,31 @@ Verify that you have the following structure after all of your refactoring:
|
|||||||
</aio-folder>
|
</aio-folder>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<aio-file>
|
<aio-file>
|
||||||
main.ts
|
main.ts
|
||||||
</aio-file>
|
</aio-file>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<aio-file>
|
<aio-file>
|
||||||
index.html
|
index.html
|
||||||
</aio-file>
|
</aio-file>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<aio-file>
|
<aio-file>
|
||||||
styles.css
|
styles.css
|
||||||
</aio-file>
|
</aio-file>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<aio-file>
|
<aio-file>
|
||||||
systemjs.config.js
|
systemjs.config.js
|
||||||
</aio-file>
|
</aio-file>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<aio-file>
|
<aio-file>
|
||||||
tsconfig.json
|
tsconfig.json
|
||||||
</aio-file>
|
</aio-file>
|
||||||
@ -473,11 +523,13 @@ Verify that you have the following structure after all of your refactoring:
|
|||||||
</aio-folder>
|
</aio-folder>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<aio-file>
|
<aio-file>
|
||||||
node_modules ...
|
node_modules ...
|
||||||
</aio-file>
|
</aio-file>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<aio-file>
|
<aio-file>
|
||||||
package.json
|
package.json
|
||||||
</aio-file>
|
</aio-file>
|
||||||
@ -491,18 +543,22 @@ Verify that you have the following structure after all of your refactoring:
|
|||||||
Here are the code files discussed in this page.
|
Here are the code files discussed in this page.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-tabs>
|
<code-tabs>
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="src/app/hero.service.ts" path="toh-4/src/app/hero.service.ts">
|
<code-pane title="src/app/hero.service.ts" path="toh-4/src/app/hero.service.ts">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="src/app/app.component.ts" path="toh-4/src/app/app.component.ts">
|
<code-pane title="src/app/app.component.ts" path="toh-4/src/app/app.component.ts">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="src/app/mock-heroes.ts" path="toh-4/src/app/mock-heroes.ts">
|
<code-pane title="src/app/mock-heroes.ts" path="toh-4/src/app/mock-heroes.ts">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
@ -532,6 +588,7 @@ Read about the Angular component router and navigation among the views in the [n
|
|||||||
To simulate a slow connection,
|
To simulate a slow connection,
|
||||||
import the `Hero` symbol and add the following `getHeroesSlowly()` method to the `HeroService`.
|
import the `Hero` symbol and add the following `getHeroesSlowly()` method to the `HeroService`.
|
||||||
|
|
||||||
|
|
||||||
<code-example path="toh-4/src/app/hero.service.ts" region="get-heroes-slowly" linenums="false">
|
<code-example path="toh-4/src/app/hero.service.ts" region="get-heroes-slowly" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
|
@ -15,6 +15,7 @@ There are new requirements for the Tour of Heroes app:
|
|||||||
|
|
||||||
When you’re done, users will be able to navigate the app like this:
|
When you’re done, users will be able to navigate the app like this:
|
||||||
|
|
||||||
|
|
||||||
<figure class='image-display'>
|
<figure class='image-display'>
|
||||||
<img src='assets/images/devguide/toh/nav-diagram.png' alt="View navigations"> </img>
|
<img src='assets/images/devguide/toh/nav-diagram.png' alt="View navigations"> </img>
|
||||||
</figure>
|
</figure>
|
||||||
@ -35,39 +36,49 @@ When you're done with this page, the app should look like this <live-example></l
|
|||||||
Before continuing with the Tour of Heroes, verify that you have the following structure.
|
Before continuing with the Tour of Heroes, verify that you have the following structure.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<aio-filetree>
|
<aio-filetree>
|
||||||
|
|
||||||
|
|
||||||
<aio-folder>
|
<aio-folder>
|
||||||
angular-tour-of-heroes
|
angular-tour-of-heroes
|
||||||
|
|
||||||
<aio-folder>
|
<aio-folder>
|
||||||
src
|
src
|
||||||
|
|
||||||
<aio-folder>
|
<aio-folder>
|
||||||
app
|
app
|
||||||
|
|
||||||
<aio-file>
|
<aio-file>
|
||||||
app.component.ts
|
app.component.ts
|
||||||
</aio-file>
|
</aio-file>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<aio-file>
|
<aio-file>
|
||||||
app.module.ts
|
app.module.ts
|
||||||
</aio-file>
|
</aio-file>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<aio-file>
|
<aio-file>
|
||||||
hero.service.ts
|
hero.service.ts
|
||||||
</aio-file>
|
</aio-file>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<aio-file>
|
<aio-file>
|
||||||
hero.ts
|
hero.ts
|
||||||
</aio-file>
|
</aio-file>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<aio-file>
|
<aio-file>
|
||||||
hero-detail.component.ts
|
hero-detail.component.ts
|
||||||
</aio-file>
|
</aio-file>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<aio-file>
|
<aio-file>
|
||||||
mock-heroes.ts
|
mock-heroes.ts
|
||||||
</aio-file>
|
</aio-file>
|
||||||
@ -76,26 +87,31 @@ Before continuing with the Tour of Heroes, verify that you have the following st
|
|||||||
</aio-folder>
|
</aio-folder>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<aio-file>
|
<aio-file>
|
||||||
main.ts
|
main.ts
|
||||||
</aio-file>
|
</aio-file>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<aio-file>
|
<aio-file>
|
||||||
index.html
|
index.html
|
||||||
</aio-file>
|
</aio-file>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<aio-file>
|
<aio-file>
|
||||||
styles.css
|
styles.css
|
||||||
</aio-file>
|
</aio-file>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<aio-file>
|
<aio-file>
|
||||||
systemjs.config.js
|
systemjs.config.js
|
||||||
</aio-file>
|
</aio-file>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<aio-file>
|
<aio-file>
|
||||||
tsconfig.json
|
tsconfig.json
|
||||||
</aio-file>
|
</aio-file>
|
||||||
@ -104,11 +120,13 @@ Before continuing with the Tour of Heroes, verify that you have the following st
|
|||||||
</aio-folder>
|
</aio-folder>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<aio-file>
|
<aio-file>
|
||||||
node_modules ...
|
node_modules ...
|
||||||
</aio-file>
|
</aio-file>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<aio-file>
|
<aio-file>
|
||||||
package.json
|
package.json
|
||||||
</aio-file>
|
</aio-file>
|
||||||
@ -123,6 +141,7 @@ Before continuing with the Tour of Heroes, verify that you have the following st
|
|||||||
## Keep the app transpiling and running
|
## Keep the app transpiling and running
|
||||||
Enter the following command in the terminal window:
|
Enter the following command in the terminal window:
|
||||||
|
|
||||||
|
|
||||||
<code-example language="sh" class="code-shell">
|
<code-example language="sh" class="code-shell">
|
||||||
npm start
|
npm start
|
||||||
|
|
||||||
@ -130,7 +149,6 @@ Enter the following command in the terminal window:
|
|||||||
|
|
||||||
This command runs the TypeScript compiler in "watch mode", recompiling automatically when the code changes.
|
This command runs the TypeScript compiler in "watch mode", recompiling automatically when the code changes.
|
||||||
The command simultaneously launches the app in a browser and refreshes the browser when the code changes.
|
The command simultaneously launches the app in a browser and refreshes the browser when the code changes.
|
||||||
|
|
||||||
You can keep building the Tour of Heroes without pausing to recompile or refresh the browser.
|
You can keep building the Tour of Heroes without pausing to recompile or refresh the browser.
|
||||||
|
|
||||||
## Action plan
|
## Action plan
|
||||||
@ -165,13 +183,14 @@ move the display of *Heroes* out of `AppComponent` and into its own `HeroesCompo
|
|||||||
### *HeroesComponent*
|
### *HeroesComponent*
|
||||||
|
|
||||||
`AppComponent` is already dedicated to *Heroes*.
|
`AppComponent` is already dedicated to *Heroes*.
|
||||||
Instead of moving the code out of `AppComponent`, rename it `HeroesComponent`
|
Instead of moving the code out of `AppComponent`, rename it to `HeroesComponent`
|
||||||
and create a separate `AppComponent` shell.
|
and create a separate `AppComponent` shell.
|
||||||
|
|
||||||
Do the following:
|
Do the following:
|
||||||
* Rename the <span ngio-ex>app.component.ts</span> file as <span ngio-ex>heroes.component.ts</span>.
|
* Rename the <span ngio-ex>app.component.ts</span> file to <span ngio-ex>heroes.component.ts</span>.
|
||||||
* Rename the `AppComponent` class as `HeroesComponent` (rename locally, _only_ in this file).
|
* Rename the `AppComponent` class to `HeroesComponent` (rename locally, _only_ in this file).
|
||||||
* Rename the selector `my-app` as `my-heroes`.
|
* Rename the selector `my-app` to `my-heroes`.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="toh-pt5/src/app/heroes.component.ts" linenums="false" title="src/app/heroes.component.ts (showing renamings only)" region="renaming">
|
<code-example path="toh-pt5/src/app/heroes.component.ts" linenums="false" title="src/app/heroes.component.ts (showing renamings only)" region="renaming">
|
||||||
@ -181,7 +200,7 @@ Do the following:
|
|||||||
### Create *AppComponent*
|
### Create *AppComponent*
|
||||||
|
|
||||||
The new `AppComponent` is the application shell.
|
The new `AppComponent` is the application shell.
|
||||||
It will have some navigation links at the top and a display area below for the pages users navigate to.
|
It will have some navigation links at the top and a display area below.
|
||||||
|
|
||||||
Perform these steps:
|
Perform these steps:
|
||||||
|
|
||||||
@ -201,13 +220,16 @@ The first draft looks like this:
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-tabs>
|
<code-tabs>
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="src/app/app.component.ts (v1)" path="toh-5/src/app/app.component.1.ts">
|
<code-pane title="src/app/app.component.ts (v1)" path="toh-5/src/app/app.component.1.ts">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="src/app/app.module.ts (v1)" path="toh-5/src/app/app.module.1.ts">
|
<code-pane title="src/app/app.module.ts (v1)" path="toh-5/src/app/app.module.1.ts">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
@ -216,9 +238,9 @@ The first draft looks like this:
|
|||||||
</code-tabs>
|
</code-tabs>
|
||||||
|
|
||||||
The app still runs and displays heroes.
|
The app still runs and displays heroes.
|
||||||
## Adding routing
|
## Add routing
|
||||||
|
|
||||||
Instead of displaying automatically, heroes should display after users click a button.
|
Instead of displaying automatically, heroes should display after users click a button.
|
||||||
In other words, users should be able to navigate to the list of heroes.
|
In other words, users should be able to navigate to the list of heroes.
|
||||||
|
|
||||||
Use the Angular router to enable navigation.
|
Use the Angular router to enable navigation.
|
||||||
@ -234,6 +256,7 @@ Open `index.html` and ensure there is a `<base href="...">` element
|
|||||||
at the top of the `<head>` section.
|
at the top of the `<head>` section.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="toh-pt5/src/index.html" linenums="false" title="src/index.html (base-href)" region="base-href">
|
<code-example path="toh-pt5/src/index.html" linenums="false" title="src/index.html (base-href)" region="base-href">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -243,6 +266,7 @@ at the top of the `<head>` section.
|
|||||||
~~~ {.callout.is-important}
|
~~~ {.callout.is-important}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<header>
|
<header>
|
||||||
base href is essential
|
base href is essential
|
||||||
</header>
|
</header>
|
||||||
@ -267,6 +291,7 @@ pastes a URL into the browser address bar.
|
|||||||
Define the first route as a route to the heroes component.
|
Define the first route as a route to the heroes component.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="toh-pt5/src/app/" linenums="false" title="src/app/ (heroes)" region="heroes">
|
<code-example path="toh-pt5/src/app/" linenums="false" title="src/app/ (heroes)" region="heroes">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -306,6 +331,7 @@ Instead, add an anchor tag to the template that, when clicked, triggers navigati
|
|||||||
The revised template looks like this:
|
The revised template looks like this:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="toh-pt5/src/app/app.component.1.ts" linenums="false" title="src/app/app.component.ts (template-v2)" region="template-v2">
|
<code-example path="toh-pt5/src/app/app.component.1.ts" linenums="false" title="src/app/app.component.ts (template-v2)" region="template-v2">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -345,6 +371,7 @@ and the list of heroes displays.
|
|||||||
`AppComponent` now looks like this:
|
`AppComponent` now looks like this:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="toh-pt5/src/app/app.component.1.ts" region="v2">
|
<code-example path="toh-pt5/src/app/app.component.1.ts" region="v2">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -358,6 +385,7 @@ Routing only makes sense when multiple views exist.
|
|||||||
To add another view, create a placeholder `DashboardComponent`, which users can navigate to and from.
|
To add another view, create a placeholder `DashboardComponent`, which users can navigate to and from.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="toh-pt5/src/app/dashboard.component.1.ts" linenums="false" title="src/app/dashboard.component.ts (v1)" region="v1">
|
<code-example path="toh-pt5/src/app/dashboard.component.1.ts" linenums="false" title="src/app/dashboard.component.ts (v1)" region="v1">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -371,20 +399,22 @@ import the dashboard component and
|
|||||||
add the following route definition to the `!{_RoutesVsAtRouteConfig}` !{_array} of definitions.
|
add the following route definition to the `!{_RoutesVsAtRouteConfig}` !{_array} of definitions.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="toh-pt5/_file + ' (Dashboard route)'" linenums="false" title="_file + ' (Dashboard route)' (dashboard)" region="dashboard">
|
<code-example path="toh-pt5/_file + ' (Dashboard route)'" linenums="false" title="_file + ' (Dashboard route)' (dashboard)" region="dashboard">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
|
|
||||||
### Add a redirect route
|
### Add a !{_redirect} route
|
||||||
|
|
||||||
|
Currently, the browser launches with `/` in the address bar.
|
||||||
When the app starts, it should show the dashboard and
|
When the app starts, it should show the dashboard and
|
||||||
display a `/dashboard` URL in the browser address bar.
|
display a `/dashboard` URL in the browser address bar.
|
||||||
Currently, the browser launches with `/` in the address bar.
|
|
||||||
|
|
||||||
To make this happen, use a redirect route. Add the following
|
To make this happen, use a redirect route. Add the following
|
||||||
to the array of route definitions:
|
to the array of route definitions:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="toh-pt5/src/app/app.module.3.ts" linenums="false" title="src/app/app.module.ts (redirect)" region="redirect">
|
<code-example path="toh-pt5/src/app/app.module.3.ts" linenums="false" title="src/app/app.module.ts (redirect)" region="redirect">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -404,6 +434,7 @@ of the [Routing & Navigation](guide/router) page.
|
|||||||
Add a dashboard navigation link to the template, just above the *Heroes* link.
|
Add a dashboard navigation link to the template, just above the *Heroes* link.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="toh-pt5/src/app/app.component" linenums="false" title="src/app/app.component (template-v3)" region="template-v3">
|
<code-example path="toh-pt5/src/app/app.component" linenums="false" title="src/app/app.component (template-v3)" region="template-v3">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -428,6 +459,7 @@ Replace the `template` metadata with a `templateUrl` property that points to a n
|
|||||||
template file.
|
template file.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="toh-pt5/src/app/dashboard.component.ts" linenums="false" title="src/app/dashboard.component.ts (metadata)" region="metadata">
|
<code-example path="toh-pt5/src/app/dashboard.component.ts" linenums="false" title="src/app/dashboard.component.ts (metadata)" region="metadata">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -436,6 +468,7 @@ template file.
|
|||||||
Create that file with this content:
|
Create that file with this content:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="toh-pt5/src/app/dashboard.component.1.html">
|
<code-example path="toh-pt5/src/app/dashboard.component.1.html">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -457,6 +490,7 @@ Angular injects `HeroService` and you can use it in the `DashboardComponent`.
|
|||||||
In <span ngio-ex>dashboard.component.ts</span>, add the following `import` statements.
|
In <span ngio-ex>dashboard.component.ts</span>, add the following `import` statements.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="toh-pt5/src/app/dashboard.component.ts" linenums="false" title="src/app/dashboard.component.ts (imports)" region="imports">
|
<code-example path="toh-pt5/src/app/dashboard.component.ts" linenums="false" title="src/app/dashboard.component.ts (imports)" region="imports">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -464,6 +498,7 @@ In <span ngio-ex>dashboard.component.ts</span>, add the following `import` state
|
|||||||
Now create the `DashboardComponent` class like this:
|
Now create the `DashboardComponent` class like this:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="toh-pt5/src/app/dashboard.component.ts" linenums="false" title="src/app/dashboard.component.ts (class)" region="class">
|
<code-example path="toh-pt5/src/app/dashboard.component.ts" linenums="false" title="src/app/dashboard.component.ts (class)" region="class">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -472,9 +507,9 @@ This kind of logic is also used in the `HeroesComponent`:
|
|||||||
|
|
||||||
* Define a `heroes` !{_array} property.
|
* Define a `heroes` !{_array} property.
|
||||||
* Inject the `HeroService` in the constructor and hold it in a private `!{_priv}heroService` field.
|
* Inject the `HeroService` in the constructor and hold it in a private `!{_priv}heroService` field.
|
||||||
* Call the service to get heroes inside the Angular `ngOnInit` lifecycle hook.
|
* Call the service to get heroes inside the Angular `ngOnInit()` lifecycle hook.
|
||||||
|
|
||||||
In this dashboard you specify four heroes (2nd, 3rd, 4th, and 5th)<span if-docs="ts"> with the `Array.slice` method</span>.
|
In this dashboard you specify four heroes (2nd, 3rd, 4th, and 5th)<span if-docs="ts"> with the `Array.slice()` method</span>.
|
||||||
|
|
||||||
Refresh the browser to see four hero names in the new dashboard.
|
Refresh the browser to see four hero names in the new dashboard.
|
||||||
|
|
||||||
@ -497,6 +532,7 @@ You didn't have to tell the `HeroesComponent` or the `DashboardComponent` anythi
|
|||||||
Currently, the parent `HeroesComponent` sets the component's `hero` property to a
|
Currently, the parent `HeroesComponent` sets the component's `hero` property to a
|
||||||
hero object with a binding like this:
|
hero object with a binding like this:
|
||||||
|
|
||||||
|
|
||||||
<code-example language="html">
|
<code-example language="html">
|
||||||
<hero-detail [hero]="selectedHero"></hero-detail>
|
<hero-detail [hero]="selectedHero"></hero-detail>
|
||||||
|
|
||||||
@ -509,6 +545,7 @@ But this binding won't work in any of the routing scenarios.
|
|||||||
You can add the hero's `id` to the URL. When routing to the hero whose `id` is 11,
|
You can add the hero's `id` to the URL. When routing to the hero whose `id` is 11,
|
||||||
you could expect to see a URL such as this:
|
you could expect to see a URL such as this:
|
||||||
|
|
||||||
|
|
||||||
<code-example format="nocode">
|
<code-example format="nocode">
|
||||||
/detail/11
|
/detail/11
|
||||||
|
|
||||||
@ -522,6 +559,7 @@ You need to represent the variable part of the route with a *parameter* (or *tok
|
|||||||
Use the following *route definition*.
|
Use the following *route definition*.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="toh-pt5/_file + ' (hero detail)'" linenums="false" title="_file + ' (hero detail)' (hero-detail)" region="hero-detail">
|
<code-example path="toh-pt5/_file + ' (hero detail)'" linenums="false" title="_file + ' (hero detail)' (hero-detail)" region="hero-detail">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -542,6 +580,7 @@ is revised and ready to be navigated to.
|
|||||||
Here's what the `HeroDetailComponent` looks like now:
|
Here's what the `HeroDetailComponent` looks like now:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="toh-4/src/app/hero-detail.component.ts">
|
<code-example path="toh-4/src/app/hero-detail.component.ts">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -555,6 +594,7 @@ in the `ActivatedRoute` service and use the `HeroService` to fetch the hero with
|
|||||||
Add the following imports:
|
Add the following imports:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="toh-pt5/src/app/hero-detail.component" linenums="false" title="src/app/hero-detail.component (added-imports)" region="added-imports">
|
<code-example path="toh-pt5/src/app/hero-detail.component" linenums="false" title="src/app/hero-detail.component (added-imports)" region="added-imports">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -563,6 +603,7 @@ Inject the `!{_ActivatedRoute}`, `HeroService`, and `Location` services
|
|||||||
into the constructor, saving their values in private fields:
|
into the constructor, saving their values in private fields:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="toh-pt5/src/app/hero-detail.component.ts" linenums="false" title="src/app/hero-detail.component.ts (constructor)" region="ctor">
|
<code-example path="toh-pt5/src/app/hero-detail.component.ts" linenums="false" title="src/app/hero-detail.component.ts (constructor)" region="ctor">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -570,16 +611,18 @@ into the constructor, saving their values in private fields:
|
|||||||
Tell the class to implement the `OnInit` interface.
|
Tell the class to implement the `OnInit` interface.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="toh-pt5/src/app/hero-detail.component.ts" linenums="false" title="src/app/hero-detail.component.ts (implement)" region="implement">
|
<code-example path="toh-pt5/src/app/hero-detail.component.ts" linenums="false" title="src/app/hero-detail.component.ts (implement)" region="implement">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
|
|
||||||
|
|
||||||
Inside the `ngOnInit` lifecycle hook, use the `params` Observable to
|
Inside the `ngOnInit()` lifecycle hook, use the `params` Observable to
|
||||||
extract the `id` parameter value from the `ActivatedRoute` service
|
extract the `id` parameter value from the `ActivatedRoute` service
|
||||||
and use the `HeroService` to fetch the hero with that `id`.
|
and use the `HeroService` to fetch the hero with that `id`.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="toh-pt5/src/app/hero-detail.component.ts" linenums="false" title="src/app/hero-detail.component.ts (ngOnInit)" region="ngOnInit">
|
<code-example path="toh-pt5/src/app/hero-detail.component.ts" linenums="false" title="src/app/hero-detail.component.ts (ngOnInit)" region="ngOnInit">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -592,10 +635,11 @@ If a user re-navigates to this component while a `getHero` request is still proc
|
|||||||
`switchMap` cancels the old request and then calls `HeroService.getHero()` again.
|
`switchMap` cancels the old request and then calls `HeroService.getHero()` again.
|
||||||
The hero `id` is a number. Route parameters are always strings.
|
The hero `id` is a number. Route parameters are always strings.
|
||||||
So the route parameter value is converted to a number with the !{_str2int}.
|
So the route parameter value is converted to a number with the !{_str2int}.
|
||||||
### Add *HeroService.getHero*
|
### Add *HeroService.getHero()*
|
||||||
|
|
||||||
In the previous code snippet, `HeroService` doesn't have a `getHero()` method. To fix this issue,
|
In the previous code snippet, `HeroService` doesn't have a `getHero()` method. To fix this issue,
|
||||||
open `HeroService` and add a `getHero()` method that filters the heroes list from `getHeroes` by `id`.
|
open `HeroService` and add a `getHero()` method that filters the heroes list from `getHeroes()` by `id`.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="toh-pt5/src/app/hero.service.ts" linenums="false" title="src/app/hero.service.ts (getHero)" region="getHero">
|
<code-example path="toh-pt5/src/app/hero.service.ts" linenums="false" title="src/app/hero.service.ts (getHero)" region="getHero">
|
||||||
@ -611,6 +655,7 @@ Now add a third option, a `goBack()` method that navigates backward one step in
|
|||||||
using the `Location` service you injected previously.
|
using the `Location` service you injected previously.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="toh-pt5/src/app/hero-detail.component.ts" linenums="false" title="src/app/hero-detail.component.ts (goBack)" region="goBack">
|
<code-example path="toh-pt5/src/app/hero-detail.component.ts" linenums="false" title="src/app/hero-detail.component.ts (goBack)" region="goBack">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -621,7 +666,7 @@ using the `Location` service you injected previously.
|
|||||||
|
|
||||||
Going back too far could take users out of the app.
|
Going back too far could take users out of the app.
|
||||||
In a real app, you can prevent this issue with the !{_CanDeactivateGuard}.
|
In a real app, you can prevent this issue with the !{_CanDeactivateGuard}.
|
||||||
Read more on the [CanDeactivate](api/!{_CanDeactivateGuardUri}) page.
|
Read more on the [CanDeactivate](api/router/index/CanDeactivate-interface) page.
|
||||||
|
|
||||||
|
|
||||||
~~~
|
~~~
|
||||||
@ -629,6 +674,7 @@ Read more on the [CanDeactivate](api/!{_CanDeactivateGuardUri}) page.
|
|||||||
You'll wire this method with an event binding to a *Back* button that you'll add to the component template.
|
You'll wire this method with an event binding to a *Back* button that you'll add to the component template.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="toh-pt5/src/app/hero-detail.component.html" linenums="false" title="src/app/hero-detail.component.html (back-button)" region="back-button">
|
<code-example path="toh-pt5/src/app/hero-detail.component.html" linenums="false" title="src/app/hero-detail.component.html (back-button)" region="back-button">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -637,6 +683,7 @@ Migrate the template to its own file
|
|||||||
called <span ngio-ex>hero-detail.component.html</span>:
|
called <span ngio-ex>hero-detail.component.html</span>:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="toh-pt5/src/app/hero-detail.component.html">
|
<code-example path="toh-pt5/src/app/hero-detail.component.html">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -645,6 +692,7 @@ Update the component metadata with a `templateUrl` pointing to the template file
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="toh-pt5/src/app/hero-detail.component.ts" linenums="false" title="src/app/hero-detail.component.ts (metadata)" region="metadata">
|
<code-example path="toh-pt5/src/app/hero-detail.component.ts" linenums="false" title="src/app/hero-detail.component.ts (metadata)" region="metadata">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -663,6 +711,7 @@ To achieve this effect, reopen `dashboard.component.html` and replace the repeat
|
|||||||
with `<a>` tags. Change the opening `<a>` tag to the following:
|
with `<a>` tags. Change the opening `<a>` tag to the following:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="toh-pt5/src/app/dashboard.component.html" region="click">
|
<code-example path="toh-pt5/src/app/dashboard.component.html" region="click">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -681,29 +730,12 @@ token in the parameterized hero detail route definition that you added to
|
|||||||
`!{_appRoutingTsVsAppComp}` earlier:
|
`!{_appRoutingTsVsAppComp}` earlier:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="toh-pt5/_file + ' (hero detail)'" linenums="false" title="_file + ' (hero detail)' (hero-detail)" region="hero-detail">
|
<code-example path="toh-pt5/_file + ' (hero detail)'" linenums="false" title="_file + ' (hero detail)' (hero-detail)" region="hero-detail">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
|
|
||||||
Refresh the browser and select a hero from the dashboard; the app navigates to that hero’s details.
|
Refresh the browser and select a hero from the dashboard; the app navigates to that hero’s details.
|
||||||
Here is the revised `AppModule`, compared to its pre-refactor state:
|
|
||||||
|
|
||||||
|
|
||||||
<code-tabs>
|
|
||||||
|
|
||||||
<code-pane title="src/app/app.module.ts (after)" path="toh-5/src/app/app.module.ts">
|
|
||||||
|
|
||||||
</code-pane>
|
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="src/app/app.module.ts (before)" path="toh-5/src/app/app.module.3.ts">
|
|
||||||
|
|
||||||
</code-pane>
|
|
||||||
|
|
||||||
|
|
||||||
</code-tabs>
|
|
||||||
|
|
||||||
The revised and simplified `AppModule` is focused on identifying the key pieces of the app.
|
|
||||||
|
|
||||||
## Select a hero in the *HeroesComponent*
|
## Select a hero in the *HeroesComponent*
|
||||||
|
|
||||||
@ -712,6 +744,7 @@ the current template exhibits a "master/detail" style with the list of heroes
|
|||||||
at the top and details of the selected hero below.
|
at the top and details of the selected hero below.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="toh-4/src/app/app.component.ts" region="template" linenums="false">
|
<code-example path="toh-4/src/app/app.component.ts" region="template" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -731,12 +764,14 @@ Instead, they'll see a mini detail on *this* page and have to click a button to
|
|||||||
Add the following HTML fragment at the bottom of the template where the `<hero-detail>` used to be:
|
Add the following HTML fragment at the bottom of the template where the `<hero-detail>` used to be:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="toh-pt5/src/app/heroes.component.html" linenums="false" title="src/app/heroes.component.html (mini-detail)" region="mini-detail">
|
<code-example path="toh-pt5/src/app/heroes.component.html" linenums="false" title="src/app/heroes.component.html (mini-detail)" region="mini-detail">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
|
|
||||||
After clicking a hero, users should see something like this below the hero list:
|
After clicking a hero, users should see something like this below the hero list:
|
||||||
|
|
||||||
|
|
||||||
<figure class='image-display'>
|
<figure class='image-display'>
|
||||||
<img src='assets/images/devguide/toh/mini-hero-detail.png' alt="Mini Hero Detail" height="70"> </img>
|
<img src='assets/images/devguide/toh/mini-hero-detail.png' alt="Mini Hero Detail" height="70"> </img>
|
||||||
</figure>
|
</figure>
|
||||||
@ -747,6 +782,7 @@ The hero's name is displayed in capital letters because of the `uppercase` pipe
|
|||||||
that's included in the interpolation binding, right after the pipe operator ( | ).
|
that's included in the interpolation binding, right after the pipe operator ( | ).
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="toh-pt5/src/app/heroes.component.html" linenums="false" title="src/app/heroes.component.html (pipe)" region="pipe">
|
<code-example path="toh-pt5/src/app/heroes.component.html" linenums="false" title="src/app/heroes.component.html (pipe)" region="pipe">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -781,13 +817,16 @@ styles contents into a new <span ngio-ex>heroes.component.css</span> file.
|
|||||||
The two new files should look like this:
|
The two new files should look like this:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-tabs>
|
<code-tabs>
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="src/app/heroes.component.html" path="toh-5/src/app/heroes.component.html">
|
<code-pane title="src/app/heroes.component.html" path="toh-5/src/app/heroes.component.html">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="src/app/heroes.component.css" path="toh-5/src/app/heroes.component.css">
|
<code-pane title="src/app/heroes.component.css" path="toh-5/src/app/heroes.component.css">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
@ -802,6 +841,7 @@ Set their properties to refer to the new files.
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="toh-pt5/src/app/heroes.component.ts" linenums="false" title="src/app/heroes.component.ts (revised metadata)" region="metadata">
|
<code-example path="toh-pt5/src/app/heroes.component.ts" linenums="false" title="src/app/heroes.component.ts (revised metadata)" region="metadata">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -826,7 +866,8 @@ This approach requires the following changes to the component class:
|
|||||||
|
|
||||||
1. Import the `router` from the Angular router library.
|
1. Import the `router` from the Angular router library.
|
||||||
1. Inject the `router` in the constructor, along with the `HeroService`.
|
1. Inject the `router` in the constructor, along with the `HeroService`.
|
||||||
1. Implement `gotoDetail()` by calling the `router.navigate()` method.
|
1. Implement `gotoDetail()` by calling the router `navigate()` method.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="toh-pt5/src/app/heroes.component.ts" linenums="false" title="src/app/heroes.component.ts (gotoDetail)" region="gotoDetail">
|
<code-example path="toh-pt5/src/app/heroes.component.ts" linenums="false" title="src/app/heroes.component.ts (gotoDetail)" region="gotoDetail">
|
||||||
@ -834,12 +875,13 @@ This approach requires the following changes to the component class:
|
|||||||
</code-example>
|
</code-example>
|
||||||
|
|
||||||
Note that you're passing a two-element *link parameters !{_array}*—a
|
Note that you're passing a two-element *link parameters !{_array}*—a
|
||||||
path and the route parameter—to
|
!{_pathVsName} and the route parameter—to
|
||||||
the `router.navigate()` method, just as you did in the `[routerLink]` binding
|
the router `navigate()` method, just as you did in the `[routerLink]` binding
|
||||||
back in the `DashboardComponent`.
|
back in the `DashboardComponent`.
|
||||||
Here's the revised `HeroesComponent` class:
|
Here's the revised `HeroesComponent` class:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="toh-pt5/src/app/heroes.component.ts" linenums="false" title="src/app/heroes.component.ts (class)" region="class">
|
<code-example path="toh-pt5/src/app/heroes.component.ts" linenums="false" title="src/app/heroes.component.ts (class)" region="class">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -864,6 +906,7 @@ Add a <span ngio-ex>dashboard.component.css</span> file to the `!{_appDir}` fold
|
|||||||
that file in the component metadata's `styleUrls` !{_array} property like this:
|
that file in the component metadata's `styleUrls` !{_array} property like this:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="toh-pt5/src/app/dashboard.component.ts" linenums="false" title="src/app/dashboard.component.ts (styleUrls)" region="css">
|
<code-example path="toh-pt5/src/app/dashboard.component.ts" linenums="false" title="src/app/dashboard.component.ts (styleUrls)" region="css">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -884,11 +927,13 @@ Here's the content for the component CSS files.
|
|||||||
|
|
||||||
<code-tabs>
|
<code-tabs>
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="src/app/hero-detail.component.css" path="toh-5/src/app/hero-detail.component.css">
|
<code-pane title="src/app/hero-detail.component.css" path="toh-5/src/app/hero-detail.component.css">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="src/app/dashboard.component.css" path="toh-5/src/app/dashboard.component.css">
|
<code-pane title="src/app/dashboard.component.css" path="toh-5/src/app/dashboard.component.css">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
@ -904,6 +949,7 @@ You'll surround those links in `<nav>` tags.
|
|||||||
Add an <span ngio-ex>app.component.css</span> file to the `!{_appDir}` folder with the following content.
|
Add an <span ngio-ex>app.component.css</span> file to the `!{_appDir}` folder with the following content.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="toh-pt5/src/app/app.component.css" linenums="false" title="src/app/app.component.css (navigation styles)" region="navigation styles">
|
<code-example path="toh-pt5/src/app/app.component.css" linenums="false" title="src/app/app.component.css (navigation styles)" region="navigation styles">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -932,6 +978,7 @@ All you have to do is define the style for it.
|
|||||||
Add a `styleUrls` property that refers to this CSS file as follows:
|
Add a `styleUrls` property that refers to this CSS file as follows:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="toh-pt5/src/app/app.component.ts" linenums="false" title="src/app/app.component.ts (styleUrls)" region="styleUrls">
|
<code-example path="toh-pt5/src/app/app.component.ts" linenums="false" title="src/app/app.component.ts (styleUrls)" region="styleUrls">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -949,6 +996,7 @@ These correspond to the full set of master styles that you installed earlier dur
|
|||||||
Here's an excerpt:
|
Here's an excerpt:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="toh-pt5/src/styles.css" linenums="false" title="src/styles.css (excerpt)" region="toh">
|
<code-example path="toh-pt5/src/styles.css" linenums="false" title="src/styles.css (excerpt)" region="toh">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -958,12 +1006,14 @@ Ensure that the file contains the [master styles provided here](tutorial/!{style
|
|||||||
Also edit <span ngio-ex>index.html</span> to refer to this stylesheet.
|
Also edit <span ngio-ex>index.html</span> to refer to this stylesheet.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="toh-pt5/src/index.html" linenums="false" title="src/index.html (link ref)" region="css">
|
<code-example path="toh-pt5/src/index.html" linenums="false" title="src/index.html (link ref)" region="css">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
|
|
||||||
Look at the app now. The dashboard, heroes, and navigation links are styled.
|
Look at the app now. The dashboard, heroes, and navigation links are styled.
|
||||||
|
|
||||||
|
|
||||||
<figure class='image-display'>
|
<figure class='image-display'>
|
||||||
<img src='assets/images/devguide/toh/dashboard-top-heroes.png' alt="View navigations"> </img>
|
<img src='assets/images/devguide/toh/dashboard-top-heroes.png' alt="View navigations"> </img>
|
||||||
</figure>
|
</figure>
|
||||||
@ -975,89 +1025,109 @@ Review the sample source code in the <live-example></live-example> for this page
|
|||||||
Verify that you have the following structure:
|
Verify that you have the following structure:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<aio-filetree>
|
<aio-filetree>
|
||||||
|
|
||||||
|
|
||||||
<aio-folder>
|
<aio-folder>
|
||||||
angular-tour-of-heroes
|
angular-tour-of-heroes
|
||||||
|
|
||||||
<aio-folder>
|
<aio-folder>
|
||||||
src
|
src
|
||||||
|
|
||||||
<aio-folder>
|
<aio-folder>
|
||||||
app
|
app
|
||||||
|
|
||||||
<aio-file>
|
<aio-file>
|
||||||
app.component.css
|
app.component.css
|
||||||
</aio-file>
|
</aio-file>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<aio-file>
|
<aio-file>
|
||||||
app.component.ts
|
app.component.ts
|
||||||
</aio-file>
|
</aio-file>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<aio-file>
|
<aio-file>
|
||||||
app.module.ts
|
app.module.ts
|
||||||
</aio-file>
|
</aio-file>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<aio-file>
|
<aio-file>
|
||||||
app-routing.module.ts
|
app-routing.module.ts
|
||||||
</aio-file>
|
</aio-file>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<aio-file>
|
<aio-file>
|
||||||
dashboard.component.css
|
dashboard.component.css
|
||||||
</aio-file>
|
</aio-file>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<aio-file>
|
<aio-file>
|
||||||
dashboard.component.html
|
dashboard.component.html
|
||||||
</aio-file>
|
</aio-file>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<aio-file>
|
<aio-file>
|
||||||
dashboard.component.ts
|
dashboard.component.ts
|
||||||
</aio-file>
|
</aio-file>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<aio-file>
|
<aio-file>
|
||||||
hero.service.ts
|
hero.service.ts
|
||||||
</aio-file>
|
</aio-file>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<aio-file>
|
<aio-file>
|
||||||
hero.ts
|
hero.ts
|
||||||
</aio-file>
|
</aio-file>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<aio-file>
|
<aio-file>
|
||||||
hero-detail.component.css
|
hero-detail.component.css
|
||||||
</aio-file>
|
</aio-file>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<aio-file>
|
<aio-file>
|
||||||
hero-detail.component.html
|
hero-detail.component.html
|
||||||
</aio-file>
|
</aio-file>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<aio-file>
|
<aio-file>
|
||||||
hero-detail.component.ts
|
hero-detail.component.ts
|
||||||
</aio-file>
|
</aio-file>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<aio-file>
|
<aio-file>
|
||||||
heroes.component.css
|
heroes.component.css
|
||||||
</aio-file>
|
</aio-file>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<aio-file>
|
<aio-file>
|
||||||
heroes.component.html
|
heroes.component.html
|
||||||
</aio-file>
|
</aio-file>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<aio-file>
|
<aio-file>
|
||||||
heroes.component.ts
|
heroes.component.ts
|
||||||
</aio-file>
|
</aio-file>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<aio-file>
|
<aio-file>
|
||||||
mock-heroes.ts
|
mock-heroes.ts
|
||||||
</aio-file>
|
</aio-file>
|
||||||
@ -1066,26 +1136,31 @@ Verify that you have the following structure:
|
|||||||
</aio-folder>
|
</aio-folder>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<aio-file>
|
<aio-file>
|
||||||
main.ts
|
main.ts
|
||||||
</aio-file>
|
</aio-file>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<aio-file>
|
<aio-file>
|
||||||
index.html
|
index.html
|
||||||
</aio-file>
|
</aio-file>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<aio-file>
|
<aio-file>
|
||||||
styles.css
|
styles.css
|
||||||
</aio-file>
|
</aio-file>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<aio-file>
|
<aio-file>
|
||||||
systemjs.config.js
|
systemjs.config.js
|
||||||
</aio-file>
|
</aio-file>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<aio-file>
|
<aio-file>
|
||||||
tsconfig.json
|
tsconfig.json
|
||||||
</aio-file>
|
</aio-file>
|
||||||
@ -1094,11 +1169,13 @@ Verify that you have the following structure:
|
|||||||
</aio-folder>
|
</aio-folder>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<aio-file>
|
<aio-file>
|
||||||
node_modules ...
|
node_modules ...
|
||||||
</aio-file>
|
</aio-file>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<aio-file>
|
<aio-file>
|
||||||
package.json
|
package.json
|
||||||
</aio-file>
|
</aio-file>
|
||||||
|
@ -24,6 +24,7 @@ That's the starting point for this page.
|
|||||||
## Keep the app transpiling and running
|
## Keep the app transpiling and running
|
||||||
Enter the following command in the terminal window:
|
Enter the following command in the terminal window:
|
||||||
|
|
||||||
|
|
||||||
<code-example language="sh" class="code-shell">
|
<code-example language="sh" class="code-shell">
|
||||||
npm start
|
npm start
|
||||||
|
|
||||||
@ -31,10 +32,10 @@ Enter the following command in the terminal window:
|
|||||||
|
|
||||||
This command runs the TypeScript compiler in "watch mode", recompiling automatically when the code changes.
|
This command runs the TypeScript compiler in "watch mode", recompiling automatically when the code changes.
|
||||||
The command simultaneously launches the app in a browser and refreshes the browser when the code changes.
|
The command simultaneously launches the app in a browser and refreshes the browser when the code changes.
|
||||||
|
|
||||||
You can keep building the Tour of Heroes without pausing to recompile or refresh the browser.
|
You can keep building the Tour of Heroes without pausing to recompile or refresh the browser.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<h1>
|
<h1>
|
||||||
Providing HTTP Services
|
Providing HTTP Services
|
||||||
</h1>
|
</h1>
|
||||||
@ -45,7 +46,7 @@ The `HttpModule` is not a core Angular module.
|
|||||||
and is shipped in a separate script file as part of the Angular npm package.
|
and is shipped in a separate script file as part of the Angular npm package.
|
||||||
|
|
||||||
You're ready to import from `@angular/http` because `systemjs.config` configured *SystemJS* to load that library when you need it.
|
You're ready to import from `@angular/http` because `systemjs.config` configured *SystemJS* to load that library when you need it.
|
||||||
### Register for HTTP services
|
## Register for HTTP services
|
||||||
|
|
||||||
The app will depend on the Angular `http` service, which itself depends on other supporting services.
|
The app will depend on the Angular `http` service, which itself depends on other supporting services.
|
||||||
The `HttpModule` from the `@angular/http` library holds providers for a complete set of HTTP services.
|
The `HttpModule` from the `@angular/http` library holds providers for a complete set of HTTP services.
|
||||||
@ -54,6 +55,7 @@ To allow access to these services from anywhere in the app,
|
|||||||
add `HttpModule` to the `imports` list of the `AppModule`.
|
add `HttpModule` to the `imports` list of the `AppModule`.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="toh-pt6/src/app/app.module.ts" region="v1">
|
<code-example path="toh-pt6/src/app/app.module.ts" region="v1">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -62,20 +64,14 @@ Notice that you also supply `!{_HttpModule}` as part of the *imports* !{_array}
|
|||||||
|
|
||||||
## Simulate the web API
|
## Simulate the web API
|
||||||
|
|
||||||
We recommend registering app-wide services in the root
|
|
||||||
`!{_AppModuleVsAppComp}` *providers*. <span if-docs="dart">Here you're
|
|
||||||
registering in `main` for a special reason.</span>
|
|
||||||
|
|
||||||
Until you have a web server that can handle requests for hero data,
|
Until you have a web server that can handle requests for hero data,
|
||||||
the HTTP client will fetch and save data from
|
the HTTP client will fetch and save data from
|
||||||
a mock service, the *in-memory web API*.
|
a mock service, the *in-memory web API*.
|
||||||
<span if-docs="dart"> The app itself doesn't need to know
|
|
||||||
about this, so you can slip the in-memory web API into the
|
|
||||||
configuration above the `AppComponent`.</span>
|
|
||||||
|
|
||||||
Update <span ngio-ex>!{_appModuleTsVsMainTs}</span> with this version, which uses the mock service:
|
Update <span ngio-ex>!{_appModuleTsVsMainTs}</span> with this version, which uses the mock service:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="toh-pt6/_appModuleTsVsMainTs" linenums="false" title="_appModuleTsVsMainTs (v2)" region="v2">
|
<code-example path="toh-pt6/_appModuleTsVsMainTs" linenums="false" title="_appModuleTsVsMainTs (v2)" region="v2">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -86,6 +82,7 @@ Rather than require a real API server, this example simulates communication with
|
|||||||
to the module `imports`, effectively replacing the `Http` client's XHR backend service with an in-memory alternative.
|
to the module `imports`, effectively replacing the `Http` client's XHR backend service with an in-memory alternative.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="toh-pt6/_appModuleTsVsMainTs" linenums="false" title="_appModuleTsVsMainTs (in-mem-web-api)" region="in-mem-web-api">
|
<code-example path="toh-pt6/_appModuleTsVsMainTs" linenums="false" title="_appModuleTsVsMainTs (in-mem-web-api)" region="in-mem-web-api">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -95,6 +92,7 @@ that primes the in-memory database.
|
|||||||
Add the file `in-memory-data.service.ts` in `!{_appDir}` with the following content:
|
Add the file `in-memory-data.service.ts` in `!{_appDir}` with the following content:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="toh-pt6/src/app/in-memory-data.service.ts" region="init" linenums="false">
|
<code-example path="toh-pt6/src/app/in-memory-data.service.ts" region="init" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -122,6 +120,7 @@ section of the [HTTP Client](guide/server-communication) page.
|
|||||||
In the current `HeroService` implementation, a !{_Promise} resolved with mock heroes is returned.
|
In the current `HeroService` implementation, a !{_Promise} resolved with mock heroes is returned.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="toh-4/src/app/hero.service.ts" linenums="false" title="toh-4/ts/src/app/hero.service.ts (old getHeroes)" region="get-heroes">
|
<code-example path="toh-4/src/app/hero.service.ts" linenums="false" title="toh-4/ts/src/app/hero.service.ts (old getHeroes)" region="get-heroes">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -132,6 +131,7 @@ fetching heroes with an HTTP client, which must be an asynchronous operation.
|
|||||||
Now convert `getHeroes()` to use HTTP.
|
Now convert `getHeroes()` to use HTTP.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="toh-pt6/src/app/hero.service.ts" linenums="false" title="src/app/hero.service.ts (updated getHeroes and new class members)" region="getHeroes">
|
<code-example path="toh-pt6/src/app/hero.service.ts" linenums="false" title="src/app/hero.service.ts (updated getHeroes and new class members)" region="getHeroes">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -139,6 +139,7 @@ Now convert `getHeroes()` to use HTTP.
|
|||||||
Update the import statements as follows:
|
Update the import statements as follows:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="toh-pt6/src/app/hero.service.ts" linenums="false" title="src/app/hero.service.ts (updated imports)" region="imports">
|
<code-example path="toh-pt6/src/app/hero.service.ts" linenums="false" title="src/app/hero.service.ts (updated imports)" region="imports">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -156,6 +157,7 @@ You'll read about [Observables](tutorial/toh-pt6#observables) later in this page
|
|||||||
For now, you've converted the `Observable` to a `Promise` using the `toPromise` operator.
|
For now, you've converted the `Observable` to a `Promise` using the `toPromise` operator.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="toh-pt6/src/app/hero.service.ts" linenums="false" title="src/app/hero.service.ts (to-promise)" region="to-promise">
|
<code-example path="toh-pt6/src/app/hero.service.ts" linenums="false" title="src/app/hero.service.ts (to-promise)" region="to-promise">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -167,6 +169,7 @@ To use those capabilities, you have to add the operators themselves.
|
|||||||
That's as easy as importing them from the RxJS library like this:
|
That's as easy as importing them from the RxJS library like this:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="toh-pt6/src/app/hero.service.ts" linenums="false" title="src/app/hero.service.ts (rxjs)" region="rxjs">
|
<code-example path="toh-pt6/src/app/hero.service.ts" linenums="false" title="src/app/hero.service.ts (rxjs)" region="rxjs">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -186,6 +189,7 @@ In the *Promise*'s `then()` callback, you call the `json` method of the HTTP `Re
|
|||||||
data within the response.
|
data within the response.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="toh-pt6/src/app/hero.service.ts" linenums="false" title="src/app/hero.service.ts (to-data)" region="to-data">
|
<code-example path="toh-pt6/src/app/hero.service.ts" linenums="false" title="src/app/hero.service.ts (to-data)" region="to-data">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -212,6 +216,7 @@ It receives a !{_Promise} of *heroes* just as it did before.
|
|||||||
At the end of `getHeroes()`, you `catch` server failures and pass them to an error handler.
|
At the end of `getHeroes()`, you `catch` server failures and pass them to an error handler.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="toh-pt6/src/app/hero.service.ts" linenums="false" title="src/app/hero.service.ts (catch)" region="catch">
|
<code-example path="toh-pt6/src/app/hero.service.ts" linenums="false" title="src/app/hero.service.ts (catch)" region="catch">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -220,11 +225,12 @@ This is a critical step.
|
|||||||
You must anticipate HTTP failures, as they happen frequently for reasons beyond your control.
|
You must anticipate HTTP failures, as they happen frequently for reasons beyond your control.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="toh-pt6/src/app/hero.service.ts" linenums="false" title="src/app/hero.service.ts (handleError)" region="handleError">
|
<code-example path="toh-pt6/src/app/hero.service.ts" linenums="false" title="src/app/hero.service.ts (handleError)" region="handleError">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
|
|
||||||
In this demo service, you log the error to the console; in real life,
|
This demo service logs the error to the console; in real life,
|
||||||
you would handle the error in code. For a demo, this works.
|
you would handle the error in code. For a demo, this works.
|
||||||
|
|
||||||
The code also includes an error to
|
The code also includes an error to
|
||||||
@ -239,13 +245,14 @@ filters for the one with the matching `id`.
|
|||||||
That's fine for a simulation, but it's wasteful to ask a real server for all heroes when you only want one.
|
That's fine for a simulation, but it's wasteful to ask a real server for all heroes when you only want one.
|
||||||
Most web APIs support a _get-by-id_ request in the form `api/hero/:id` (such as `api/hero/11`).
|
Most web APIs support a _get-by-id_ request in the form `api/hero/:id` (such as `api/hero/11`).
|
||||||
|
|
||||||
Update the `HeroService.getHero` method to make a _get-by-id_ request:
|
Update the `HeroService.getHero()` method to make a _get-by-id_ request:
|
||||||
|
|
||||||
|
|
||||||
<code-example path="toh-pt6/src/app/hero.service.ts" linenums="false" title="src/app/hero.service.ts (getHero)" region="getHero">
|
<code-example path="toh-pt6/src/app/hero.service.ts" linenums="false" title="src/app/hero.service.ts (getHero)" region="getHero">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
|
|
||||||
This request is almost the same as `getHeroes`.
|
This request is almost the same as `getHeroes()`.
|
||||||
The hero id in the URL identifies which hero the server should update.
|
The hero id in the URL identifies which hero the server should update.
|
||||||
|
|
||||||
Also, the `data` in the response is a single hero object rather than !{_an} !{_array}.
|
Also, the `data` in the response is a single hero object rather than !{_an} !{_array}.
|
||||||
@ -274,25 +281,28 @@ the server.
|
|||||||
### Add the ability to save hero details
|
### Add the ability to save hero details
|
||||||
|
|
||||||
At the end of the hero detail template, add a save button with a `click` event
|
At the end of the hero detail template, add a save button with a `click` event
|
||||||
binding that invokes a new component method named `save`.
|
binding that invokes a new component method named `save()`.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="toh-pt6/src/app/hero-detail.component.html" linenums="false" title="src/app/hero-detail.component.html (save)" region="save">
|
<code-example path="toh-pt6/src/app/hero-detail.component.html" linenums="false" title="src/app/hero-detail.component.html (save)" region="save">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
|
|
||||||
Add the following `save` method, which persists hero name changes using the hero service
|
Add the following `save()` method, which persists hero name changes using the hero service
|
||||||
`update` method and then navigates back to the previous view.
|
`update()` method and then navigates back to the previous view.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="toh-pt6/src/app/hero-detail.component.ts" linenums="false" title="src/app/hero-detail.component.ts (save)" region="save">
|
<code-example path="toh-pt6/src/app/hero-detail.component.ts" linenums="false" title="src/app/hero-detail.component.ts (save)" region="save">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
|
|
||||||
### Add a hero service _update_ method
|
### Add a hero service _update()_ method
|
||||||
|
|
||||||
|
The overall structure of the `update()` method is similar to that of
|
||||||
|
`getHeroes()`, but it uses an HTTP `put()` to persist server-side changes.
|
||||||
|
|
||||||
The overall structure of the `update` method is similar to that of
|
|
||||||
`getHeroes`, but it uses an HTTP `put()` to persist server-side changes.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -317,6 +327,7 @@ Insert the following into the heroes component HTML, just after
|
|||||||
the heading:
|
the heading:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="toh-pt6/src/app/heroes.component.html" linenums="false" title="src/app/heroes.component.html (add)" region="add">
|
<code-example path="toh-pt6/src/app/heroes.component.html" linenums="false" title="src/app/heroes.component.html (add)" region="add">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -325,6 +336,7 @@ In response to a click event, call the component's click handler and then
|
|||||||
clear the input field so that it's ready for another name.
|
clear the input field so that it's ready for another name.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="toh-pt6/src/app/heroes.component.ts" linenums="false" title="src/app/heroes.component.ts (add)" region="add">
|
<code-example path="toh-pt6/src/app/heroes.component.ts" linenums="false" title="src/app/heroes.component.ts (add)" region="add">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -332,7 +344,8 @@ clear the input field so that it's ready for another name.
|
|||||||
When the given name is non-blank, the handler delegates creation of the
|
When the given name is non-blank, the handler delegates creation of the
|
||||||
named hero to the hero service, and then adds the new hero to the !{_array}.
|
named hero to the hero service, and then adds the new hero to the !{_array}.
|
||||||
|
|
||||||
Implement the `create` method in the `HeroService` class.
|
Implement the `create()` method in the `HeroService` class.
|
||||||
|
|
||||||
|
|
||||||
<code-example path="toh-pt6/src/app/hero.service.ts" linenums="false" title="src/app/hero.service.ts (create)" region="create">
|
<code-example path="toh-pt6/src/app/hero.service.ts" linenums="false" title="src/app/hero.service.ts (create)" region="create">
|
||||||
|
|
||||||
@ -345,7 +358,8 @@ Refresh the browser and create some heroes.
|
|||||||
Each hero in the heroes view should have a delete button.
|
Each hero in the heroes view should have a delete button.
|
||||||
|
|
||||||
Add the following button element to the heroes component HTML, after the hero
|
Add the following button element to the heroes component HTML, after the hero
|
||||||
name in the repeated `<li>` tag.
|
name in the repeated `<li>` element.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="toh-pt6/src/app/heroes.component.html" linenums="false" title="src/app/heroes.component.html (delete)" region="delete">
|
<code-example path="toh-pt6/src/app/heroes.component.html" linenums="false" title="src/app/heroes.component.html (delete)" region="delete">
|
||||||
@ -355,6 +369,7 @@ name in the repeated `<li>` tag.
|
|||||||
The `<li>` element should now look like this:
|
The `<li>` element should now look like this:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="toh-pt6/src/app/heroes.component.html" linenums="false" title="src/app/heroes.component.html (li-element)" region="li-element">
|
<code-example path="toh-pt6/src/app/heroes.component.html" linenums="false" title="src/app/heroes.component.html (li-element)" region="li-element">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -367,6 +382,7 @@ select the hero that the user will delete.
|
|||||||
The logic of the `delete()` handler is a bit trickier:
|
The logic of the `delete()` handler is a bit trickier:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="toh-pt6/src/app/heroes.component.ts" linenums="false" title="src/app/heroes.component.ts (delete)" region="delete">
|
<code-example path="toh-pt6/src/app/heroes.component.ts" linenums="false" title="src/app/heroes.component.ts (delete)" region="delete">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -375,24 +391,27 @@ Of course you delegate hero deletion to the hero service, but the component
|
|||||||
is still responsible for updating the display: it removes the deleted hero
|
is still responsible for updating the display: it removes the deleted hero
|
||||||
from the !{_array} and resets the selected hero, if necessary.
|
from the !{_array} and resets the selected hero, if necessary.
|
||||||
To place the delete button at the far right of the hero entry,
|
To place the delete button at the far right of the hero entry,
|
||||||
add this additional CSS:
|
add this CSS:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="toh-pt6/src/app/heroes.component.css" linenums="false" title="src/app/heroes.component.css (additions)" region="additions">
|
<code-example path="toh-pt6/src/app/heroes.component.css" linenums="false" title="src/app/heroes.component.css (additions)" region="additions">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
|
|
||||||
### Hero service `delete()` method
|
### Hero service _delete()_ method
|
||||||
|
|
||||||
Add the hero service's `delete()` method, which uses the `delete()` HTTP method to remove the hero from the server:
|
Add the hero service's `delete()` method, which uses the `delete()` HTTP method to remove the hero from the server:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="toh-pt6/src/app/hero.service.ts" linenums="false" title="src/app/hero.service.ts (delete)" region="delete">
|
<code-example path="toh-pt6/src/app/hero.service.ts" linenums="false" title="src/app/hero.service.ts (delete)" region="delete">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
|
|
||||||
Refresh the browser and try the new delete functionality.
|
Refresh the browser and try the new delete functionality.
|
||||||
|
|
||||||
|
|
||||||
<div id='observables'>
|
<div id='observables'>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
@ -421,8 +440,8 @@ The calling component can easily consume a single result in the form of a Promis
|
|||||||
But requests aren't always done only once.
|
But requests aren't always done only once.
|
||||||
You may start one request,
|
You may start one request,
|
||||||
cancel it, and make a different request before the server has responded to the first request.
|
cancel it, and make a different request before the server has responded to the first request.
|
||||||
A *request-cancel-new-request* sequence is difficult to implement with *!{Promise}s*, but
|
A *request-cancel-new-request* sequence is difficult to implement with *!{_Promise}s*, but
|
||||||
easy with *!{Observable}s*.
|
easy with *!{_Observable}s*.
|
||||||
|
|
||||||
### Add the ability to search by name
|
### Add the ability to search by name
|
||||||
You're going to add a *hero search* feature to the Tour of Heroes.
|
You're going to add a *hero search* feature to the Tour of Heroes.
|
||||||
@ -431,6 +450,7 @@ As the user types a name into a search box, you'll make repeated HTTP requests f
|
|||||||
Start by creating `HeroSearchService` that sends search queries to the server's web API.
|
Start by creating `HeroSearchService` that sends search queries to the server's web API.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="toh-pt6/src/app/hero-search.service.ts">
|
<code-example path="toh-pt6/src/app/hero-search.service.ts">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -442,9 +462,8 @@ in the `HeroService`, although the URL now has a query string.
|
|||||||
Instead you return the *Observable* from the the `htttp.get()`,
|
Instead you return the *Observable* from the the `htttp.get()`,
|
||||||
after chaining it to another RxJS operator, <code>map()</code>,
|
after chaining it to another RxJS operator, <code>map()</code>,
|
||||||
to extract heroes from the response data.
|
to extract heroes from the response data.
|
||||||
|
|
||||||
RxJS operator chaining makes response processing easy and readable.
|
RxJS operator chaining makes response processing easy and readable.
|
||||||
See the [discussion below about operators](tutorial/toh-pt6#rxjs-imports).
|
See the [discussion below about operators](tutorial/toh-pt6#rxjs-imports).</span>
|
||||||
### HeroSearchComponent
|
### HeroSearchComponent
|
||||||
|
|
||||||
Create a `HeroSearchComponent` that calls the new `HeroSearchService`.
|
Create a `HeroSearchComponent` that calls the new `HeroSearchService`.
|
||||||
@ -452,12 +471,14 @@ Create a `HeroSearchComponent` that calls the new `HeroSearchService`.
|
|||||||
The component template is simple—just a text box and a list of matching search results.
|
The component template is simple—just a text box and a list of matching search results.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="toh-pt6/src/app/hero-search.component.html">
|
<code-example path="toh-pt6/src/app/hero-search.component.html">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
|
|
||||||
Also, add styles for the new component.
|
Also, add styles for the new component.
|
||||||
|
|
||||||
|
|
||||||
<code-example path="toh-pt6/src/app/hero-search.component.css">
|
<code-example path="toh-pt6/src/app/hero-search.component.css">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -474,13 +495,15 @@ The `async` pipe subscribes to the `!{_Observable}` and produces the !{_array} o
|
|||||||
Create the `HeroSearchComponent` class and metadata.
|
Create the `HeroSearchComponent` class and metadata.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="toh-pt6/src/app/hero-search.component.ts">
|
<code-example path="toh-pt6/src/app/hero-search.component.ts">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
|
|
||||||
#### Search terms
|
#### Search terms
|
||||||
|
|
||||||
Focus on the `!{_priv}searchTerms`:
|
Focus on `!{_priv}searchTerms`:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="toh-pt6/src/app/hero-search.component.ts" linenums="false" title="src/app/hero-search.component.ts (searchTerms)" region="searchTerms">
|
<code-example path="toh-pt6/src/app/hero-search.component.ts" linenums="false" title="src/app/hero-search.component.ts (searchTerms)" region="searchTerms">
|
||||||
@ -500,6 +523,7 @@ You can turn the stream
|
|||||||
of search terms into a stream of `Hero` !{_array}s and assign the result to the `heroes` property.
|
of search terms into a stream of `Hero` !{_array}s and assign the result to the `heroes` property.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="toh-pt6/src/app/hero-search.component.ts" linenums="false" title="src/app/hero-search.component.ts (search)" region="search">
|
<code-example path="toh-pt6/src/app/hero-search.component.ts" linenums="false" title="src/app/hero-search.component.ts (search)" region="search">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -512,8 +536,8 @@ You'll make fewer calls to the `HeroSearchService` and still get timely results.
|
|||||||
|
|
||||||
* `debounceTime(300)` waits until the flow of new string events pauses for 300 milliseconds
|
* `debounceTime(300)` waits until the flow of new string events pauses for 300 milliseconds
|
||||||
before passing along the latest string. You'll never make requests more frequently than 300ms.
|
before passing along the latest string. You'll never make requests more frequently than 300ms.
|
||||||
* `distinctUntilChanged` ensures that a request is sent only if the filter text changed.
|
* `distinctUntilChanged()` ensures that a request is sent only if the filter text changed.
|
||||||
* `switchMap()` calls the search service for each search term that makes it through `debounce` and `distinctUntilChanged`.
|
* `switchMap()` calls the search service for each search term that makes it through `debounceTime()` and `distinctUntilChanged()`.
|
||||||
It cancels and discards previous search observables, returning only the latest search service observable.
|
It cancels and discards previous search observables, returning only the latest search service observable.
|
||||||
|
|
||||||
|
|
||||||
@ -553,6 +577,7 @@ When you need more RxJS features, extend `Observable` by *importing* the librar
|
|||||||
Here are all the RxJS imports that _this_ component needs:
|
Here are all the RxJS imports that _this_ component needs:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="toh-pt6/src/app/hero-search.component.ts" region="rxjs-imports" linenums="false">
|
<code-example path="toh-pt6/src/app/hero-search.component.ts" region="rxjs-imports" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -568,6 +593,7 @@ loads and executes the library's script file which, in turn, adds the operator t
|
|||||||
Add the hero search HTML element to the bottom of the `DashboardComponent` template.
|
Add the hero search HTML element to the bottom of the `DashboardComponent` template.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="toh-pt6/src/app/dashboard.component.html" linenums="false">
|
<code-example path="toh-pt6/src/app/dashboard.component.html" linenums="false">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -577,6 +603,7 @@ Finally, import `HeroSearchComponent` from
|
|||||||
and add it to the `!{_declarations}` !{_array}.
|
and add it to the `!{_declarations}` !{_array}.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="toh-pt6/declFile" linenums="false" title="declFile (search)" region="search">
|
<code-example path="toh-pt6/declFile" linenums="false" title="declFile (search)" region="search">
|
||||||
|
|
||||||
</code-example>
|
</code-example>
|
||||||
@ -584,6 +611,7 @@ and add it to the `!{_declarations}` !{_array}.
|
|||||||
Run the app again. In the Dashboard, enter some text in the search box.
|
Run the app again. In the Dashboard, enter some text in the search box.
|
||||||
If you enter characters that match any existing hero names, you'll see something like this.
|
If you enter characters that match any existing hero names, you'll see something like this.
|
||||||
|
|
||||||
|
|
||||||
<figure class='image-display'>
|
<figure class='image-display'>
|
||||||
<img src='assets/images/devguide/toh/toh-hero-search.png' alt="Hero Search Component"> </img>
|
<img src='assets/images/devguide/toh/toh-hero-search.png' alt="Hero Search Component"> </img>
|
||||||
</figure>
|
</figure>
|
||||||
@ -595,109 +623,133 @@ Review the sample source code in the <live-example></live-example> for this page
|
|||||||
Verify that you have the following structure:
|
Verify that you have the following structure:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<aio-filetree>
|
<aio-filetree>
|
||||||
|
|
||||||
|
|
||||||
<aio-folder>
|
<aio-folder>
|
||||||
angular-tour-of-heroes
|
angular-tour-of-heroes
|
||||||
|
|
||||||
<aio-folder>
|
<aio-folder>
|
||||||
src
|
src
|
||||||
|
|
||||||
<aio-folder>
|
<aio-folder>
|
||||||
app
|
app
|
||||||
|
|
||||||
<aio-file>
|
<aio-file>
|
||||||
app.component.ts
|
app.component.ts
|
||||||
</aio-file>
|
</aio-file>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<aio-file>
|
<aio-file>
|
||||||
app.component.css
|
app.component.css
|
||||||
</aio-file>
|
</aio-file>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<aio-file>
|
<aio-file>
|
||||||
app.module.ts
|
app.module.ts
|
||||||
</aio-file>
|
</aio-file>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<aio-file>
|
<aio-file>
|
||||||
app-routing.module.ts
|
app-routing.module.ts
|
||||||
</aio-file>
|
</aio-file>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<aio-file>
|
<aio-file>
|
||||||
dashboard.component.css
|
dashboard.component.css
|
||||||
</aio-file>
|
</aio-file>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<aio-file>
|
<aio-file>
|
||||||
dashboard.component.html
|
dashboard.component.html
|
||||||
</aio-file>
|
</aio-file>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<aio-file>
|
<aio-file>
|
||||||
dashboard.component.ts
|
dashboard.component.ts
|
||||||
</aio-file>
|
</aio-file>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<aio-file>
|
<aio-file>
|
||||||
hero.ts
|
hero.ts
|
||||||
</aio-file>
|
</aio-file>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<aio-file>
|
<aio-file>
|
||||||
hero-detail.component.css
|
hero-detail.component.css
|
||||||
</aio-file>
|
</aio-file>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<aio-file>
|
<aio-file>
|
||||||
hero-detail.component.html
|
hero-detail.component.html
|
||||||
</aio-file>
|
</aio-file>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<aio-file>
|
<aio-file>
|
||||||
hero-detail.component.ts
|
hero-detail.component.ts
|
||||||
</aio-file>
|
</aio-file>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<aio-file>
|
<aio-file>
|
||||||
hero-search.component.html (new)
|
hero-search.component.html (new)
|
||||||
</aio-file>
|
</aio-file>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<aio-file>
|
<aio-file>
|
||||||
hero-search.component.css (new)
|
hero-search.component.css (new)
|
||||||
</aio-file>
|
</aio-file>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<aio-file>
|
<aio-file>
|
||||||
hero-search.component.ts (new)
|
hero-search.component.ts (new)
|
||||||
</aio-file>
|
</aio-file>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<aio-file>
|
<aio-file>
|
||||||
hero-search.service.ts (new)
|
hero-search.service.ts (new)
|
||||||
</aio-file>
|
</aio-file>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<aio-file>
|
<aio-file>
|
||||||
hero.service.ts
|
hero.service.ts
|
||||||
</aio-file>
|
</aio-file>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<aio-file>
|
<aio-file>
|
||||||
heroes.component.css
|
heroes.component.css
|
||||||
</aio-file>
|
</aio-file>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<aio-file>
|
<aio-file>
|
||||||
heroes.component.html
|
heroes.component.html
|
||||||
</aio-file>
|
</aio-file>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<aio-file>
|
<aio-file>
|
||||||
heroes.component.ts
|
heroes.component.ts
|
||||||
</aio-file>
|
</aio-file>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<aio-file>
|
<aio-file>
|
||||||
in-memory-data.service.ts (new)
|
in-memory-data.service.ts (new)
|
||||||
</aio-file>
|
</aio-file>
|
||||||
@ -706,26 +758,31 @@ Verify that you have the following structure:
|
|||||||
</aio-folder>
|
</aio-folder>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<aio-file>
|
<aio-file>
|
||||||
main.ts
|
main.ts
|
||||||
</aio-file>
|
</aio-file>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<aio-file>
|
<aio-file>
|
||||||
index.html
|
index.html
|
||||||
</aio-file>
|
</aio-file>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<aio-file>
|
<aio-file>
|
||||||
styles.css
|
styles.css
|
||||||
</aio-file>
|
</aio-file>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<aio-file>
|
<aio-file>
|
||||||
systemjs.config.js
|
systemjs.config.js
|
||||||
</aio-file>
|
</aio-file>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<aio-file>
|
<aio-file>
|
||||||
tsconfig.json
|
tsconfig.json
|
||||||
</aio-file>
|
</aio-file>
|
||||||
@ -734,11 +791,13 @@ Verify that you have the following structure:
|
|||||||
</aio-folder>
|
</aio-folder>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<aio-file>
|
<aio-file>
|
||||||
node_modules ...
|
node_modules ...
|
||||||
</aio-file>
|
</aio-file>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<aio-file>
|
<aio-file>
|
||||||
package.json
|
package.json
|
||||||
</aio-file>
|
</aio-file>
|
||||||
@ -764,48 +823,58 @@ Here are the files you added or changed in this page.
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-tabs>
|
<code-tabs>
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="app.comp...ts" path="toh-6/src/app/app.component.ts">
|
<code-pane title="app.comp...ts" path="toh-6/src/app/app.component.ts">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="app.mod...ts" path="toh-6/src/app/app.module.ts">
|
<code-pane title="app.mod...ts" path="toh-6/src/app/app.module.ts">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="heroes.comp...ts" path="toh-6/src/app/heroes.component.ts">
|
<code-pane title="heroes.comp...ts" path="toh-6/src/app/heroes.component.ts">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="heroes.comp...html" path="toh-6/src/app/heroes.component.html">
|
<code-pane title="heroes.comp...html" path="toh-6/src/app/heroes.component.html">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="heroes.comp...css" path="toh-6/src/app/heroes.component.css">
|
<code-pane title="heroes.comp...css" path="toh-6/src/app/heroes.component.css">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="hero-detail.comp...ts" path="toh-6/src/app/hero-detail.component.ts">
|
<code-pane title="hero-detail.comp...ts" path="toh-6/src/app/hero-detail.component.ts">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="hero-detail.comp...html" path="toh-6/src/app/hero-detail.component.html">
|
<code-pane title="hero-detail.comp...html" path="toh-6/src/app/hero-detail.component.html">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="hero.service.ts" path="toh-6/src/app/hero.service.ts">
|
<code-pane title="hero.service.ts" path="toh-6/src/app/hero.service.ts">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="in-memory-data.service.ts" path="toh-6/src/app/in-memory-data.service.ts">
|
<code-pane title="in-memory-data.service.ts" path="toh-6/src/app/in-memory-data.service.ts">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
@ -815,23 +884,28 @@ Here are the files you added or changed in this page.
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-tabs>
|
<code-tabs>
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="hero-search.service.ts" path="toh-6/src/app/hero-search.service.ts">
|
<code-pane title="hero-search.service.ts" path="toh-6/src/app/hero-search.service.ts">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="hero-search.component.ts" path="toh-6/src/app/hero-search.component.ts">
|
<code-pane title="hero-search.component.ts" path="toh-6/src/app/hero-search.component.ts">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="hero-search.component.html" path="toh-6/src/app/hero-search.component.html">
|
<code-pane title="hero-search.component.html" path="toh-6/src/app/hero-search.component.html">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-pane title="hero-search.component.css" path="toh-6/src/app/hero-search.component.css">
|
<code-pane title="hero-search.component.css" path="toh-6/src/app/hero-search.component.css">
|
||||||
|
|
||||||
</code-pane>
|
</code-pane>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user