docs(aio): migrate content docs from angular.io
This content was generated by a tool: https://github.com/petebacondarwin/aio-migrator
This commit is contained in:
committed by
Igor Minar
parent
c3247c64a4
commit
3e34ba01bd
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
@@ -11,7 +11,8 @@ Our components often refer to external template and style files.
|
||||
We identify those files with a URL in the `templateUrl` and `styleUrls` properties of the `@Component` metadata
|
||||
as seen here:
|
||||
|
||||
{@example 'cb-component-relative-paths/ts/app/some.component.ts' -region='absolute-config' -linenums='false' }
|
||||
|
||||
{@example 'cb-component-relative-paths/ts/src/app/some.component.ts' region='absolute-config'}
|
||||
|
||||
By default, we *must* specify the full path back to the application root.
|
||||
We call this an ***absolute path*** because it is *absolute* with respect to the application root.
|
||||
@@ -20,13 +21,14 @@ There are two problems with an *absolute path*:
|
||||
|
||||
1. We have to remember the full path back to the application root.
|
||||
|
||||
2. We have to update the URL when we move the component around in the application files structure.
|
||||
1. We have to update the URL when we move the component around in the application files structure.
|
||||
|
||||
It would be much easier to write and maintain our application components if we could specify template and style locations
|
||||
*relative* to their component class file.
|
||||
|
||||
*We can!*
|
||||
|
||||
|
||||
~~~ {.alert.is-important}
|
||||
|
||||
We can if we build our application as `commonjs` modules and load those modules
|
||||
@@ -38,27 +40,44 @@ The Angular CLI uses these technologies and defaults to the
|
||||
CLI users can skip this chapter or read on to understand
|
||||
how it works.
|
||||
|
||||
|
||||
~~~
|
||||
|
||||
|
||||
## _Component-Relative_ Paths
|
||||
|
||||
Our goal is to specify template and style URLs *relative* to their component class files,
|
||||
Our goal is to specify template and style URLs *relative* to their component class files,
|
||||
hence the term ***component-relative path***.
|
||||
|
||||
The key to success is following a convention that puts related component files in well-known locations.
|
||||
|
||||
We recommend keeping component template and component-specific style files as *siblings* of their
|
||||
companion component class files.
|
||||
Here we see the three files for `SomeComponent` sitting next to each other in the `app` folder.
|
||||
companion component class files.
|
||||
Here we see the three files for `SomeComponent` sitting next to each other in the `app` folder.
|
||||
|
||||
<aio-filetree>
|
||||
|
||||
<aio-folder>
|
||||
app
|
||||
<aio-file>
|
||||
some.component.css
|
||||
</aio-file>
|
||||
|
||||
|
||||
<aio-file>
|
||||
some.component.html
|
||||
</aio-file>
|
||||
|
||||
|
||||
<aio-file>
|
||||
some.component.ts
|
||||
</aio-file>
|
||||
|
||||
|
||||
<aio-file-tree>
|
||||
<aio-folder>app
|
||||
<aio-file>some.component.css</aio-file>
|
||||
<aio-file>some.component.html</aio-file>
|
||||
<aio-file>some.component.ts</aio-file>
|
||||
<aio-file>...</aio-file>
|
||||
</aio-folder>
|
||||
</aio-file-tree>
|
||||
|
||||
|
||||
</aio-filetree>
|
||||
|
||||
We'll have more files and folders — and greater folder depth — as our application grows.
|
||||
We'll be fine as long as the component files travel together as the inseparable siblings they are.
|
||||
@@ -68,16 +87,19 @@ We'll be fine as long as the component files travel together as the inseparable
|
||||
Having adopted this file structure convention, we can specify locations of the template and style files
|
||||
relative to the component class file simply by setting the `moduleId` property of the `@Component` metadata like this
|
||||
|
||||
{@example 'cb-component-relative-paths/ts/app/some.component.ts' -region='module-id' -linenums='false'}
|
||||
{@example 'cb-component-relative-paths/ts/src/app/some.component.ts' region='module-id'}
|
||||
|
||||
We strip the `app/` base path from the `templateUrl` and `styleUrls` and replace it with `./`.
|
||||
We strip the `src/app/` base path from the `templateUrl` and `styleUrls` and replace it with `./`.
|
||||
The result looks like this:
|
||||
|
||||
{@example 'cb-component-relative-paths/ts/app/some.component.ts' -region='relative-config' -linenums='false'}
|
||||
{@example 'cb-component-relative-paths/ts/src/app/some.component.ts' region='relative-config'}
|
||||
|
||||
|
||||
|
||||
~~~ {.alert.is-helpful}
|
||||
|
||||
Webpack users may prefer [an alternative approach](#webpack).
|
||||
Webpack users may prefer [an alternative approach](#webpack).
|
||||
|
||||
|
||||
~~~
|
||||
|
||||
@@ -87,21 +109,30 @@ The result looks like this:
|
||||
**We can see the <live-example name="cb-component-relative-paths"></live-example>**
|
||||
and download the source code from there
|
||||
or simply read the pertinent source here.
|
||||
<md-tab-group>
|
||||
|
||||
<md-tab-group>
|
||||
<md-tab label="app/some.component.ts">
|
||||
{@example 'cb-component-relative-paths/ts/app/some.component.ts'}
|
||||
<md-tab label="src/app/some.component.ts">
|
||||
{@example 'cb-component-relative-paths/ts/src/app/some.component.ts'}
|
||||
</md-tab>
|
||||
<md-tab label="app/some.component.html">
|
||||
{@example 'cb-component-relative-paths/ts/app/some.component.html'}
|
||||
|
||||
|
||||
<md-tab label="src/app/some.component.html">
|
||||
{@example 'cb-component-relative-paths/ts/src/app/some.component.html'}
|
||||
</md-tab>
|
||||
<md-tab label="app/some.component.css">
|
||||
{@example 'cb-component-relative-paths/ts/app/some.component.css'}
|
||||
|
||||
|
||||
<md-tab label="src/app/some.component.css">
|
||||
{@example 'cb-component-relative-paths/ts/src/app/some.component.css'}
|
||||
</md-tab>
|
||||
<md-tab label="app/app.component.ts">
|
||||
{@example 'cb-component-relative-paths/ts/app/app.component.ts'}
|
||||
|
||||
|
||||
<md-tab label="src/app/app.component.ts">
|
||||
{@example 'cb-component-relative-paths/ts/src/app/app.component.ts'}
|
||||
</md-tab>
|
||||
<md-tab-group>
|
||||
|
||||
|
||||
</md-tab-group>
|
||||
|
||||
|
||||
|
||||
{@a why-default}
|
||||
@@ -118,15 +149,15 @@ First, let's look at what happens if we use a relative path and omit the `module
|
||||
|
||||
Angular can't find the file so it throws an error.
|
||||
|
||||
Why can't Angular calculate the template and style URLs from the component file's location?
|
||||
Why can't Angular calculate the template and style URLs from the component file's location?
|
||||
|
||||
Because the location of the component can't be determined without the developer's help.
|
||||
Angular apps can be loaded in many ways: from individual files, from SystemJS packages, or
|
||||
from CommonJS packages, to name a few.
|
||||
We might generate modules in any of several formats.
|
||||
from CommonJS packages, to name a few.
|
||||
We might generate modules in any of several formats.
|
||||
We might not be writing modular code at all!
|
||||
|
||||
With this diversity of packaging and module load strategies,
|
||||
With this diversity of packaging and module load strategies,
|
||||
it's not possible for Angular to know with certainty where these files reside at runtime.
|
||||
|
||||
The only location Angular can be sure of is the URL of the `index.html` home page, the application root.
|
||||
@@ -142,7 +173,8 @@ the absolute URL of the component class module file.
|
||||
That knowledge enables us to tell Angular where the *component* file is
|
||||
by setting the `moduleId`:
|
||||
|
||||
{@example 'cb-component-relative-paths/ts/app/some.component.ts' -region='module-id' -linenums='false'}
|
||||
{@example 'cb-component-relative-paths/ts/src/app/some.component.ts' region='module-id'}
|
||||
|
||||
|
||||
|
||||
{@a webpack}
|
||||
@@ -153,8 +185,10 @@ Webpack developers have an alternative to `moduleId`.
|
||||
They can load templates and styles at runtime by adding `./` at the beginning of the `template` and `styles` / `styleUrls`
|
||||
properties that reference *component-relative URLS.
|
||||
|
||||
{@example 'webpack/ts/src/app/app.component.ts' --linenums='false'}
|
||||
|
||||
{@example 'webpack/ts/src/app/app.component.ts'}
|
||||
|
||||
|
||||
Webpack will do a `require` behind the scenes to load the templates and styles. Read more [here](../guide/webpack.html#highlights).
|
||||
|
||||
See the [Introduction to Webpack](../guide/webpack.html).
|
||||
See the [Introduction to Webpack](../guide/webpack.html).
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,138 @@
|
||||
@title
|
||||
Dynamic Component Loader
|
||||
|
||||
@intro
|
||||
Load components dynamically
|
||||
|
||||
@description
|
||||
Component templates are not always fixed. An application may need to load new components at runtime.
|
||||
|
||||
In this cookbook we show how to use `ComponentFactoryResolver` to add components dynamically.
|
||||
|
||||
<a id="toc"></a>## Table of contents
|
||||
|
||||
[Dynamic Component Loading](#dynamic-loading)
|
||||
|
||||
[Where to load the component](#where-to-load)
|
||||
|
||||
[Loading components](#loading-components)
|
||||
|
||||
<a id="dynamic-loading"></a>## Dynamic Component Loading
|
||||
|
||||
The following example shows how to build a dynamic ad banner.
|
||||
|
||||
The hero agency is planning an ad campaign with several different ads cycling through the banner.
|
||||
|
||||
New ad components are added frequently by several different teams. This makes it impractical to use a template with a static component structure.
|
||||
|
||||
Instead we need a way to load a new component without a fixed reference to the component in the ad banner's template.
|
||||
|
||||
Angular comes with its own API for loading components dynamically. In the following sections you will learn how to use it.
|
||||
|
||||
|
||||
<a id="where-to-load"></a>## Where to load the component
|
||||
|
||||
Before components can be added we have to define an anchor point to mark where components can be inserted dynamically.
|
||||
|
||||
The ad banner uses a helper directive called `AdDirective` to mark valid insertion points in the template.
|
||||
|
||||
|
||||
{@example 'cb-dynamic-component-loader/ts/src/app/ad.directive.ts'}
|
||||
|
||||
`AdDirective` injects `ViewContainerRef` to gain access to the view container of the element that will become the host of the dynamically added component.
|
||||
|
||||
<a id="loading-components"></a>## Loading components
|
||||
|
||||
The next step is to implement the ad banner. Most of the implementation is in `AdBannerComponent`.
|
||||
|
||||
We start by adding a `template` element with the `AdDirective` directive applied.
|
||||
|
||||
<md-tab-group>
|
||||
|
||||
<md-tab label="ad-banner.component.ts">
|
||||
{@example 'cb-dynamic-component-loader/ts/src/app/ad-banner.component.ts'}
|
||||
</md-tab>
|
||||
|
||||
|
||||
<md-tab label="ad.service.ts">
|
||||
{@example 'cb-dynamic-component-loader/ts/src/app/ad.service.ts'}
|
||||
</md-tab>
|
||||
|
||||
|
||||
<md-tab label="ad-item.ts">
|
||||
{@example 'cb-dynamic-component-loader/ts/src/app/ad-item.ts'}
|
||||
</md-tab>
|
||||
|
||||
|
||||
<md-tab label="app.module.ts">
|
||||
{@example 'cb-dynamic-component-loader/ts/src/app/app.module.ts'}
|
||||
</md-tab>
|
||||
|
||||
|
||||
<md-tab label="app.component">
|
||||
{@example 'cb-dynamic-component-loader/ts/src/app/app.component.ts'}
|
||||
</md-tab>
|
||||
|
||||
|
||||
</md-tab-group>
|
||||
|
||||
The `template` element decorated with the `ad-host` directive marks where dynamically loaded components will be added.
|
||||
|
||||
Using a `template` element is recommended since it doesn't render any additional output.
|
||||
|
||||
|
||||
{@example 'cb-dynamic-component-loader/ts/src/app/ad-banner.component.ts' region='ad-host'}
|
||||
|
||||
### Resolving Components
|
||||
|
||||
`AdBanner` takes an array of `AdItem` objects as input. `AdItem` objects specify the type of component to load and any data to bind to the component.
|
||||
|
||||
The ad components making up the ad campaign are returned from `AdService`.
|
||||
|
||||
Passing an array of components to `AdBannerComponent` allows for a dynamic list of ads without static elements in the template.
|
||||
|
||||
`AdBannerComponent` cycles through the array of `AdItems` and loads the corresponding components on an interval. Every 3 seconds a new component is loaded.
|
||||
|
||||
`ComponentFactoryResolver` is used to resolve a `ComponentFactory` for each specific component. The component factory is need to create an instance of the component.
|
||||
|
||||
`ComponentFactories` are generated by the Angular compiler.
|
||||
|
||||
Generally the compiler will generate a component factory for any component referenced in a template.
|
||||
|
||||
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.
|
||||
|
||||
|
||||
{@example 'cb-dynamic-component-loader/ts/src/app/app.module.ts' region='entry-components'}
|
||||
|
||||
Components are added to the template by calling `createComponent` on the `ViewContainerRef` reference.
|
||||
|
||||
`createComponent` returns a reference to the loaded component. The component reference can be used to pass input data or call methods to interact with the component.
|
||||
|
||||
In the Ad banner, all components implement a common `AdComponent` interface to standardize the api for passing data to the components.
|
||||
|
||||
Two sample components and the `AdComponent` interface are shown below:
|
||||
|
||||
<md-tab-group>
|
||||
|
||||
<md-tab label="hero-job-ad.component.ts">
|
||||
{@example 'cb-dynamic-component-loader/ts/src/app/hero-job-ad.component.ts'}
|
||||
</md-tab>
|
||||
|
||||
|
||||
<md-tab label="hero-profile.component.ts">
|
||||
{@example 'cb-dynamic-component-loader/ts/src/app/hero-profile.component.ts'}
|
||||
</md-tab>
|
||||
|
||||
|
||||
<md-tab label="ad.component.ts">
|
||||
{@example 'cb-dynamic-component-loader/ts/src/app/ad.component.ts'}
|
||||
</md-tab>
|
||||
|
||||
|
||||
</md-tab-group>
|
||||
|
||||
The final ad banner looks like this:
|
||||
<figure class='image-display'>
|
||||
<img src="/resources/images/cookbooks/dynamic-component-loader/ads.gif" alt="Ads"> </img>
|
||||
</figure>
|
||||
|
||||
@@ -0,0 +1,168 @@
|
||||
@title
|
||||
Dynamic Forms
|
||||
|
||||
@intro
|
||||
Render dynamic forms with FormGroup
|
||||
|
||||
@description
|
||||
We can't always justify the cost and time to build handcrafted forms,
|
||||
especially if we'll need a great number of them, they're similar to each other, and they change frequently
|
||||
to meet rapidly changing business and regulatory requirements.
|
||||
|
||||
It may be more economical to create the forms dynamically, based on metadata that describe the business object model.
|
||||
|
||||
In this cookbook we show how to use `formGroup` to dynamically render a simple form with different control types and validation.
|
||||
It's a primitive start.
|
||||
It might evolve to support a much richer variety of questions, more graceful rendering, and superior user experience.
|
||||
All such greatness has humble beginnings.
|
||||
|
||||
In our example we use a dynamic form to build an online application experience for heroes seeking employment.
|
||||
The agency is constantly tinkering with the application process.
|
||||
We can create the forms on the fly *without changing our application code*.
|
||||
<a id="toc"></a>## Table of contents
|
||||
|
||||
[Bootstrap](#bootstrap)
|
||||
|
||||
[Question Model](#object-model)
|
||||
|
||||
[Form Component](#form-component)
|
||||
|
||||
[Questionnaire Metadata](#questionnaire-metadata)
|
||||
|
||||
[Dynamic Template](#dynamic-template)
|
||||
**See the <live-example name="cb-dynamic-form"></live-example>**.
|
||||
|
||||
<a id="bootstrap"></a>## Bootstrap
|
||||
|
||||
We start by creating an `NgModule` called `AppModule`.
|
||||
|
||||
In our example we will be using Reactive Forms.
|
||||
|
||||
Reactive Forms belongs to a different `NgModule` called `ReactiveFormsModule`, so in order to access any Reactive Forms directives, we have to import `ReactiveFormsModule` from the `@angular/forms` library.
|
||||
|
||||
We bootstrap our `AppModule` in main.ts.
|
||||
|
||||
<md-tab-group>
|
||||
|
||||
<md-tab label="app.module.ts">
|
||||
{@example 'cb-dynamic-form/ts/src/app/app.module.ts'}
|
||||
</md-tab>
|
||||
|
||||
|
||||
<md-tab label="main.ts">
|
||||
{@example 'cb-dynamic-form/ts/src/main.ts'}
|
||||
</md-tab>
|
||||
|
||||
|
||||
</md-tab-group>
|
||||
|
||||
|
||||
<a id="object-model"></a>## Question Model
|
||||
|
||||
The next step is to define an object model that can describe all scenarios needed by the form functionality.
|
||||
The hero application process involves a form with a lot of questions.
|
||||
The "question" is the most fundamental object in the model.
|
||||
|
||||
We have created `QuestionBase` as the most fundamental question class.
|
||||
|
||||
|
||||
{@example 'cb-dynamic-form/ts/src/app/question-base.ts'}
|
||||
|
||||
From this base we derived two new classes in `TextboxQuestion` and `DropdownQuestion` that represent Textbox and Dropdown questions.
|
||||
The idea is that the form will be bound to specific question types and render the appropriate controls dynamically.
|
||||
|
||||
`TextboxQuestion` supports multiple html5 types like text, email, url etc via the `type` property.
|
||||
|
||||
|
||||
{@example 'cb-dynamic-form/ts/src/app/question-textbox.ts'}
|
||||
|
||||
`DropdownQuestion` presents a list of choices in a select box.
|
||||
|
||||
|
||||
{@example 'cb-dynamic-form/ts/src/app/question-dropdown.ts'}
|
||||
|
||||
Next we have defined `QuestionControlService`, a simple service for transforming our questions to a `FormGroup`.
|
||||
In a nutshell, the form group consumes the metadata from the question model and allows us to specify default values and validation rules.
|
||||
|
||||
|
||||
{@example 'cb-dynamic-form/ts/src/app/question-control.service.ts'}
|
||||
|
||||
<a id="form-component"></a>## Question form components
|
||||
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.
|
||||
<md-tab-group>
|
||||
|
||||
<md-tab label="dynamic-form.component.html">
|
||||
{@example 'cb-dynamic-form/ts/src/app/dynamic-form.component.html'}
|
||||
</md-tab>
|
||||
|
||||
|
||||
<md-tab label="dynamic-form.component.ts">
|
||||
{@example 'cb-dynamic-form/ts/src/app/dynamic-form.component.ts'}
|
||||
</md-tab>
|
||||
|
||||
|
||||
</md-tab-group>
|
||||
|
||||
It presents a list of questions, each question bound to a `<df-question>` component element.
|
||||
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.
|
||||
|
||||
<md-tab-group>
|
||||
|
||||
<md-tab label="dynamic-form-question.component.html">
|
||||
{@example 'cb-dynamic-form/ts/src/app/dynamic-form-question.component.html'}
|
||||
</md-tab>
|
||||
|
||||
|
||||
<md-tab label="dynamic-form-question.component.ts">
|
||||
{@example 'cb-dynamic-form/ts/src/app/dynamic-form-question.component.ts'}
|
||||
</md-tab>
|
||||
|
||||
|
||||
</md-tab-group>
|
||||
|
||||
Notice this component can present any type of question in our model.
|
||||
We only have two types of questions at this point but we can imagine many more.
|
||||
The `ngSwitch` determines which type of question to display.
|
||||
|
||||
In both components we're relying on Angular's **formGroup** to connect the template HTML to the
|
||||
underlying control objects, populated from the question model with display and validation rules.
|
||||
|
||||
`formControlName` and `formGroup` are directives defined in `ReactiveFormsModule`. Our templates can can access these directives directly since we imported `ReactiveFormsModule` from `AppModule`.
|
||||
<a id="questionnaire-metadata"></a>## Questionnaire data`DynamicFormComponent` expects the list of questions in the form of an array bound to `@Input() questions`.
|
||||
|
||||
The set of questions we have defined for the job application is returned from the `QuestionService`.
|
||||
In a real app we'd retrieve these questions from storage.
|
||||
|
||||
The key point is that we control the hero job application questions entirely through the objects returned from `QuestionService`.
|
||||
Questionnaire maintenance is a simple matter of adding, updating, and removing objects from the `questions` array.
|
||||
|
||||
|
||||
{@example 'cb-dynamic-form/ts/src/app/question.service.ts'}
|
||||
|
||||
Finally, we display an instance of the form in the `AppComponent` shell.
|
||||
|
||||
|
||||
{@example 'cb-dynamic-form/ts/src/app/app.component.ts'}
|
||||
|
||||
<a id="dynamic-template"></a>## Dynamic Template
|
||||
Although in this example we're modelling a job application for heroes, there are no references to any specific hero question
|
||||
outside the objects returned by `QuestionService`.
|
||||
|
||||
This is very important since it allows us to repurpose the components for any type of survey
|
||||
as long as it's compatible with our *question* object model.
|
||||
The key is the dynamic data binding of metadata used to render the form
|
||||
without making any hardcoded assumptions about specific questions.
|
||||
In addition to control metadata, we are also adding validation dynamically.
|
||||
|
||||
The *Save* button is disabled until the form is in a valid state.
|
||||
When the form is valid, we can click *Save* and the app renders the current form values as JSON.
|
||||
This proves that any user input is bound back to the data model.
|
||||
Saving and retrieving the data is an exercise for another time.
|
||||
The final form looks like this:
|
||||
<figure class='image-display'>
|
||||
<img src="/resources/images/cookbooks/dynamic-form/dynamic-form.png" alt="Dynamic-Form"> </img>
|
||||
</figure>
|
||||
|
||||
[Back to top](#top)
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,28 @@
|
||||
@title
|
||||
Cookbook
|
||||
|
||||
@intro
|
||||
A collection of recipes for common Angular application scenarios
|
||||
|
||||
@description
|
||||
The *Cookbook* offers answers to common implementation questions.
|
||||
|
||||
Each cookbook chapter is a collection of recipes focused on a particular Angular feature or application challenge
|
||||
such as data binding, cross-component interaction, and communicating with a remote server via HTTP.
|
||||
|
||||
The cookbook is just getting started. Many more recipes are on the way.
|
||||
Each cookbook chapter links to a live sample with every recipe included.
|
||||
|
||||
Recipes are deliberately brief and code-centric.
|
||||
Each recipe links to a chapter of the Developer Guide or the API Guide
|
||||
where you can learn more about the purpose, context, and design choices behind the code snippets.
|
||||
|
||||
## Feedback
|
||||
|
||||
The cookbook is a perpetual *work-in-progress*.
|
||||
We welcome feedback! Leave a comment by clicking the icon in upper right corner of the banner.
|
||||
|
||||
Post *documentation* issues and pull requests on the
|
||||
[angular.io](https://github.com/angular/angular.io) github repository.
|
||||
|
||||
Post issues with *Angular itself* to the [angular](https://github.com/angular/angular) github repository.
|
||||
@@ -0,0 +1,103 @@
|
||||
@title
|
||||
Set the Document Title
|
||||
|
||||
@intro
|
||||
Setting the document or window title using the Title service.
|
||||
|
||||
@description
|
||||
|
||||
|
||||
{@a top}
|
||||
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>**.
|
||||
|
||||
<table>
|
||||
|
||||
<tr>
|
||||
|
||||
<td>
|
||||
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,
|
||||
then pop out the preview window by clicking the blue 'X' button in the upper right corner.
|
||||
</td>
|
||||
|
||||
|
||||
<td>
|
||||
<img src='/resources/images/devguide/plunker-switch-to-editor-button.png' width="200px" height="70px" alt="pop out the window" align="right"> </img> <br> </br> <img src='/resources/images/devguide/plunker-separate-window-button.png' width="200px" height="47px" alt="pop out the window" align="right"> </img>
|
||||
</td>
|
||||
|
||||
|
||||
</tr>
|
||||
|
||||
|
||||
</table>
|
||||
|
||||
## The problem with *<title>*
|
||||
|
||||
The obvious approach is to bind a property of the component to the HTML `<title>` like this:
|
||||
<code-example format=''>
|
||||
<title>{{This_Does_Not_Work}}</title>
|
||||
</code-example>
|
||||
|
||||
Sorry but that won't work.
|
||||
The root component of our application is an element contained within the `<body>` tag.
|
||||
The HTML `<title>` is in the document `<head>`, outside the body, making it inaccessible to Angular data binding.
|
||||
|
||||
We could grab the browser `document` object and set the title manually.
|
||||
That's dirty and undermines our chances of running the app outside of a browser someday.
|
||||
Running your app outside a browser means that you can take advantage of server-side
|
||||
pre-rendering for near-instant first app render times and for SEO. It means you could run from
|
||||
inside a Web Worker to improve your app's responsiveness by using multiple threads. And it
|
||||
means that you could run your app inside Electron.js or Windows Universal to deliver it to the desktop.
|
||||
## Use the *Title* service
|
||||
Fortunately, Angular bridges the gap by providing a `Title` service as part of the *Browser platform*.
|
||||
The [Title](../api/platform-browser/index/Title-class.html) service is a simple class that provides an API
|
||||
for getting and setting the current HTML document title:
|
||||
|
||||
* `getTitle() : string` — Gets the title of the current HTML document.
|
||||
* `setTitle( newTitle : string )` — Sets the title of the current HTML document.
|
||||
|
||||
Let's inject the `Title` service into the root `AppComponent` and expose a bindable `setTitle` method that calls it:
|
||||
|
||||
|
||||
{@example 'cb-set-document-title/ts/src/app/app.component.ts' region='class'}
|
||||
|
||||
We bind that method to three anchor tags and, voilà!
|
||||
<figure class='image-display'>
|
||||
<img src="/resources/images/cookbooks/set-document-title/set-title-anim.gif" alt="Set title"> </img>
|
||||
</figure>
|
||||
|
||||
Here's the complete solution
|
||||
|
||||
<md-tab-group>
|
||||
|
||||
<md-tab label="src/main.ts">
|
||||
{@example 'cb-set-document-title/ts/src/main.ts'}
|
||||
</md-tab>
|
||||
|
||||
|
||||
<md-tab label="src/app/app.module.ts">
|
||||
{@example 'cb-set-document-title/ts/src/app/app.module.ts'}
|
||||
</md-tab>
|
||||
|
||||
|
||||
<md-tab label="src/app/app.component.ts">
|
||||
{@example 'cb-set-document-title/ts/src/app/app.component.ts'}
|
||||
</md-tab>
|
||||
|
||||
|
||||
</md-tab-group>
|
||||
|
||||
|
||||
## Why we provide the *Title* service in *bootstrap*
|
||||
|
||||
We generally recommended providing application-wide services in the root application component, `AppComponent`.
|
||||
|
||||
Here we recommend registering the title service during bootstrapping,
|
||||
a location we reserve for configuring the runtime Angular environment.
|
||||
|
||||
That's exactly what we're doing.
|
||||
The `Title` service is part of the Angular *browser platform*.
|
||||
If we bootstrap our application into a different platform,
|
||||
we'll have to provide a different `Title` service that understands the concept of a "document title" for that specific platform.
|
||||
Ideally the application itself neither knows nor cares about the runtime environment.[Back to top](#top)
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,171 @@
|
||||
@title
|
||||
Visual Studio 2015 QuickStart
|
||||
|
||||
@intro
|
||||
Use Visual Studio 2015 with the QuickStart files
|
||||
|
||||
@description
|
||||
<a id="top"></a>Some developers prefer Visual Studio as their Integrated Development Environment (IDE).
|
||||
|
||||
This cookbook describes the steps required to set up and use the
|
||||
Angular QuickStart files in **Visual Studio 2015 within an ASP.NET 4.x project**.
|
||||
There is no *live example* for this cookbook because it describes Visual Studio, not the application.
|
||||
|
||||
<a id="asp-net-4"></a>## ASP.NET 4.x Project
|
||||
|
||||
This cookbook explains how to set up the QuickStart files with an **ASP.NET 4.x project** in
|
||||
Visual Studio 2015.
|
||||
If you prefer a `File | New Project` experience and are using **ASP.NET Core**,
|
||||
then consider the _experimental_
|
||||
<a href="http://blog.stevensanderson.com/2016/10/04/angular2-template-for-visual-studio/" target="_blank">ASP.NET Core + Angular template for Visual Studio 2015</a>.
|
||||
Note that the resulting code does not map to the docs. Adjust accordingly.
|
||||
The steps are as follows:
|
||||
|
||||
- [Prerequisite](#prereq1): Install Node.js
|
||||
- [Prerequisite](#prereq2): Install Visual Studio 2015 Update 3
|
||||
- [Prerequisite](#prereq3): Configure External Web tools
|
||||
- [Prerequisite](#prereq4): Install TypeScript 2 for Visual Studio 2015
|
||||
- [Step 1](#download): Download the QuickStart files
|
||||
- [Step 2](#create-project): Create the Visual Studio ASP.NET project
|
||||
- [Step 3](#copy): Copy the QuickStart files into the ASP.NET project folder
|
||||
- [Step 4](#restore): Restore required packages
|
||||
- [Step 5](#build-and-run): Build and run the app
|
||||
|
||||
|
||||
<h2 id='prereq1'>
|
||||
Prerequisite: Node.js
|
||||
</h2>
|
||||
|
||||
Install **[Node.js® and npm](https://nodejs.org/en/download/)**
|
||||
if they are not already on your machine.
|
||||
**Verify that you are running node version `4.6.x` or greater, and npm `3.x.x` or greater**
|
||||
by running `node -v` and `npm -v` in a terminal/console window.
|
||||
Older versions produce errors.
|
||||
|
||||
|
||||
<h2 id='prereq2'>
|
||||
Prerequisite: Visual Studio 2015 Update 3
|
||||
</h2>
|
||||
|
||||
The minimum requirement for developing Angular applications with Visual Studio is Update 3.
|
||||
Earlier versions do not follow the best practices for developing applications with TypeScript.
|
||||
To view your version of Visual Studio 2015, go to `Help | About Visual Studio`.
|
||||
|
||||
If you don't have it, install **[Visual Studio 2015 Update 3](https://www.visualstudio.com/en-us/news/releasenotes/vs2015-update3-vs)**.
|
||||
Or use `Tools | Extensions and Updates` to update to Update 3 directly from Visual Studio 2015.
|
||||
|
||||
|
||||
<h2 id='prereq3'>
|
||||
Prerequisite: Configure External Web tools
|
||||
</h2>
|
||||
|
||||
Configure Visual Studio to use the global external web tools instead of the tools that ship with Visual Studio:
|
||||
|
||||
* Open the **Options** dialog with `Tools` | `Options`
|
||||
* In the tree on the left, select `Projects and Solutions` | `External Web Tools`.
|
||||
* On the right, move the `$(PATH)` entry above the `$(DevEnvDir`) entries. This tells Visual Studio to
|
||||
use the external tools (such as npm) found in the global path before using its own version of the external tools.
|
||||
* Click OK to close the dialog.
|
||||
* Restart Visual Studio for this change to take effect.
|
||||
|
||||
Visual Studio will now look first for external tools in the current workspace and
|
||||
if not found then look in the global path and if it is not found there, Visual Studio
|
||||
will use its own versions of the tools.
|
||||
|
||||
|
||||
<h2 id='prereq4'>
|
||||
Prerequisite: Install TypeScript 2 for Visual Studio 2015
|
||||
</h2>
|
||||
|
||||
While Visual Studio Update 3 ships with TypeScript support out of the box, it currently doesn’t ship with TypeScript 2,
|
||||
which you need to develop Angular applications.
|
||||
|
||||
To install TypeScript 2:
|
||||
* Download and install **[TypeScript 2.0 for Visual Studio 2015](http://download.microsoft.com/download/6/D/8/6D8381B0-03C1-4BD2-AE65-30FF0A4C62DA/TS2.0.3-TS-release20-nightly-20160921.1/TypeScript_Dev14Full.exe)**
|
||||
* OR install it with npm: `npm install -g [email protected]`.
|
||||
|
||||
You can find out more about TypeScript 2 support in Visual studio **[here](https://blogs.msdn.microsoft.com/typescript/2016/09/22/announcing-typescript-2-0/)**
|
||||
|
||||
At this point, Visual Studio is ready. It’s a good idea to close Visual Studio and
|
||||
restart it to make sure everything is clean.
|
||||
|
||||
|
||||
<h2 id='download'>
|
||||
Step 1: Download the QuickStart files
|
||||
</h2>
|
||||
|
||||
[Download the QuickStart source](https://github.com/angular/quickstart)
|
||||
from github. If you downloaded as a zip file, extract the files.
|
||||
|
||||
|
||||
<h2 id='create-project'>
|
||||
Step 2: Create the Visual Studio ASP.NET project
|
||||
</h2>
|
||||
|
||||
Create the ASP.NET 4.x project in the usual way as follows:
|
||||
|
||||
* In Visual Studio, select `File` | `New` | `Project` from the menu.
|
||||
* In the template tree, select `Templates` | `Visual C#` (or `Visual Basic`) | `Web`.
|
||||
* Select the `ASP.NET Web Application` template, give the project a name, and click OK.
|
||||
* Select the desired ASP.NET 4.5.2 template and click OK.
|
||||
|
||||
In this cookbook we'll select the `Empty` template with no added folders,
|
||||
no authentication and no hosting. Pick the template and options appropriate for your project.
|
||||
|
||||
|
||||
<h2 id='copy'>
|
||||
Step 3: Copy the QuickStart files into the ASP.NET project folder
|
||||
</h2>
|
||||
|
||||
Copy the QuickStart files we downloaded from github into the folder containing the `.csproj` file.
|
||||
Include the files in the Visual Studio project as follows:
|
||||
|
||||
* Click the `Show All Files` button in Solution Explorer to reveal all of the hidden files in the project.
|
||||
* Right-click on each folder/file to be included in the project and select `Include in Project`.
|
||||
Minimally, include the following folder/files:
|
||||
* app folder (answer *No* if asked to search for TypeScript Typings)
|
||||
* styles.css
|
||||
* index.html
|
||||
* package.json
|
||||
* tsconfig.json
|
||||
|
||||
|
||||
<h2 id='restore'>
|
||||
Step 4: Restore the required packages
|
||||
</h2>
|
||||
|
||||
Restore the packages required for an Angular application as follows:
|
||||
|
||||
* Right-click on the `package.json` file in Solution Explorer and select `Restore Packages`.
|
||||
<br>This uses `npm` to install all of the packages defined in the `package.json` file.
|
||||
It may take some time.
|
||||
* If desired, open the Output window (`View` | `Output`) to watch the npm commands execute.
|
||||
* Ignore the warnings.
|
||||
* When the restore is finished, a message should say: `npm command completed with exit code 0`.
|
||||
* Click the `Refresh` icon in Solution Explorer.
|
||||
* **Do not** include the `node_modules` folder in the project. Let it be a hidden project folder.
|
||||
|
||||
|
||||
<h2 id='build-and-run'>
|
||||
Step 5: Build and run the app
|
||||
</h2>
|
||||
|
||||
First, ensure that `index.html` is set as the start page.
|
||||
Right-click `index.html` in Solution Explorer and select option `Set As Start Page`.
|
||||
|
||||
Build and launch the app with debugger by clicking the **Run** button or press `F5`.
|
||||
It's faster to run without the debugger by pressing `Ctrl-F5`.The default browser opens and displays the QuickStart sample application.
|
||||
|
||||
Try editing any of the project files. *Save* and refresh the browser to
|
||||
see the changes.
|
||||
|
||||
|
||||
<h2 id='routing'>
|
||||
Note on Routing Applications
|
||||
</h2>
|
||||
|
||||
If this application used the Angular router, a browser refresh could return a *404 - Page Not Found*.
|
||||
Look at the address bar. Does it contain a navigation url (a "deep link") ... any path other than `/` or `/index.html`?
|
||||
|
||||
You'll have to configure the server to return `index.html` for these requests.
|
||||
Until you do, remove the navigation path and refresh again.
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,157 @@
|
||||
@title
|
||||
AppModule: the root module
|
||||
|
||||
@intro
|
||||
Tell Angular how to construct and bootstrap the app in the root "AppModule".
|
||||
|
||||
@description
|
||||
An Angular module class describes how the application parts fit together.
|
||||
Every application has at least one Angular module, the _root_ module
|
||||
that you [bootstrap](#main) to launch the application.
|
||||
You can call it anything you want. The conventional name is `AppModule`.
|
||||
|
||||
The [setup](setup.html) instructions produce a new project with the following minimal `AppModule`.
|
||||
You'll evolve this module as your application grows.
|
||||
|
||||
|
||||
{@example 'setup/ts/src/app/app.module.ts'}
|
||||
|
||||
After the `import` statements, you come to a class adorned with the
|
||||
**`@NgModule`** [_decorator_](glossary.html#decorator '"Decorator" explained').
|
||||
|
||||
The `@NgModule` decorator identifies `AppModule` as an Angular module class (also called an `NgModule` class).
|
||||
`@NgModule` takes a _metadata_ object that tells Angular how to compile and launch the application.
|
||||
|
||||
* **_imports_** — the `BrowserModule` that this and every application needs to run in a browser.
|
||||
* **_declarations_** — the application's lone component, which is also ...
|
||||
* **_bootstrap_** — the _root_ component that Angular creates and inserts into the `index.html` host web page.
|
||||
|
||||
The [Angular Modules (NgModule)](ngmodule.html) guide dives deeply into the details of Angular modules.
|
||||
All you need to know at the moment is a few basics about these three properties.
|
||||
|
||||
|
||||
{@a imports}
|
||||
### The _imports_ array
|
||||
|
||||
Angular modules are a way to consolidate features that belong together into discrete units.
|
||||
Many features of Angular itself are organized as Angular modules.
|
||||
HTTP services are in the `HttpModule`. The router is in the `RouterModule`.
|
||||
Eventually you may create a feature module.
|
||||
|
||||
Add a module to the `imports` array when the application requires its features.
|
||||
|
||||
_This_ application, like most applications, executes in a browser.
|
||||
Every application that executes in a browser needs the `BrowserModule` from `@angular/platform-browser`.
|
||||
So every such application includes the `BrowserModule` in its _root_ `AppModule`'s `imports` array.
|
||||
Other guide and cookbook pages will tell you when you need to add additional modules to this array.
|
||||
|
||||
|
||||
~~~ {.alert.is-important}
|
||||
|
||||
**Only `NgModule` classes** go in the `imports` array. Do not put any other kind of class in `imports`.
|
||||
|
||||
|
||||
~~~
|
||||
|
||||
|
||||
The `import` statements at the top of the file and the Angular module's `imports` array
|
||||
are unrelated and have completely different jobs.
|
||||
|
||||
The _JavaScript_ `import` statements give you access to symbols _exported_ by other files
|
||||
so you can reference them within _this_ file.
|
||||
You add `import` statements to almost every application file.
|
||||
They have nothing to do with Angular and Angular knows nothing about them.
|
||||
|
||||
The _module's_ `imports` array appears _exclusively_ in the `@NgModule` metadata object.
|
||||
It tells Angular about specific _other_ Angular modules — all of them classes decorated with `@NgModule` —
|
||||
that the application needs to function properly.
|
||||
|
||||
{@a declarations}
|
||||
### The _declarations_ array
|
||||
|
||||
You tell Angular which components belong to the `AppModule` by listing it in the module's `declarations` array.
|
||||
As you create more components, you'll add them to `declarations`.
|
||||
|
||||
You must declare _every_ component in an `NgModule` class.
|
||||
If you use a component without declaring it, you'll see a clear error message in the browser console.
|
||||
|
||||
You'll learn to create two other kinds of classes —
|
||||
[directives](attribute-directives.html) and [pipes](pipes.html) —
|
||||
that you must also add to the `declarations` array.
|
||||
|
||||
|
||||
~~~ {.alert.is-important}
|
||||
|
||||
**Only _declarables_** — _components_, _directives_ and _pipes_ — belong in the `declarations` array.
|
||||
Do not put any other kind of class in `declarations`; _not_ `NgModule` classes, _not_ service classes, _not_ model classes.
|
||||
|
||||
|
||||
~~~
|
||||
|
||||
|
||||
|
||||
{@a bootstrap-array}
|
||||
### The _bootstrap_ array
|
||||
|
||||
You launch the application by [_bootstrapping_](#main) the root `AppModule`.
|
||||
Among other things, the _bootstrapping_ process creates the component(s) listed in the `bootstrap` array
|
||||
and inserts each one into the browser DOM.
|
||||
|
||||
Each bootstrapped component is the base of its own tree of components.
|
||||
Inserting a bootstrapped component usually triggers a cascade of component creations that fill out that tree.
|
||||
|
||||
While you can put more than one component tree on a host web page, that's not typical.
|
||||
Most applications have only one component tree and they bootstrap a single _root_ component.
|
||||
|
||||
You can call the one _root_ component anything you want but most developers call it `AppComponent`.
|
||||
|
||||
Which brings us to the _bootstrapping_ process itself.
|
||||
|
||||
|
||||
{@a main}
|
||||
|
||||
<l-main-section>
|
||||
|
||||
</l-main-section>
|
||||
|
||||
## Bootstrap in _main.ts_
|
||||
|
||||
There are many ways to bootstrap an application.
|
||||
The variations depend upon how you want to compile the application and where you want to run it.
|
||||
|
||||
In the beginning, you will compile the application dynamically with the _Just-in-Time (JIT)_ compiler
|
||||
and you'll run it in a browser. You can learn about other options later.
|
||||
|
||||
The recommended place to bootstrap a JIT-compiled browser application is in a separate file
|
||||
in the `src` folder named `src/main.ts`
|
||||
|
||||
{@example 'setup/ts/src/main.ts'}
|
||||
|
||||
This code creates a browser platform for dynamic (JIT) compilation and
|
||||
bootstraps the `AppModule` described above.
|
||||
|
||||
The _bootstrapping_ process sets up the execution environment,
|
||||
digs the _root_ `AppComponent` out of the module's `bootstrap` array,
|
||||
creates an instance of the component and inserts it within the element tag identified by the component's `selector`.
|
||||
|
||||
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 ...
|
||||
|
||||
{@example 'setup/ts/src/index.html' region='my-app'}
|
||||
|
||||
... and displays the `AppComponent` there.
|
||||
|
||||
This file is very stable. Once you've set it up, you may never change it again.
|
||||
|
||||
<l-main-section>
|
||||
|
||||
</l-main-section>
|
||||
|
||||
## More about Angular Modules
|
||||
|
||||
Your initial app has only a single module, the _root_ module.
|
||||
As your app grows, you'll consider subdividing it into multiple "feature" modules,
|
||||
so of which can be loaded later ("lazy loaded") if and when the user chooses
|
||||
to visit those features.
|
||||
|
||||
When you're ready to explore these possibilities, visit the [Angular Modules (NgModule)](ngmodule.html) guide.
|
||||
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
@@ -0,0 +1,187 @@
|
||||
@title
|
||||
Change Log
|
||||
|
||||
@intro
|
||||
An annotated history of recent documentation improvements.
|
||||
|
||||
@description
|
||||
The Angular documentation is a living document with continuous improvements.
|
||||
This log calls attention to recent significant changes.
|
||||
|
||||
## Template Syntax/Structural Directives: refreshed (2017-02-06)
|
||||
The [_Template-Syntax_](template-syntax.html) and [_Structural Directives_](structural-directives.html)
|
||||
guides were significantly revised for clarity, accuracy, and current recommended practices.
|
||||
Discusses `<ng-container>`.
|
||||
Revised samples are more clear and cover all topics discussed.
|
||||
|
||||
## NEW: Samples re-structured with `src/` folder (2017-02-02)
|
||||
All documentation samples have been realigned with the default folder structure of the angular-cli.
|
||||
That's a step along the road to basing our sample in the angular-cli.
|
||||
But it's also good in its own right.
|
||||
It helps clearly separate app code from setup and configuration files.
|
||||
|
||||
We've updated all samples with an `src/` folder at the project root.
|
||||
The former `app/` folder moves under `src/`.
|
||||
Read about moving your existing project to this structure in
|
||||
<a href="https://github.com/angular/quickstart#updating-to-a-newer-version-of-the-quickstart-repo" target="_blank" target="Migrating samples/quickstart app to the src folder">
|
||||
the QuickStart repo update instructions</a>.
|
||||
|
||||
Notably:
|
||||
* `app/main.ts` moved to `src/main.ts`.
|
||||
* `app/` moved to `src/app/`.
|
||||
* `index.html`, `styles.css` and `tsconfig.json` moved inside `src/`.
|
||||
* `systemjs.config.js` now imports `main.js` instead of `app`.
|
||||
* Added `lite-server` configuration (`bs-config.json`) to serve `src/`.
|
||||
|
||||
## NEW: Reactive Forms guide (2017-01-31)
|
||||
The new [**Reactive Forms**](reactive-forms.html) guide explains how and why to build a "reactive form".
|
||||
"Reactive Forms" are the code-based counterpart to the declarative "Template Driven" forms approach
|
||||
introduced in the [Forms](forms.html) guide.
|
||||
Check it out before you decide how to add forms to your app.
|
||||
Remember also that you can use both techniques in the same app,
|
||||
choosing the approach that best fits each scenario.
|
||||
|
||||
## NEW: Deployment guide (2017-01-30)
|
||||
The new [Deployment](deployment.html) guide describes techniques for putting your application on a server.
|
||||
It includes important advice on optimizing for production.
|
||||
|
||||
## Hierarchical Dependency Injection: refreshed (2017-01-13)
|
||||
[Hierarchical Dependency Injection](hierarchical-dependency-injection.html) guide significantly revised.
|
||||
Closes issue #3086
|
||||
Revised samples are more clear and cover all topics discussed.
|
||||
|
||||
## Miscellaneous (2017-01-05)
|
||||
* [Setup](setup.html) guide:
|
||||
added (optional) instructions on how to remove _non-essential_ files.
|
||||
* No longer consolidate RxJS operator imports in `rxjs-extensions` file; each file should import what it needs.
|
||||
* All samples prepend template/style URLS URLs w/ `./` ... and so should you.
|
||||
* [Style Guide](style-guide.html): copy edits and revised rules.
|
||||
|
||||
## Router: more detail (2016-12-21)
|
||||
Added more information to the [Router](router.html) guide
|
||||
including sections named outlets, wildcard routes, and preload strategies.
|
||||
|
||||
## Http: how to set default request headers (and other request options) (2016-12-14)
|
||||
Added section on how to set default request headers (and other request options) to
|
||||
[Http](server-communication.html#override-default-request-options) guide.
|
||||
|
||||
## Testing: added component test plunkers (2016-12-02)
|
||||
Added two plunkers that each test _one simple component_ so you can write a component test plunker of your own: <live-example name="setup" plnkr="quickstart-specs">one</live-example> for the QuickStart seed's `AppComponent` and <live-example name="testing" plnkr="banner-specs">another</live-example> for the Testing guide's `BannerComponent`.
|
||||
Linked to these plunkers in [Testing](testing.html#live-examples) and [Setup anatomy](setup-systemjs-anatomy) guides.
|
||||
|
||||
## Internationalization: pluralization and _select_ (2016-11-30)
|
||||
The [Internationalization (i18n)](../cookbook/i18n.html) guide explains how to handle pluralization and
|
||||
translation of alternative texts with `select`.
|
||||
The sample demonstrates these features too.
|
||||
|
||||
## Testing: karma file updates (2016-11-30)
|
||||
* karma.config + karma-test-shim can handle multiple spec source paths;
|
||||
see quickstart issue: [angular/quickstart#294](https://github.com/angular/quickstart/issues/294)
|
||||
* Displays Jasmine Runner output in the karma-launched browser
|
||||
|
||||
## QuickStart Rewrite (2016-11-18)
|
||||
The QuickStart is completely rewritten so that it actually is quick.
|
||||
It references a minimal "Hello Angular" app running in Plunker.
|
||||
The new [Setup](setup.html) page tells you how to install a local development environment
|
||||
by downloading (or cloning) the QuickStart github repository.
|
||||
You are no longer asked to copy-and-paste code into setup files that were not explained anyway.
|
||||
|
||||
## Sync with Angular v.2.2.0 (2016-11-14)
|
||||
Docs and code samples updated and tested with Angular v.2.2.0
|
||||
|
||||
## UPDATE: NgUpgrade Guide for the AOT friendly _upgrade/static_ module (2016-11-14)
|
||||
The updated [NgUpgrade Guide](upgrade.html) guide covers the
|
||||
new AOT friendly `upgrade/static` module
|
||||
released in v.2.2.0, which is the recommended
|
||||
facility for migrating from AngularJS to Angular.
|
||||
The documentation for the version prior to v.2.2.0 has been removed.
|
||||
|
||||
## ES6 described in "TypeScript to JavaScript" (2016-11-14)
|
||||
The updated "[TypeScript to JavaScript](../cookbook/ts-to-js.html)" cookbook
|
||||
now explains how to write apps in ES6/7
|
||||
by translating the common idioms in the TypeScript documentation examples
|
||||
(and elsewhere on the web) to ES6/7 and ES5.
|
||||
|
||||
## Sync with Angular v.2.1.1 (2016-10-21)
|
||||
Docs and code samples updated and tested with Angular v.2.1.0
|
||||
|
||||
## npm _@types_ packages replace _typings_ (2016-10-20)
|
||||
Documentation samples now get TypeScript type information for 3rd party libraries
|
||||
from npm `@types` packages rather than with the _typings_ tooling.
|
||||
The `typings.json` file is gone.
|
||||
|
||||
The "[AngularJS Upgrade](upgrade.html)" guide reflects this change.
|
||||
The `package.json` installs `@types/angular` and several `@types/angular-...`
|
||||
packages in support of upgrade; these are not needed for pure Angular development.
|
||||
|
||||
## "Template Syntax" explains two-way data binding syntax (2016-10-20)
|
||||
Demonstrates how to two-way data bind to a custom Angular component and
|
||||
re-explains `[(ngModel)]` in terms of the basic `[()]` syntax.
|
||||
|
||||
## BREAKING CHANGE: `in-memory-web-api` (v.0.1.11) delivered as esm umd (2016-10-19)
|
||||
This change supports ES6 developers and aligns better with typical Angular libraries.
|
||||
It does not affect the module's API but it does affect how you load and import it.
|
||||
See the <a href="https://github.com/angular/in-memory-web-api/blob/master/CHANGELOG.md#0113-2016-10-20" target="_blank">change note</a>
|
||||
in the `in-memory-web-api` repo.
|
||||
|
||||
## "Router" _preload_ syntax and _:enter_/_:leave_ animations (2016-10-19)
|
||||
The router can lazily _preload_ modules _after_ the app starts and
|
||||
_before_ the user navigates to them for improved perceived performance.
|
||||
|
||||
New `:enter` and `:leave` aliases make animation more natural.
|
||||
|
||||
## Sync with Angular v.2.1.0 (2016-10-12)
|
||||
Docs and code samples updated and tested with Angular v.2.1.0
|
||||
|
||||
## NEW "Ahead of time (AOT) Compilation" cookbook (2016-10-11)
|
||||
The NEW [Ahead of time (AOT) Compilation](../cookbook/aot-compiler.html) cookbook
|
||||
explains what AOT compilation is and why you'd want it.
|
||||
It demonstrates the basics with a QuickStart app
|
||||
followed by the more advanced considerations of compiling and bundling the Tour of Heroes.
|
||||
|
||||
## Sync with Angular v.2.0.2 (2016-10-6)
|
||||
Docs and code samples updated and tested with Angular v.2.0.2
|
||||
|
||||
## "Routing and Navigation" guide with the _Router Module_ (2016-10-5)
|
||||
The [Routing and Navigation](router.html) guide now locates route configuration
|
||||
in a _Routing Module_.
|
||||
The _Routing Module_ replaces the previous _routing object_ involving the `ModuleWithProviders`.
|
||||
|
||||
All guided samples with routing use the _Routing Module_ and prose content has been updated,
|
||||
most conspicuously in the
|
||||
[NgModule](ngmodule.html) guide and [NgModule FAQ](../cookbook/ngmodule-faq.html) cookbook.
|
||||
|
||||
## New "Internationalization" Cookbook (2016-09-30)
|
||||
|
||||
Added a new [Internationalization (i18n)](../cookbook/i18n.html) cookbook that shows how
|
||||
to use Angular "i18n" facilities to translate template text into multiple languages.
|
||||
|
||||
## "angular-in-memory-web-api" package rename (2016-09-27)
|
||||
|
||||
Many samples use the `angular-in-memory-web-api` to simulate a remote server.
|
||||
This library is also useful to you during early development before you have a server to talk to.
|
||||
|
||||
The package name was changed from "angular2-in-memory-web-api" which is still frozen-in-time on npm.
|
||||
The new "angular-in-memory-web-api" has new features.
|
||||
<a href="https://github.com/angular/in-memory-web-api/blob/master/README.md" target="_blank">Read about them on github</a>.
|
||||
|
||||
## "Style Guide" with _NgModules_ (2016-09-27)
|
||||
|
||||
[StyleGuide](style-guide.html) explains our recommended conventions for Angular modules (NgModule).
|
||||
Barrels now are far less useful and have been removed from the style guide;
|
||||
they remain valuable but are not a matter of Angular style.
|
||||
We also relaxed the rule that discouraged use of the `@Component.host` property.
|
||||
|
||||
## _moduleId: module.id_ everywhere (2016-09-25)
|
||||
|
||||
Sample components that get their templates or styles with `templateUrl` or `styleUrls`
|
||||
have been converted to _module-relative_ URLs.
|
||||
We added the `moduleId: module.id` property-and-value to their `@Component` metadata.
|
||||
|
||||
This change is a requirement for compilation with AOT compiler when the app loads
|
||||
modules with SystemJS as the samples currently do.
|
||||
|
||||
## "Lifecycle Hooks" guide simplified (2016-09-24)
|
||||
|
||||
The [Lifecycle Hooks](lifecycle-hooks.html) guide is shorter, simpler, and
|
||||
draws more attention to the order in which Angular calls the hooks.
|
||||
@@ -0,0 +1,3 @@
|
||||
@title
|
||||
Cheat Sheet
|
||||
|
||||
@@ -0,0 +1,291 @@
|
||||
@title
|
||||
Component Styles
|
||||
|
||||
@intro
|
||||
Learn how to apply CSS styles to components.
|
||||
|
||||
@description
|
||||
Angular applications are styled with regular CSS. That means we can apply
|
||||
everything we know about CSS stylesheets, selectors, rules, and media queries
|
||||
to our Angular applications directly.
|
||||
|
||||
On top of this, Angular has the ability to bundle *component styles*
|
||||
with our components enabling a more modular design than regular stylesheets.
|
||||
|
||||
In this chapter we learn how to load and apply these *component styles*.
|
||||
|
||||
## Table Of Contents
|
||||
|
||||
* [Using Component Styles](#using-component-styles)
|
||||
* [Special selectors](#special-selectors)
|
||||
* [Loading Styles into Components](#loading-styles)
|
||||
* [Controlling View Encapsulation: Emulated, Native, and None](#view-encapsulation)
|
||||
* [Appendix 1: Inspecting the generated runtime component styles](#inspect-generated-css)
|
||||
* [Appendix 2: Loading Styles with Relative URLs](#relative-urls)
|
||||
|
||||
Run the <live-example></live-example> of the code shown in this chapter.
|
||||
|
||||
## Using Component Styles
|
||||
|
||||
For every Angular component we write, we may define not only an HTML template,
|
||||
but also the CSS styles that go with that template,
|
||||
specifying any selectors, rules, and media queries that we need.
|
||||
|
||||
One way to do this is to set the `styles` property in the component metadata.
|
||||
The `styles` property takes #{_an} #{_array} of strings that contain CSS code.
|
||||
Usually we give it one string as in this example:
|
||||
|
||||
|
||||
{@example 'component-styles/ts/src/app/hero-app.component.ts'}
|
||||
|
||||
Component styles differ from traditional, global styles in a couple of ways.
|
||||
|
||||
Firstly, the selectors we put into a component's styles *only apply within the template
|
||||
of that component*. The `h1` selector in the example above only applies to the `<h1>` tag
|
||||
in the template of `HeroAppComponent`. Any `<h1>` elements elsewhere in
|
||||
the application are unaffected.
|
||||
|
||||
This is a big improvement in modularity compared to how CSS traditionally works:
|
||||
|
||||
1. We can use the CSS class names and selectors that make the most sense in the context of each component.
|
||||
|
||||
1. Class names and selectors are local to the component and won't collide with
|
||||
classes and selectors used elsewhere in the application.
|
||||
|
||||
1. Our component's styles *cannot* be changed by changes to styles elsewhere in the application.
|
||||
|
||||
1. We can co-locate the CSS code of each component with the TypeScript and HTML code of the component,
|
||||
which leads to a neat and tidy project structure.
|
||||
|
||||
1. We can change or remove component CSS code in the future without trawling through the
|
||||
whole application to see where else it may have been used. We just look at the component we're in.
|
||||
|
||||
|
||||
{@a special-selectors}
|
||||
|
||||
## Special selectors
|
||||
|
||||
Component styles have a few special *selectors* from the world of
|
||||
[shadow DOM style scoping](https://www.w3.org/TR/css-scoping-1):
|
||||
|
||||
### :host
|
||||
|
||||
Use the `:host` pseudo-class selector to target styles in the element that *hosts* the component (as opposed to
|
||||
targeting elements *inside* the component's template):
|
||||
|
||||
|
||||
{@example 'component-styles/ts/src/app/hero-details.component.css' region='host'}
|
||||
|
||||
This is the *only* way we can target the host element. We cannot reach
|
||||
it from inside the component with other selectors, because it is not part of the
|
||||
component's own template. It is in a parent component's template.
|
||||
|
||||
Use the *function form* to apply host styles conditionally by
|
||||
including another selector inside parentheses after `:host`.
|
||||
|
||||
In the next example we target the host element again, but only when it also has the `active` CSS class.
|
||||
|
||||
|
||||
{@example 'component-styles/ts/src/app/hero-details.component.css' region='hostfunction'}
|
||||
|
||||
### :host-context
|
||||
|
||||
Sometimes it is useful to apply styles based on some condition *outside* a component's view.
|
||||
For example, there may be a CSS theme class applied to the document `<body>` element, and
|
||||
we want to change how our component looks based on that.
|
||||
|
||||
Use the `:host-context()` pseudo-class selector. It works just like the function
|
||||
form of `:host()`. It looks for a CSS class in *any ancestor* of the component host element, all the way
|
||||
up to the document root. It's useful when combined with another selector.
|
||||
|
||||
In the following example, we apply a `background-color` style to all `<h2>` elements *inside* the component, only
|
||||
if some ancestor element has the CSS class `theme-light`.
|
||||
|
||||
|
||||
{@example 'component-styles/ts/src/app/hero-details.component.css' region='hostcontext'}
|
||||
|
||||
### /deep/
|
||||
|
||||
Component styles normally apply only to the HTML in the component's own template.
|
||||
|
||||
We can use the `/deep/` selector to force a style down through the child component tree into all the child component views.
|
||||
The `/deep/` selector works to any depth of nested components, and it applies *both to the view
|
||||
children and the content children* of the component.
|
||||
|
||||
In this example, we target all `<h3>` elements, from the host element down
|
||||
through this component to all of its child elements in the DOM:
|
||||
|
||||
{@example 'component-styles/ts/src/app/hero-details.component.css' region='deep'}
|
||||
|
||||
The `/deep/` selector also has the alias `>>>`. We can use either of the two interchangeably.
|
||||
|
||||
|
||||
~~~ {.alert.is-important}
|
||||
|
||||
The `/deep/` and `>>>` selectors should only be used with **emulated** view encapsulation.
|
||||
This is the default and it is what we use most of the time. See the
|
||||
[Controlling View Encapsulation](#view-encapsulation)
|
||||
section for more details.
|
||||
|
||||
|
||||
~~~
|
||||
|
||||
|
||||
|
||||
{@a loading-styles}
|
||||
|
||||
## Loading Styles into Components
|
||||
|
||||
We have several ways to add styles to a component:
|
||||
* inline in the template HTML
|
||||
* by setting `styles` or `styleUrls` metadata
|
||||
* with CSS imports
|
||||
|
||||
The scoping rules outlined above apply to each of these loading patterns.
|
||||
|
||||
### Styles in Metadata
|
||||
|
||||
We can add a `styles` #{_array} property to the `@Component` #{_decorator}.
|
||||
Each string in the #{_array} (usually just one string) defines the CSS.
|
||||
|
||||
|
||||
{@example 'component-styles/ts/src/app/hero-app.component.ts'}
|
||||
|
||||
### Template Inline Styles
|
||||
|
||||
We can embed styles directly into the HTML template by putting them
|
||||
inside `<style>` tags.
|
||||
|
||||
|
||||
{@example 'component-styles/ts/src/app/hero-controls.component.ts' region='inlinestyles'}
|
||||
|
||||
### Style URLs in Metadata
|
||||
|
||||
We can load styles from external CSS files by adding a `styleUrls` attribute
|
||||
into a component's `@Component` #{_decorator}:
|
||||
|
||||
|
||||
{@example 'component-styles/ts/src/app/hero-details.component.ts' region='styleurls'}
|
||||
|
||||
### Template Link Tags
|
||||
|
||||
We can also embed `<link>` tags into the component's HTML template.
|
||||
|
||||
As with `styleUrls`, the link tag's `href` URL is relative to the
|
||||
application root, not relative to the component file.
|
||||
|
||||
|
||||
{@example 'component-styles/ts/src/app/hero-team.component.ts' region='stylelink'}
|
||||
|
||||
### CSS @imports
|
||||
|
||||
We can also import CSS files into our CSS files by using the standard CSS
|
||||
[`@import` rule](https://developer.mozilla.org/en/docs/Web/CSS/@import).
|
||||
|
||||
|
||||
{@example 'component-styles/ts/src/app/hero-details.component.css' region='import'}
|
||||
|
||||
|
||||
|
||||
{@a view-encapsulation}
|
||||
|
||||
## Controlling View Encapsulation: Native, Emulated, and None
|
||||
|
||||
As discussed above, component CSS styles are *encapsulated* into the component's own view and do
|
||||
not affect the rest of the application.
|
||||
|
||||
We can control how this encapsulation happens on a *per
|
||||
component* basis by setting the *view encapsulation mode* in the component metadata. There
|
||||
are three modes to choose from:
|
||||
|
||||
* `Native` view encapsulation uses the browser's native [Shadow DOM](https://developer.mozilla.org/en-US/docs/Web/Web_Components/Shadow_DOM)
|
||||
implementation to attach a Shadow DOM to the component's host element, and then puts the component
|
||||
view inside that Shadow DOM. The component's styles are included within the Shadow DOM.
|
||||
|
||||
* `Emulated` view encapsulation (**the default**) emulates the behavior of Shadow DOM by preprocessing
|
||||
(and renaming) the CSS code to effectively scope the CSS to the component's view.
|
||||
See [Appendix 1](#inspect-generated-css) for details.
|
||||
|
||||
* `None` means that Angular does no view encapsulation.
|
||||
Angular adds the CSS to the global styles.
|
||||
The scoping rules, isolations, and protections discussed earlier do not apply.
|
||||
This is essentially the same as pasting the component's styles into the HTML.
|
||||
|
||||
Set the components encapsulation mode using the `encapsulation` property in the component metadata:
|
||||
|
||||
|
||||
{@example 'component-styles/ts/src/app/quest-summary.component.ts' region='encapsulation.native'}
|
||||
|
||||
`Native` view encapsulation only works on [browsers that have native support
|
||||
for Shadow DOM](http://caniuse.com/#feat=shadowdom). The support is still limited,
|
||||
which is why `Emulated` view encapsulation is the default mode and recommended
|
||||
in most cases.
|
||||
|
||||
|
||||
{@a inspect-generated-css}
|
||||
|
||||
## Appendix 1: Inspecting The CSS Generated in Emulated View Encapsulation
|
||||
|
||||
When using the default emulated view encapsulation, Angular preprocesses
|
||||
all component styles so that they approximate the standard Shadow CSS scoping rules.
|
||||
|
||||
When we inspect the DOM of a running Angular application with emulated view
|
||||
encapsulation enabled, we see that each DOM element has some extra attributes
|
||||
attached to it:
|
||||
|
||||
<code-example format="">
|
||||
<hero-details _nghost-pmm-5>
|
||||
<h2 _ngcontent-pmm-5>Mister Fantastic</h2>
|
||||
<hero-team _ngcontent-pmm-5 _nghost-pmm-6>
|
||||
<h3 _ngcontent-pmm-6>Team</h3>
|
||||
</hero-team>
|
||||
</hero-detail>
|
||||
|
||||
</code-example>
|
||||
|
||||
We see two kinds of generated attributes:
|
||||
* An element that would be a Shadow DOM host in native encapsulation has a
|
||||
generated `_nghost` attribute. This is typically the case for component host elements.
|
||||
|
||||
* An element within a component's view has a `_ngcontent` attribute
|
||||
that identifies to which host's emulated Shadow DOM this element belongs.
|
||||
|
||||
The exact values of these attributes are not important. They are automatically
|
||||
generated and we never refer to them in application code. But they are targeted
|
||||
by the generated component styles, which we'll find in the `<head>` section of the DOM:
|
||||
|
||||
<code-example format="">
|
||||
[_nghost-pmm-5] {
|
||||
display: block;
|
||||
border: 1px solid black;
|
||||
}
|
||||
|
||||
h3[_ngcontent-pmm-6] {
|
||||
background-color: white;
|
||||
border: 1px solid #777;
|
||||
}
|
||||
|
||||
</code-example>
|
||||
|
||||
These are the styles we wrote, post-processed so that each selector is augmented
|
||||
with `_nghost` or `_ngcontent` attribute selectors.
|
||||
These extra selectors enable the scoping rules described in this guide.
|
||||
|
||||
We'll likely live with *emulated* mode until shadow DOM gains traction.
|
||||
|
||||
|
||||
{@a 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:
|
||||
<code-example format="nocode">
|
||||
quest-summary.component.ts
|
||||
quest-summary.component.html
|
||||
quest-summary.component.css
|
||||
|
||||
</code-example>
|
||||
|
||||
We include the template and CSS files by setting the `templateUrl` and `styleUrls` metadata properties respectively.
|
||||
Because these files are co-located with the component,
|
||||
it would be nice to refer to them by name without also having to specify a path back to the root of the application.
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,186 @@
|
||||
@title
|
||||
Displaying Data
|
||||
|
||||
@intro
|
||||
Property binding helps show app data in the UI.
|
||||
|
||||
@description
|
||||
You can display data by binding controls in an HTML template to properties of an Angular component.
|
||||
|
||||
In this page, you'll create a component with a list of heroes.
|
||||
You'll display the list of hero names and
|
||||
conditionally show a message below the list.
|
||||
|
||||
The final UI looks like this:
|
||||
|
||||
<figure class='image-display'>
|
||||
<img src="/resources/images/devguide/displaying-data/final.png" alt="Final UI"> </img>
|
||||
</figure>
|
||||
|
||||
# Contents
|
||||
|
||||
* [Showing component properties with interpolation](#interpolation).
|
||||
* [Showing !{_an} !{_array} property with NgFor](#ngFor).
|
||||
* [Conditional display with NgIf](#ngIf).
|
||||
|
||||
The <live-example></live-example> demonstrates all of the syntax and code
|
||||
snippets described in this page.
|
||||
|
||||
## Showing component properties with interpolation
|
||||
The easiest way to display a component property
|
||||
is to bind the property name through interpolation.
|
||||
With interpolation, you put the property name in the view template, enclosed in double curly braces: `{{myHero}}`.
|
||||
|
||||
Follow the [setup](setup.html) instructions for creating a new project
|
||||
named <ngio-ex path="displaying-data"></ngio-ex>.
|
||||
|
||||
Then modify the <ngio-ex path="app.component.ts"></ngio-ex> file by
|
||||
changing the template and the body of the component.
|
||||
|
||||
When you're done, it should look like this:
|
||||
|
||||
|
||||
{@example 'displaying-data/ts/src/app/app.component.1.ts'}
|
||||
|
||||
You added two properties to the formerly empty component: `title` and `myHero`.
|
||||
|
||||
The revised template displays the two component properties using double curly brace
|
||||
interpolation:
|
||||
Angular automatically pulls the value of the `title` and `myHero` properties from the component and
|
||||
inserts those values into the browser. Angular updates the display
|
||||
when these properties change.
|
||||
|
||||
More precisely, the redisplay occurs after some kind of asynchronous event related to
|
||||
the view, such as a keystroke, a timer completion, or a response to an HTTP request.
|
||||
Notice that you don't call **new** to create an instance of the `AppComponent` class.
|
||||
Angular is creating an instance for you. How?
|
||||
|
||||
The CSS `selector` in the `@Component` !{_decorator} specifies an element named `<my-app>`.
|
||||
That element is a placeholder in the body of your `index.html` file:
|
||||
When you bootstrap with the `AppComponent` class (in <ngio-ex path="main.ts"></ngio-ex>), Angular looks for a `<my-app>`
|
||||
in the `index.html`, finds it, instantiates an instance of `AppComponent`, and renders it
|
||||
inside the `<my-app>` tag.
|
||||
|
||||
Now run the app. It should display the title and hero name:
|
||||
<figure class='image-display'>
|
||||
<img src="/resources/images/devguide/displaying-data/title-and-hero.png" alt="Title and Hero"> </img>
|
||||
</figure>
|
||||
|
||||
## Template inline or template file?
|
||||
|
||||
You can store your component's template in one of two places.
|
||||
You can define it *inline* using the `template` property, or you can define
|
||||
the template in a separate HTML file and link to it in
|
||||
the component metadata using the `@Component` !{_decorator}'s `templateUrl` property.
|
||||
|
||||
The choice between inline and separate HTML is a matter of taste,
|
||||
circumstances, and organization policy.
|
||||
Here the app uses inline HTML because the template is small and the demo
|
||||
is simpler without the additional HTML file.
|
||||
|
||||
In either style, the template data bindings have the same access to the component's properties.
|
||||
|
||||
## Showing !{_an} !{_array} property with ***ngFor**
|
||||
|
||||
To display a list of heroes, begin by adding !{_an} !{_array} of hero names to the component and redefine `myHero` to be the first name in the !{_array}.
|
||||
Now use the Angular `ngFor` directive in the template to display
|
||||
each item in the `heroes` list.
|
||||
This UI uses the HTML unordered list with `<ul>` and `<li>` tags. The `*ngFor`
|
||||
in the `<li>` element is the Angular "repeater" directive.
|
||||
It marks that `<li>` element (and its children) as the "repeater template":
|
||||
|
||||
|
||||
~~~ {.alert.is-important}
|
||||
|
||||
Don't forget the leading asterisk (\*) in `*ngFor`. It is an essential part of the syntax.
|
||||
For more information, see the [Template Syntax](./template-syntax.html#ngFor) page.
|
||||
|
||||
|
||||
~~~
|
||||
|
||||
Notice the `hero` in the `ngFor` double-quoted instruction;
|
||||
it is an example of a template input variable. Read
|
||||
more about template input variables in the [microsyntax](./template-syntax.html#ngForMicrosyntax) section of
|
||||
the [Template Syntax](./template-syntax.html) page.
|
||||
|
||||
Angular duplicates the `<li>` for each item in the list, setting the `hero` variable
|
||||
to the item (the hero) in the current iteration. Angular uses that variable as the
|
||||
context for the interpolation in the double curly braces.
|
||||
|
||||
In this case, `ngFor` is displaying !{_an} !{_array}, but `ngFor` can
|
||||
repeat items for any [iterable](!{_iterableUrl}) object.Now the heroes appear in an unordered list.
|
||||
|
||||
<figure class='image-display'>
|
||||
<img src="/resources/images/devguide/displaying-data/hero-names-list.png" alt="After ngfor"> </img>
|
||||
</figure>
|
||||
|
||||
|
||||
## Creating a class for the data
|
||||
|
||||
The app's code defines the data directly inside the component, which isn't best practice.
|
||||
In a simple demo, however, it's fine.
|
||||
|
||||
At the moment, the binding is to !{_an} !{_array} of strings.
|
||||
In real applications, most bindings are to more specialized objects.
|
||||
|
||||
To convert this binding to use specialized objects, turn the !{_array}
|
||||
of hero names into !{_an} !{_array} of `Hero` objects. For that you'll need a `Hero` class.
|
||||
|
||||
Create a new file in the `!{_appDir}` folder called <ngio-ex path="hero.ts"></ngio-ex> with the following code:
|
||||
|
||||
## Using the Hero class
|
||||
|
||||
After importing the `Hero` class, the `AppComponent.heroes` property can return a _typed_ !{_array}
|
||||
of `Hero` objects:
|
||||
Next, update the template.
|
||||
At the moment it displays the hero's `id` and `name`.
|
||||
Fix that to display only the hero's `name` property.
|
||||
The display looks the same, but the code is clearer.
|
||||
|
||||
## Conditional display with NgIf
|
||||
|
||||
Sometimes an app needs to display a view or a portion of a view only under specific circumstances.
|
||||
|
||||
Let's change the example to display a message if there are more than three heroes.
|
||||
|
||||
The Angular `ngIf` directive inserts or removes an element based on a !{_boolean} condition.
|
||||
To see it in action, add the following paragraph at the bottom of the template:
|
||||
|
||||
|
||||
~~~ {.alert.is-important}
|
||||
|
||||
Don't forget the leading asterisk (\*) in `*ngIf`. It is an essential part of the syntax.
|
||||
Read more about `ngIf` and `*` in the [ngIf section](./template-syntax.html#ngIf) of the [Template Syntax](./template-syntax.html) page.
|
||||
|
||||
|
||||
~~~
|
||||
|
||||
The template expression inside the double quotes,
|
||||
`*ngIf="heros.length > 3"`, looks and behaves much like !{_Lang}.
|
||||
When the component's list of heroes has more than three items, Angular adds the paragraph
|
||||
to the DOM and the message appears. If there are three or fewer items, Angular omits the
|
||||
paragraph, so no message appears. For more information,
|
||||
see the [template expressions](./template-syntax.html#template-expressions) section of the
|
||||
[Template Syntax](./template-syntax.html) page.
|
||||
|
||||
|
||||
~~~ {.alert.is-helpful}
|
||||
|
||||
Angular isn't showing and hiding the message. It is adding and removing the paragraph element from the DOM. That improves performance, especially in larger projects when conditionally including or excluding
|
||||
big chunks of HTML with many data bindings.
|
||||
|
||||
|
||||
~~~
|
||||
|
||||
Try it out. Because the !{_array} has four items, the message should appear.
|
||||
Go back into <ngio-ex path="app.component.ts"></ngio-ex> and delete or comment out one of the elements from the hero !{_array}.
|
||||
The browser should refresh automatically and the message should disappear.
|
||||
|
||||
## Summary
|
||||
Now you know how to use:
|
||||
- **Interpolation** with double curly braces to display a component property.
|
||||
- **ngFor** to display !{_an} !{_array} of items.
|
||||
- A !{_Lang} class to shape the **model data** for your component and display properties of that model.
|
||||
- **ngIf** to conditionally display a chunk of HTML based on a boolean expression.
|
||||
|
||||
Here's the final code:
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,6 @@
|
||||
@title
|
||||
Glossary
|
||||
|
||||
@intro
|
||||
Brief definitions of the most important words in the Angular vocabulary
|
||||
|
||||
@@ -0,0 +1,184 @@
|
||||
@title
|
||||
Hierarchical Dependency Injectors
|
||||
|
||||
@intro
|
||||
Angular's hierarchical dependency injection system supports nested injectors in parallel with the component tree.
|
||||
|
||||
@description
|
||||
You learned the basics of Angular Dependency injection in the
|
||||
[Dependency Injection](./dependency-injection.html) guide.
|
||||
|
||||
Angular has a _Hierarchical Dependency Injection_ system.
|
||||
There is actually a tree of injectors that parallel an application's component tree.
|
||||
You can reconfigure the injectors at any level of that component tree.
|
||||
|
||||
This guide explores this system and how to use it to your advantage.
|
||||
|
||||
Try the <live-example></live-example>.
|
||||
|
||||
## The injector tree
|
||||
|
||||
In the [Dependency Injection](./dependency-injection.html) guide,
|
||||
you learned how to configure a dependency injector and how to retrieve dependencies where you need them.
|
||||
|
||||
In fact, there is no such thing as ***the*** injector.
|
||||
An application may have multiple injectors.
|
||||
An Angular application is a tree of components. Each component instance has its own injector.
|
||||
The tree of components parallels the tree of injectors.
|
||||
|
||||
The component's injector may be a _proxy_ for an ancestor injector higher in the component tree.
|
||||
That's an implementation detail that improves efficiency.
|
||||
You won't notice the difference and
|
||||
your mental model should be that every component has its own injector.
|
||||
Consider this guide's variation on the Tour of Heroes application.
|
||||
At the top is the `AppComponent` which has some sub-components.
|
||||
One of them is the `HeroesListComponent`.
|
||||
The `HeroesListComponent` holds and manages multiple instances of the `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.
|
||||
|
||||
<figure class='image-display'>
|
||||
<img src="/resources/images/devguide/dependency-injection/component-hierarchy.png" alt="injector tree" width="600"> </img>
|
||||
</figure>
|
||||
|
||||
### Injector bubbling
|
||||
|
||||
When a component requests a dependency, Angular tries to satisfy that dependency with a provider registered in that component's own injector.
|
||||
If the component's injector lacks the provider, it passes the request up to its parent component's injector.
|
||||
If that injector can't satisfy the request, it passes it along to *its* parent injector.
|
||||
The requests keep bubbling up until Angular finds an injector that can handle the request or runs out of ancestor injectors.
|
||||
If it runs out of ancestors, Angular throws an error.
|
||||
|
||||
You can cap the bubbling. An intermediate component can declare that it is the "host" component.
|
||||
The hunt for providers will climb no higher than the injector for that host component.
|
||||
This a topic for another day.
|
||||
### Re-providing a service at different levels
|
||||
You can re-register a provider for a particular dependency token at multiple levels of the injector tree.
|
||||
You don't *have* to re-register providers. You shouldn't do so unless you have a good reason.
|
||||
But you *can*.
|
||||
|
||||
As the resolution logic works upwards, the first provider encountered wins.
|
||||
Thus, a provider in an intermediate injector intercepts a request for a service from something lower in the tree.
|
||||
It effectively "reconfigures" and "shadows" a provider at a higher level in the tree.
|
||||
|
||||
If you only specify providers at the top level (typically the root `AppModule`), the tree of injectors appears to be flat.
|
||||
All requests bubble up to the root <span if-docs="ts"><code>NgModule</code></span> injector that you configured with the `!{_bootstrapModule}` method.
|
||||
|
||||
## Component injectors
|
||||
|
||||
The ability to configure one or more providers at different levels opens up interesting and useful possibilities.
|
||||
### Scenario: service isolation
|
||||
|
||||
Architectural reasons may lead you to restrict access to a service to the application domain where it belongs.
|
||||
|
||||
The guide sample includes a `VillainsListComponent` that displays a list of villains.
|
||||
It gets those villains from a `VillainsService`.
|
||||
|
||||
While you could provide `VillainsService` in the root `AppModule` (that's where you'll find the `HeroesService`),
|
||||
that would make the `VillainsService` available everywhere in the application, including the _Hero_ workflows.
|
||||
|
||||
If you later modify the `VillainsService`, you could break something in a hero component somewhere.
|
||||
That's not supposed to happen but the way you've provided the service creates that risk.
|
||||
|
||||
Instead, provide the `VillainsService` in the `providers` metadata of the `VillainsListComponent` like this:
|
||||
|
||||
|
||||
{@example 'hierarchical-dependency-injection/ts/src/app/villains-list.component.ts' region='metadata'}
|
||||
|
||||
By providing `VillainsService` in the `VillainsListComponent` metadata — and nowhere else —,
|
||||
the service becomes available only in the `VillainsListComponent` and its sub-component tree.
|
||||
It's still a singleton, but it's a singleton that exist solely in the _villain_ domain.
|
||||
|
||||
You are confident that a hero component can't access it. You've reduced your exposure to error.
|
||||
|
||||
### Scenario: multiple edit sessions
|
||||
|
||||
Many applications allow users to work on several open tasks at the same time.
|
||||
For example, in a tax preparation application, the preparer could be working several tax returns,
|
||||
switching from one to the other throughout the day.
|
||||
|
||||
This guide demonstrates that scenario with an example in the Tour of Heroes theme.
|
||||
Imagine an outer `HeroListComponent` that displays a list of super heroes.
|
||||
|
||||
To open a hero's tax return, the preparer clicks on a hero name, which opens a component for editing that return.
|
||||
Each selected hero tax return opens in its own component and multiple returns can be open at the same time.
|
||||
|
||||
Each tax return component
|
||||
* is its own tax return editing session.
|
||||
* can change a tax return without affecting a return in another component.
|
||||
* has the ability to save the changes to its tax return or cancel them.
|
||||
|
||||
<figure class='image-display'>
|
||||
<img src="/resources/images/devguide/dependency-injection/hid-heroes-anim.gif" width="400" alt="Heroes in action"> </img>
|
||||
</figure>
|
||||
|
||||
One might suppose that the `TaxReturnComponent` has logic to manage and restore changes.
|
||||
That would be a pretty easy task for a simple hero tax return.
|
||||
In the real world, with a rich tax return data model, the change management would be tricky.
|
||||
You might delegate that management to a helper service, as this example does.
|
||||
|
||||
Here is the `HeroTaxReturnService`.
|
||||
It caches a single `HeroTaxReturn`, tracks changes to that return, and can save or restore it.
|
||||
It also delegates to the application-wide, singleton `HeroService`, which it gets by injection.
|
||||
|
||||
{@example 'hierarchical-dependency-injection/ts/src/app/hero-tax-return.service.ts'}
|
||||
|
||||
Here is the `HeroTaxReturnComponent` that makes use of it.
|
||||
|
||||
{@example 'hierarchical-dependency-injection/ts/src/app/hero-tax-return.component.ts'}
|
||||
|
||||
The _tax-return-to-edit_ arrives via the input property which is implemented with getters and setters.
|
||||
The setter initializes the component's own instance of the `HeroTaxReturnService` with the incoming return.
|
||||
The getter always returns what that service says is the current state of the hero.
|
||||
The component also asks the service to save and restore this tax return.
|
||||
|
||||
There'd be big trouble if _this_ service were an application-wide singleton.
|
||||
Every component would share the same service instance.
|
||||
Each component would overwrite the tax return that belonged to another hero.
|
||||
What a mess!
|
||||
|
||||
Look closely at the metadata for the `HeroTaxReturnComponent`. Notice the `providers` property.
|
||||
|
||||
|
||||
{@example 'hierarchical-dependency-injection/ts/src/app/hero-tax-return.component.ts' region='providers'}
|
||||
|
||||
The `HeroTaxReturnComponent` has its own provider of the `HeroTaxReturnService`.
|
||||
Recall that every component _instance_ has its own injector.
|
||||
Providing the service at the component level ensures that _every_ instance of the component gets its own, private instance of the service.
|
||||
No tax return overwriting. No mess.
|
||||
|
||||
The rest of the scenario code relies on other Angular features and techniques that you can learn about elsewhere in the documentation.
|
||||
You can review it and download it from the <live-example></live-example>
|
||||
### Scenario: specialized providers
|
||||
|
||||
Another reason to re-provide a service is to substitute a _more specialized_ implementation of that service,
|
||||
deeper in the component tree.
|
||||
|
||||
Consider again the Car example from the [Dependency Injection](./dependency-injection.html) guide.
|
||||
Suppose you configured the root injector (marked as A) with _generic_ providers for
|
||||
`CarService`, `EngineService` and `TiresService`.
|
||||
|
||||
You create a car component (A) that displays a car constructed from these three generic services.
|
||||
|
||||
Then you create a child component (B) that defines its own, _specialized_ providers for `CarService` and `EngineService`
|
||||
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`.
|
||||
|
||||
<figure class='image-display'>
|
||||
<img src="/resources/images/devguide/dependency-injection/car-components.png" alt="car components" width="220"> </img>
|
||||
</figure>
|
||||
|
||||
Behind the scenes, each component sets up its own injector with zero, one, or more providers defined for that component itself.
|
||||
|
||||
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
|
||||
`Tires` resolved by the root injector (A).
|
||||
|
||||
<figure class='image-display'>
|
||||
<img src="/resources/images/devguide/dependency-injection/injector-tree.png" alt="car injector tree" width="600"> </img>
|
||||
</figure>
|
||||
|
||||
|
||||
The code for this _cars_ scenario is in the `car.components.ts` and `car.services.ts` files of the sample
|
||||
which you can review and download from the <live-example></live-example>
|
||||
@@ -0,0 +1,152 @@
|
||||
@title
|
||||
Documentation Overview
|
||||
|
||||
@intro
|
||||
How to read and use this documentation
|
||||
|
||||
@description
|
||||
This page describes the Angular documentation at a high level.
|
||||
If you're new to Angular, you may want to visit "[Learning Angular](learning-angular.html)" first.
|
||||
|
||||
## Themes
|
||||
|
||||
The documentation is divided into major thematic sections, each
|
||||
a collection of pages devoted to that theme.
|
||||
|
||||
<table width="100%">
|
||||
|
||||
<col width="15%">
|
||||
|
||||
</col>
|
||||
|
||||
|
||||
<col>
|
||||
|
||||
</col>
|
||||
|
||||
|
||||
<tr style=top>
|
||||
|
||||
<td>
|
||||
<b><a href="../quickstart.html">QuickStart</a></b>
|
||||
</td>
|
||||
|
||||
|
||||
<td>
|
||||
A first taste of Angular<span if-docs="ts"> with zero installation.
|
||||
Run "Hello World" in an online code editor and start playing with live code</span>.
|
||||
</td>
|
||||
|
||||
|
||||
</tr>
|
||||
|
||||
|
||||
<tr style=top>
|
||||
|
||||
<td>
|
||||
<b>Guide</b>
|
||||
</td>
|
||||
|
||||
|
||||
<td>
|
||||
Learn the Angular basics (you're already here!) like the setup for local development,
|
||||
displaying data and accepting user input, injecting application services into components,
|
||||
and building simple forms.
|
||||
</td>
|
||||
|
||||
|
||||
</tr>
|
||||
|
||||
|
||||
<tr style=top>
|
||||
|
||||
<td>
|
||||
<b><a href="../api/">API Reference</a></b>
|
||||
</td>
|
||||
|
||||
|
||||
<td>
|
||||
Authoritative details about each of the Angular libraries.
|
||||
</td>
|
||||
|
||||
|
||||
</tr>
|
||||
|
||||
|
||||
<tr style=top>
|
||||
|
||||
<td>
|
||||
<b><a href="../tutorial/">Tutorial</a></b>
|
||||
</td>
|
||||
|
||||
|
||||
<td>
|
||||
A step-by-step, immersive approach to learning Angular that
|
||||
introduces the major features of Angular in an application context.
|
||||
</td>
|
||||
|
||||
|
||||
</tr>
|
||||
|
||||
|
||||
<tr style=top>
|
||||
|
||||
<td>
|
||||
<b><a href=" ">Advanced</a></b>
|
||||
</td>
|
||||
|
||||
|
||||
<td>
|
||||
In-depth analysis of Angular features and development practices.
|
||||
</td>
|
||||
|
||||
|
||||
</tr>
|
||||
|
||||
|
||||
<tr style=top if-docs="ts">
|
||||
|
||||
<td>
|
||||
<b><a href="../cookbook/">Cookbook</a></b>
|
||||
</td>
|
||||
|
||||
|
||||
<td>
|
||||
Recipes for specific application challenges, mostly code snippets with a minimum of exposition.
|
||||
|
||||
</td>
|
||||
|
||||
|
||||
</tr>
|
||||
|
||||
|
||||
</table>
|
||||
|
||||
A few early pages are written as tutorials and are clearly marked as such.
|
||||
The rest of the pages highlight key points in code rather than explain each step necessary to build the sample.
|
||||
You can always get the full source through the #{_liveLink}s.
|
||||
|
||||
## Code samples
|
||||
|
||||
Each page includes code snippets from a sample application that accompanies the page.
|
||||
You can reuse these snippets in your applications.
|
||||
|
||||
Look for a link to a running version of that sample, often near the top of the page,
|
||||
such as this <live-example name="architecture"></live-example> from the [Architecture](architecture.html) page.
|
||||
<span if-docs="ts">
|
||||
The link launches a browser-based, code editor where you can inspect, modify, save, and download the code.
|
||||
</span>
|
||||
|
||||
## Reference pages
|
||||
|
||||
* The [Cheat Sheet](cheatsheet.html) lists Angular syntax for common scenarios.
|
||||
* The [Glossary](glossary.html) defines terms that Angular developers should know.
|
||||
<li if-docs="ts">The [Change Log](change-log.html) announces what's new and changed in the documentation.</li>
|
||||
* The [API Reference](../api/) is the authority on every public-facing member of the Angular libraries.
|
||||
|
||||
## Feedback
|
||||
|
||||
We welcome feedback!
|
||||
|
||||
* Use the <a href="!{_ngDocRepoURL}" target="_blank" title="angular docs on github">!{_angular_io} Github repository</a> for **documentation** issues and pull requests.
|
||||
* Use the <a href="!{_ngRepoURL}" target="_blank" title="angular source on github">Angular Github repository</a> to report issues with **Angular** itself.
|
||||
@@ -0,0 +1,46 @@
|
||||
@title
|
||||
Learning Angular
|
||||
|
||||
@intro
|
||||
A suggested path through the documentation for Angular newcomers
|
||||
|
||||
@description
|
||||
|
||||
<figure>
|
||||
<img src="/resources/images/devguide/intro/people.png" width="200px" height="152px" alt="Us" align="left" style="margin-left:-40px;margin-right:10px"> </img>
|
||||
</figure>
|
||||
|
||||
Everyone learns differently.
|
||||
You don't have to read the documentation straight through. Most pages stand on their own.
|
||||
Those new to Angular may wish to follow this popular learning path.
|
||||
<br class="l-clear-left">
|
||||
|
||||
1. [Setup](setup.html "Setup locally withe Quickstart seed") for local Angular development, if you haven't already done so.
|
||||
|
||||
1. Take the [*Tour of Heroes* tutorial](../tutorial "Tour of Heroes").
|
||||
|
||||
The *Tour of Heroes* takes you step-by-step from [setup](setup.html)
|
||||
to a full-featured example that demonstrates the essential characteristics of a professional application:
|
||||
a sensible project structure, data binding, master/detail, services, dependency injection, navigation, and remote data access.
|
||||
|
||||
1. <a id="architecture"></a>Read the [Architecture](architecture.html) overview for the big picture.
|
||||
|
||||
1. [The Root Module](appmodule.html) introduces the `NgModule` class that tells Angular how to compile and run your application.
|
||||
|
||||
1. [Displaying Data](displaying-data.html) shows how data binding puts component property values on screen.
|
||||
|
||||
1. [User Input](user-input.html) explains how to respond to user-initiated DOM events.
|
||||
|
||||
1. [Forms](forms.html) covers data entry and validation within the UI.
|
||||
|
||||
1. [Dependency Injection](dependency-injection.html) is the way to build large, maintainable applications
|
||||
from small, single-purpose parts.
|
||||
|
||||
1. [Template Syntax](template-syntax.html) is a comprehensive study of Angular template HTML.
|
||||
|
||||
After reading the above sections, feel free to skip around among the other pages on this site.
|
||||
|
||||
### Next Step
|
||||
|
||||
Try the [tutorial](../tutorial "Tour of Heroes") if you're ready to start coding or
|
||||
visit the [Architecture](architecture.html "Basic Concepts") page if you prefer to learn the basic concepts first.
|
||||
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user