Compare commits

..

2 Commits
4.2.4 ... 4.2.0

Author SHA1 Message Date
1c04b83ea3 docs: add changelog for 4.2.0 2017-06-08 15:13:37 -07:00
429bc9d3cd release: cut the 4.2.0 release 2017-06-08 15:04:22 -07:00
314 changed files with 4145 additions and 6520 deletions

View File

@ -3,7 +3,7 @@ jobs:
build:
working_directory: ~/ng
docker:
- image: angular/ngcontainer
- image: alexeagle/ngcontainer
steps:
- checkout
- restore_cache:

View File

@ -1,57 +1,39 @@
<!--
PLEASE HELP US PROCESS GITHUB ISSUES FASTER BY PROVIDING THE FOLLOWING INFORMATION.
ISSUES MISSING IMPORTANT INFORMATION MIGHT BE CLOSED WITHOUT INVESTIGATION.
IF YOU DON'T FILL OUT THE FOLLOWING INFORMATION WE MIGHT CLOSE YOUR ISSUE WITHOUT INVESTIGATING
-->
## I'm submitting a ...
<!-- Check one of the following options with "x" -->
<pre><code>
[ ] Regression (behavior that used to work and stopped working in a new release)
[ ] Bug report <!-- Please search github for a similar issue or PR before submitting -->
[ ] Feature request
[ ] Documentation issue or request
[ ] Support request => Please do not submit support request here, instead see https://github.com/angular/angular/blob/master/CONTRIBUTING.md#question
</code></pre>
**I'm submitting a ...** (check one with "x")
```
[ ] bug report => search github for a similar issue or PR before submitting
[ ] feature request
[ ] support request => Please do not submit support request here, instead see https://github.com/angular/angular/blob/master/CONTRIBUTING.md#question
```
## Current behavior
<!-- Describe how the issue manifests. -->
**Current behavior**
<!-- Describe how the bug manifests. -->
**Expected behavior**
<!-- Describe what the behavior would be without the bug. -->
## Expected behavior
<!-- Describe what the desired behavior would be. -->
## Minimal reproduction of the problem with instructions
**Minimal reproduction of the problem with instructions**
<!--
For bug reports please provide the *STEPS TO REPRODUCE* and if possible a *MINIMAL DEMO* of the problem via
If the current behavior is a bug or you can illustrate your feature request better with an example,
please provide the *STEPS TO REPRODUCE* and if possible a *MINIMAL DEMO* of the problem via
https://plnkr.co or similar (you can use this template as a starting point: http://plnkr.co/edit/tpl:AvJOMERrnz94ekVua0u5).
-->
## What is the motivation / use case for changing the behavior?
<!-- Describe the motivation or the concrete use case. -->
**What is the motivation / use case for changing the behavior?**
<!-- Describe the motivation or the concrete use case -->
**Please tell us about your environment:**
<!-- Operating system, IDE, package manager, HTTP server, ... -->
## Please tell us about your environment
<pre><code>
Angular version: X.Y.Z
* **Angular version:** 2.0.X
<!-- Check whether this is still an issue in the most recent Angular version -->
Browser:
- [ ] Chrome (desktop) version XX
- [ ] Chrome (Android) version XX
- [ ] Chrome (iOS) version XX
- [ ] Firefox version XX
- [ ] Safari (desktop) version XX
- [ ] Safari (iOS) version XX
- [ ] IE version XX
- [ ] Edge version XX
* **Browser:** [all | Chrome XX | Firefox XX | IE XX | Safari XX | Mobile Chrome XX | Android X.X Web Browser | iOS XX Safari | iOS XX UIWebView | iOS XX WKWebView ]
<!-- All browsers where this could be reproduced -->
For Tooling issues:
- Node version: XX <!-- use `node --version` -->
- Platform: <!-- Mac, Linux, Windows -->
* **Language:** [all | TypeScript X.X | ES6/7 | ES5]
Others:
<!-- Anything else relevant? Operating system version, IDE, package manager, HTTP server, ... -->
</code></pre>
* **Node (for AoT issues):** `node --version` =

View File

@ -1,15 +1,10 @@
## PR Checklist
Does please check if your PR fulfills the following requirements:
**Please check if the PR fulfills these requirements**
- [ ] The commit message follows our guidelines: https://github.com/angular/angular/blob/master/CONTRIBUTING.md#commit
- [ ] Tests for the changes have been added (for bug fixes / features)
- [ ] Docs have been added / updated (for bug fixes / features)
## PR Type
What kind of change does this PR introduce?
<!-- Please check the one that applies to this PR using "x". -->
**What kind of change does this PR introduce?** (check one with "x")
```
[ ] Bugfix
[ ] Feature
@ -17,27 +12,25 @@ What kind of change does this PR introduce?
[ ] Refactoring (no functional changes, no api changes)
[ ] Build related changes
[ ] CI related changes
[ ] Documentation content changes
[ ] angular.io application / infrastructure changes
[ ] Other... Please describe:
```
## What is the current behavior?
<!-- Please describe the current behavior that you are modifying, or link to a relevant issue. -->
Issue Number: N/A
**What is the current behavior?** (You can also link to an open issue here)
## What is the new behavior?
**What is the new behavior?**
## Does this PR introduce a breaking change?
**Does this PR introduce a breaking change?** (check one with "x")
```
[ ] Yes
[ ] No
```
<!-- If this PR contains a breaking change, please describe the impact and migration path for existing applications below. -->
If this PR contains a breaking change, please describe the impact and migration path for existing applications: ...
## Other information
**Other information**:

2
BUILD
View File

@ -10,7 +10,7 @@ filegroup(
# Performance workaround: list individual files
# This won't scale in the general case.
# TODO(alexeagle): figure out what to do
"node_modules/typescript/**",
"node_modules/typescript/lib/**",
"node_modules/zone.js/**/*.d.ts",
"node_modules/rxjs/**/*.d.ts",
"node_modules/@types/**/*.d.ts",

View File

@ -1,59 +1,3 @@
<a name="4.2.4"></a>
## [4.2.4](https://github.com/angular/angular/compare/4.2.3...4.2.4) (2017-06-21)
### Bug Fixes
* **compiler:** avoid emitting self importing factories ([c112232](https://github.com/angular/angular/commit/c112232))
* **compiler-cli:** find lazy routes in nested module import arrays ([59299de](https://github.com/angular/angular/commit/59299de))
* **core**: argument destructuring sometimes breaks strictNullChecks ([77860a0](https://github.com/angular/angular/commit/77860a0))
* **forms:** roll back breaking change with min/max directives ([4ab7353](https://github.com/angular/angular/commit/4ab7353)), closes [#17491](https://github.com/angular/angular/issues/17491)
* **language-service:** infer `any` `ngForOf` of type `any` ([63a5f33](https://github.com/angular/angular/commit/63a5f33))
* **language-service:** rollup `tslib` into the language service package ([20eb5cf](https://github.com/angular/angular/commit/20eb5cf))
* **router:** update the version placeholder so that it gets replaced during the build ([7de1ae2](https://github.com/angular/angular/commit/7de1ae2)), closes [#17403](https://github.com/angular/angular/issues/17403)
* **tsc-wrapped:** skip collecting metadata for default functions ([3390648](https://github.com/angular/angular/commit/3390648))
<a name="4.2.3"></a>
## [4.2.3](https://github.com/angular/angular/compare/4.2.1...4.2.3) (2017-06-16)
### Bug Fixes
* **animations:** compute removal node height correctly ([185075d](https://github.com/angular/angular/commit/185075d))
* **animations:** do not treat a `0` animation state as `void` ([451257a](https://github.com/angular/angular/commit/451257a))
* **animations:** properly collect :enter nodes in a partially updated collection ([6ca4692](https://github.com/angular/angular/commit/6ca4692)), closes [#17440](https://github.com/angular/angular/issues/17440)
* **animations:** remove duplicate license header ([b192dd5](https://github.com/angular/angular/commit/b192dd5))
* **forms:** temp roll back breaking change with min/max directives ([b8c39cd](https://github.com/angular/angular/commit/b8c39cd)), closes [#17491](https://github.com/angular/angular/issues/17491)
<a name="4.2.2"></a>
## [4.2.2](https://github.com/angular/angular/compare/4.2.1...4.2.2) (2017-06-12)
### Bug Fixes
* **animations:** compute removal node height correctly ([185075d](https://github.com/angular/angular/commit/185075d))
* **animations:** do not treat a `0` animation state as `void` ([451257a](https://github.com/angular/angular/commit/451257a))
* **animations:** properly collect :enter nodes in a partially updated collection ([6ca4692](https://github.com/angular/angular/commit/6ca4692)), closes [#17440](https://github.com/angular/angular/issues/17440)
* **compiler:** dont always compile `.ngfactory.ts` files by default ([ed73d4f](https://github.com/angular/angular/commit/ed73d4f3ac6b542bf5ea3eb73fbe91e2ceabcdb4))
<a name="4.2.1"></a>
## [4.2.1](https://github.com/angular/angular/compare/4.2.0-rc.2...4.2.1) (2017-06-09)
### Bug Fixes
* **compiler:** dont write summaries for jit by default ([d3a5f1a](https://github.com/angular/angular/commit/d3a5f1a))
* **http:** move destructuring inside {Request,Response}Options ctor ([c2d31fb](https://github.com/angular/angular/commit/c2d31fb)), closes [#16663](https://github.com/angular/angular/issues/16663)
<a name="4.2.0"></a>
# [4.2.0](https://github.com/angular/angular/compare/4.2.0-rc.2...4.2.0) salubrious-stratagem (2017-06-08)

View File

@ -3,10 +3,10 @@ load("@bazel_tools//tools/build_defs/repo:git.bzl", "git_repository")
git_repository(
name = "io_bazel_rules_typescript",
remote = "https://github.com/bazelbuild/rules_typescript.git",
commit = "804c5da",
tag = "0.0.3",
)
load("@io_bazel_rules_typescript//:defs.bzl", "node_repositories", "npm_install")
load("@io_bazel_rules_typescript//:defs.bzl", "node_repositories", "yarn_install")
node_repositories()
npm_install(package_json = "//:package.json")
yarn_install(package_json = "//:package.json")

View File

@ -31,7 +31,6 @@
"environmentSource": "environments/environment.ts",
"environments": {
"dev": "environments/environment.ts",
"stage": "environments/environment.stage.ts",
"prod": "environments/environment.prod.ts"
}
}

5
aio/.firebaserc Normal file
View File

@ -0,0 +1,5 @@
{
"projects": {
"staging": "aio-staging"
}
}

3
aio/.gitignore vendored
View File

@ -43,6 +43,3 @@ protractor-results*.txt
# System Files
.DS_Store
Thumbs.db
# copied dependencies
src/assets/js/lunr*

View File

@ -52,9 +52,6 @@ dist/
!aot/index.html
!rollup-config.js
# i18n
!i18n/src/systemjs-text-plugin.js
# testing
!testing/src/browser-test-shim.js
!testing/karma*.js

View File

@ -0,0 +1 @@
**/*.js

View File

@ -44,7 +44,7 @@ import { Heroes } from './hero.service';
animate('0.2s ease-in')
]),
transition('* => void', [
animate('0.2s 0.1s ease-out', style({
animate('0.2s 10 ease-out', style({
opacity: 0,
transform: 'translateX(100%)'
}))

View File

@ -0,0 +1,7 @@
**/*.ngfactory.ts
**/*.ngsummary.json
**/*.shim.ngstyle.ts
**/*.metadata.json
dist
!app/tsconfig.json
!rollup-config.js

View File

@ -0,0 +1,45 @@
# See http://help.github.com/ignore-files/ for more about ignoring files.
# compiled output
/dist
/tmp
# dependencies
/node_modules
# IDEs and editors
/.idea
.project
.classpath
.c9/
*.launch
.settings/
*.sublime-workspace
# IDE - VSCode
.vscode/*
!.vscode/settings.json
!.vscode/tasks.json
!.vscode/launch.json
!.vscode/extensions.json
# misc
/.sass-cache
/connect.lock
/coverage/*
/libpeerconnection.log
npm-debug.log
testem.log
/typings
# e2e
/e2e/*.js
/e2e/*.map
#System Files
.DS_Store
Thumbs.db
!src/styles.css
!karma.conf.js
!protractor.conf.js

View File

@ -0,0 +1,116 @@
/* #docregion , quickstart, toh */
/* Master Styles */
h1 {
color: #369;
font-family: Arial, Helvetica, sans-serif;
font-size: 250%;
}
h2, h3 {
color: #444;
font-family: Arial, Helvetica, sans-serif;
font-weight: lighter;
}
body {
margin: 2em;
}
/* #enddocregion quickstart */
body, input[text], button {
color: #888;
font-family: Cambria, Georgia;
}
/* #enddocregion toh */
a {
cursor: pointer;
cursor: hand;
}
button {
font-family: Arial;
background-color: #eee;
border: none;
padding: 5px 10px;
border-radius: 4px;
cursor: pointer;
cursor: hand;
}
button:hover {
background-color: #cfd8dc;
}
button:disabled {
background-color: #eee;
color: #aaa;
cursor: auto;
}
/* Navigation link styles */
nav a {
padding: 5px 10px;
text-decoration: none;
margin-right: 10px;
margin-top: 10px;
display: inline-block;
background-color: #eee;
border-radius: 4px;
}
nav a:visited, a:link {
color: #607D8B;
}
nav a:hover {
color: #039be5;
background-color: #CFD8DC;
}
nav a.active {
color: #039be5;
}
/* items class */
.items {
margin: 0 0 2em 0;
list-style-type: none;
padding: 0;
width: 24em;
}
.items li {
cursor: pointer;
position: relative;
left: 0;
background-color: #EEE;
margin: .5em;
padding: .3em 0;
height: 1.6em;
border-radius: 4px;
}
.items li:hover {
color: #607D8B;
background-color: #DDD;
left: .1em;
}
.items li.selected {
background-color: #CFD8DC;
color: white;
}
.items li.selected:hover {
background-color: #BBD8DC;
}
.items .text {
position: relative;
top: -3px;
}
.items .badge {
display: inline-block;
font-size: small;
color: white;
padding: 0.8em 0.7em 0 0.7em;
background-color: #607D8B;
line-height: 1em;
position: relative;
left: -1px;
top: -4px;
height: 1.8em;
margin-right: .8em;
border-radius: 4px 0 0 4px;
}
/* #docregion toh */
/* everywhere else */
* {
font-family: Arial, Helvetica, sans-serif;
}

View File

@ -0,0 +1 @@
**/*.js

View File

@ -0,0 +1 @@
!systemjs.config.server.js

View File

@ -1,15 +0,0 @@
'use strict'; // necessary for es6 output in node
import { browser, element, by } from 'protractor';
describe('Docs Style Guide', function () {
let _title = 'Authors Style Guide Sample';
beforeAll(function () {
browser.get('');
});
it('should display correct title: ' + _title, function () {
expect(element(by.css('h1')).getText()).toEqual(_title);
});
});

View File

@ -1,7 +0,0 @@
{
"scripts": {
"start": "concurrently \"npm run build:watch\" \"npm run serve\"",
"test": "concurrently \"npm run build:watch\" \"karma start karma.conf.js\"",
"lint": "tslint ./src/**/*.ts -t verbose"
}
}

View File

@ -1,10 +0,0 @@
{
"description": "Authors style guide",
"basePath": "src/",
"files": [
"!**/*.d.ts",
"!**/*.js",
"!**/*.[1,2,3].*"
],
"tags": ["author", "style guide"]
}

View File

@ -1,9 +0,0 @@
{
"description": "Second authors style guide plunker (non-executing)",
"basePath": "src/",
"files": [
"index.2.html"
],
"main": "index.2.html",
"tags": ["author", "style guide"]
}

View File

@ -1,51 +0,0 @@
/* #docregion heroes */
.heroes {
margin: 0 0 2em 0;
list-style-type: none;
padding: 0;
width: 15em;
}
/* #enddocregion heroes */
.heroes li {
cursor: pointer;
position: relative;
left: 0;
background-color: #EEE;
margin: .5em;
padding: .3em 0;
height: 1.6em;
border-radius: 4px;
}
.heroes li.selected:hover {
background-color: #BBD8DC !important;
color: white;
}
.heroes li:hover {
color: #607D8B;
background-color: #DDD;
left: .1em;
}
.heroes .text {
position: relative;
top: -3px;
}
.heroes .badge {
display: inline-block;
font-size: small;
color: white;
padding: 0.8em 0.7em 0 0.7em;
background-color: #607D8B;
line-height: 1em;
position: relative;
left: -1px;
top: -4px;
height: 1.8em;
margin-right: .8em;
border-radius: 4px 0 0 4px;
}
.selected {
background-color: #CFD8DC !important;
color: white;
}

View File

@ -1,21 +0,0 @@
<!-- #docplaster -->
<!-- #docregion -->
<h1>{{title}}</h1>
<h2>My Heroes</h2>
<ul class="heroes">
<li *ngFor="let hero of heroes"
[class.selected]="hero === selectedHero"
(click)="onSelect(hero)">
<span class="badge">{{hero.id}}</span> {{hero.name}}
</li>
</ul>
<div *ngIf="selectedHero">
<h2>{{selectedHero.name}} details!</h2>
<div><label>id: </label>{{selectedHero.id}}</div>
<div>
<label>name: </label>
<!-- #docregion selected-hero -->
<input [(ngModel)]="selectedHero.name" placeholder="name"/>
<!-- #enddocregion selected-hero -->
</div>
</div>

View File

@ -1,23 +0,0 @@
// #docplaster
// #docregion
import { Component } from '@angular/core';
import { Hero, HEROES } from './hero';
@Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
// #docregion class, class-skeleton
export class AppComponent {
// #enddocregion class-skeleton
title = 'Authors Style Guide Sample';
heroes = HEROES;
selectedHero: Hero;
onSelect(hero: Hero): void {
this.selectedHero = hero;
}
// #docregion class-skeleton
}
// #enddocregion class, class-skeleton

View File

@ -1,15 +0,0 @@
// #docregion
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { FormsModule } from '@angular/forms';
import { AppComponent } from './app.component';
// #docregion class
@NgModule({
imports: [ BrowserModule, FormsModule ],
declarations: [ AppComponent ],
bootstrap: [ AppComponent ]
})
export class AppModule { }
// #enddocregion class

View File

@ -1,11 +0,0 @@
export class Hero {
id: number;
name: string;
}
export const HEROES: Hero[] = [
{ id: 11, name: 'Mr. Nice' },
{ id: 12, name: 'Narco' },
{ id: 13, name: 'Bombasto' },
{ id: 14, name: 'Celeritas' }
];

View File

@ -1,10 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<title>Second Authors Style Guide</title>
</head>
<body>
<h1>Second Authors Style Guide</h1>
<p>Placeholder. Does nothing at all.</p>
</body>
</html>

View File

@ -1,30 +0,0 @@
<!DOCTYPE html>
<!-- #docregion -->
<html>
<head>
<title>Docs Style Guide</title>
<base href="/">
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- #docregion styles -->
<link rel="stylesheet" href="styles.css">
<!-- #enddocregion styles -->
<!-- Polyfills -->
<script src="node_modules/core-js/client/shim.min.js"></script>
<script src="node_modules/zone.js/dist/zone.js"></script>
<script src="node_modules/systemjs/dist/system.src.js"></script>
<script src="systemjs.config.js"></script>
<script>
System.import('main.js').catch(function(err){ console.error(err); });
</script>
</head>
<body>
<my-app>Loading...</my-app>
</body>
</html>

View File

@ -1,4 +0,0 @@
// #docregion
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { AppModule } from './app/app.module';
platformBrowserDynamic().bootstrapModule(AppModule);

6
aio/content/examples/i18n/.gitignore vendored Normal file
View File

@ -0,0 +1,6 @@
**/*.ngfactory.ts
**/*.metadata.json
dist
!app/tsconfig.json
!rollup.js
!src/systemjs-text-plugin.js

View File

@ -30,8 +30,4 @@ describe('i18n E2E Tests', () => {
expect(element.all(by.css('span')).get(1).getText()).toBe('El heroe es mujer');
});
it('should display the nested expression', function() {
expect(element.all(by.css('span')).get(2).getText()).toBe('Aquí tenemos: 3 mujeres');
});
});

View File

@ -2,10 +2,8 @@
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
<file source-language="en" datatype="plaintext" original="ng2.template">
<body>
<trans-unit id="introductionHeader" datatype="html">
<source>
Hello i18n!
</source>
<trans-unit id="af2ccf4b5dba59616e92cf1531505af02da8f6d2" datatype="html">
<source>Hello i18n!</source>
<target/>
<note priority="1" from="description">An introduction header for this sample</note>
<note priority="1" from="meaning">User welcome</note>
@ -26,6 +24,12 @@ I don&apos;t output any element either
<source>Angular logo</source>
<target/>
</trans-unit>
<trans-unit id="2579611bfcccd75bcd41fac90150d27d6ebb30b8" datatype="html">
<source>
<x id="START_TAG_SPAN" ctype="x-span"/><x id="ICU"/><x id="CLOSE_TAG_SPAN" ctype="x-span"/>
</source>
<target/>
</trans-unit>
<trans-unit id="6e22e74e8cbd3095560cfe08993c4fdfa3c50eb0" datatype="html">
<source/>
<target/>
@ -38,14 +42,6 @@ I don&apos;t output any element either
<source/>
<target/>
</trans-unit>
<trans-unit id="2cf9a08c5b6e3612572a2a36dd46563013848382" datatype="html">
<source>Here we have: <x id="ICU"/></source>
<target/>
</trans-unit>
<trans-unit id="db1b921b55301ce3957e382090729562002da036" datatype="html">
<source/>
<target/>
</trans-unit>
</body>
</file>
</xliff>

View File

@ -10,23 +10,6 @@
<h1 i18n="An introduction header for this sample">Hello i18n!</h1>
<!--#enddocregion i18n-attribute-desc-->
<!--#docregion i18n-attribute-meaning-->
<h1 i18n="site header|An introduction header for this sample">Hello i18n!</h1>
<!--#enddocregion i18n-attribute-meaning-->
<!--#docregion i18n-attribute-id-->
<h1 i18n="An introduction header for this sample@@introductionHeader">Hello i18n!</h1>
<!--#enddocregion i18n-attribute-id-->
<!--#docregion i18n-attribute-meaning-and-id-->
<h1 i18n="site header|An introduction header for this sample@@introductionHeader">Hello i18n!</h1>
<!--#enddocregion i18n-attribute-meaning-and-id-->
<!--#docregion i18n-attribute-solo-id-->
<h1 i18n="@@introductionHeader">Hello i18n!</h1>
<!--#enddocregion i18n-attribute-solo-id-->
<!--#docregion i18n-title-->
<img [src]="logo" title="Angular logo">
<!--#enddocregion i18n-title-->
Contact GitHub API Training Shop Blog About

View File

@ -1,8 +1,6 @@
<!--#docregion-->
<!--#docregion i18n-attribute-meaning-->
<h1 i18n="User welcome|An introduction header for this sample@@introductionHeader">
Hello i18n!
</h1>
<h1 i18n="User welcome|An introduction header for this sample">Hello i18n!</h1>
<!--#enddocregion i18n-attribute-meaning-->
<!--#docregion i18n-ng-container-->
@ -33,11 +31,4 @@ I don't output any element either
<!--#docregion i18n-select-->
<span i18n>The hero is {gender, select, m {male} f {female}}</span>
<!--#enddocregion i18n-select-->
<br><br>
<!--#docregion i18n-nested-->
<span i18n>Here we have: {count, plural,
=0 {no one}
=1 {one {gender, select, male {man} female {woman}}}
other {{{heroes.length}} {gender, select, male {men} female {women}}}
}</span>
<!--#enddocregion i18n-nested-->
<br>

View File

@ -10,8 +10,6 @@ export class AppComponent {
gender = 'f';
fly = true;
logo = 'https://angular.io/resources/images/logos/angular/angular.png';
count = 3;
heroes: string[] = ['Magneta', 'Celeritas', 'Dynama'];
inc(i: number) {
this.wolves = Math.min(5, Math.max(0, this.wolves + i));
}

View File

@ -1,7 +1,5 @@
// #docplaster
// #docregion without-missing-translation
import { TRANSLATIONS, TRANSLATIONS_FORMAT, LOCALE_ID, MissingTranslationStrategy } from '@angular/core';
import { CompilerConfig } from '@angular/compiler';
// #docregion
import { TRANSLATIONS, TRANSLATIONS_FORMAT, LOCALE_ID } from '@angular/core';
export function getTranslationProviders(): Promise<Object[]> {
@ -19,18 +17,13 @@ export function getTranslationProviders(): Promise<Object[]> {
// Ex: 'locale/messages.es.xlf`
const translationFile = `./locale/messages.${locale}.xlf`;
// #docregion missing-translation
return getTranslationsWithSystemJs(translationFile)
.then( (translations: string ) => [
{ provide: TRANSLATIONS, useValue: translations },
{ provide: TRANSLATIONS_FORMAT, useValue: 'xlf' },
{ provide: LOCALE_ID, useValue: locale },
// #enddocregion without-missing-translation
{ provide: CompilerConfig, useValue: new CompilerConfig({ missingTranslation: MissingTranslationStrategy.Error }) }
// #docregion without-missing-translation
{ provide: LOCALE_ID, useValue: locale }
])
.catch(() => noProviders); // ignore if file not found
// #enddocregion missing-translation
}
declare var System: any;
@ -38,4 +31,3 @@ declare var System: any;
function getTranslationsWithSystemJs(file: string) {
return System.import(file + '!text'); // relies on text plugin
}
// #enddocregion without-missing-translation

View File

@ -2,7 +2,7 @@
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
<file source-language="en" datatype="plaintext" original="ng2.template">
<body>
<trans-unit id="introductionHeader" datatype="html">
<trans-unit id="af2ccf4b5dba59616e92cf1531505af02da8f6d2" datatype="html">
<source>Hello i18n!</source>
<target>¡Hola i18n!</target>
<note priority="1" from="description">An introduction header for this sample</note>
@ -36,20 +36,6 @@ I don&apos;t output any element either
<source/>
<target>{gender, select, m {hombre} f {mujer}}</target>
</trans-unit>
<trans-unit id="2cf9a08c5b6e3612572a2a36dd46563013848382" datatype="html">
<source>Here we have: <x id="ICU"/></source>
<target>Aquí tenemos: <x id="ICU"/></target>
</trans-unit>
<trans-unit id="db1b921b55301ce3957e382090729562002da036" datatype="html">
<source/>
<target>
{count, plural,
=0 { nadie }
=1 {{gender, select, m {un hombre} f {una mujer}}}
other {{{heroes.length}} {gender, select, m {hombres} f {mujeres}}}
}
</target>
</trans-unit>
</body>
</file>
</xliff>

View File

@ -5,9 +5,7 @@
<file source-language="en" datatype="plaintext" original="ng2.template">
<body>
<!-- #docregion translated-hello -->
<!-- #docregion custom-id -->
<trans-unit id="introductionHeader" datatype="html">
<!-- #enddocregion custom-id -->
<trans-unit id="af2ccf4b5dba59616e92cf1531505af02da8f6d2" datatype="html">
<source>Hello i18n!</source>
<target>¡Hola i18n!</target>
<note priority="1" from="description">An introduction header for this sample</note>
@ -15,9 +13,7 @@
</trans-unit>
<!-- #enddocregion translated-hello -->
<!-- #docregion translated-other-nodes -->
<!-- #docregion generated-id -->
<trans-unit id="ba0cc104d3d69bf669f97b8d96a4c5d8d9559aa3" datatype="html">
<!-- #enddocregion generated-id -->
<source>I don&apos;t output any element</source>
<target>No genero ningún elemento</target>
</trans-unit>
@ -52,34 +48,6 @@
</trans-unit>
<!-- #enddocregion translate-select-2 -->
<!-- #enddocregion translated-select -->
<trans-unit id="db04527df562d12c8607eab2b5723ef6e2066ba0" datatype="html">
<source>Here we have: <x id="ICU"/></source>
<target/>
</trans-unit>
<trans-unit id="000058be4e6f08b685d1d0a70f9da68067df7379" datatype="html">
<source/>
<target/>
</trans-unit>
<!-- #docregion translate-nested -->
<!-- #docregion translate-nested-1 -->
<trans-unit id="2cf9a08c5b6e3612572a2a36dd46563013848382" datatype="html">
<source>Here we have: <x id="ICU"/></source>
<target>Aquí tenemos: <x id="ICU"/></target>
</trans-unit>
<!-- #enddocregion translate-nested-1 -->
<!-- #docregion translate-nested-2 -->
<trans-unit id="db1b921b55301ce3957e382090729562002da036" datatype="html">
<source/>
<target>
{count, plural,
=0 { nadie }
=1 {{gender, select, m {un hombre} f {una mujer}}}
other {{{heroes.length}} {gender, select, m {hombres} f {mujeres}}}
}
</target>
</trans-unit>
<!-- #enddocregion translate-nested-2 -->
<!-- #enddocregion translate-nested -->
</body>
</file>
</xliff>

View File

@ -1,47 +0,0 @@
/* items class */
.items {
margin: 0 0 2em 0;
list-style-type: none;
padding: 0;
width: 24em;
}
.items li {
cursor: pointer;
position: relative;
left: 0;
background-color: #EEE;
margin: .5em;
padding: .3em 0;
height: 1.6em;
border-radius: 4px;
}
.items li:hover {
color: #607D8B;
background-color: #DDD;
left: .1em;
}
.items li.selected {
background-color: #CFD8DC;
color: white;
}
.items li.selected:hover {
background-color: #BBD8DC;
}
.items .text {
position: relative;
top: -3px;
}
.items .badge {
display: inline-block;
font-size: small;
color: white;
padding: 0.8em 0.7em 0 0.7em;
background-color: #607D8B;
line-height: 1em;
position: relative;
left: -1px;
top: -4px;
height: 1.8em;
margin-right: .8em;
border-radius: 4px 0 0 4px;
}

View File

@ -10,7 +10,6 @@
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="styles.css">
<link rel="stylesheet" href="app.css">
<!-- Polyfills -->
<script src="node_modules/core-js/client/shim.min.js"></script>

View File

@ -27,7 +27,7 @@ describe('AppComponent', function () {
it('should have expected <h1> text', () => {
fixture.detectChanges();
const h1 = de.nativeElement;
expect(h1.textContent).toMatch(/angular/i,
expect(h1.innerText).toMatch(/angular/i,
'<h1> should say something about "Angular"');
});
});

View File

@ -0,0 +1,2 @@
*.js
!systemjs.custom.js

View File

@ -36,7 +36,6 @@
<a href="#inputs-and-outputs">Inputs and outputs</a><br>
<a href="#pipes">Pipes</a><br>
<a href="#safe-navigation-operator">Safe navigation operator <i>?.</i></a><br>
<a href="#non-null-assertion-operator">Non-null assertion operator <i>!.</i></a><br>
<a href="#enums">Enums</a><br>
<!-- Interpolation and expressions -->
@ -804,12 +803,6 @@ The null hero's name is {{nullHero && nullHero.name}}
<!-- #enddocregion safe-6 -->
</div>
<a class="to-toc" href="#toc">top</a>
<!-- non-null assertion operator -->
<hr><h2 id="non-null-assertion-operator">Non-null assertion operator <i>!.</i></h2>
<div>
<!-- #docregion non-null-assertion-1 -->
<!--No hero, no text -->

View File

@ -111,7 +111,7 @@ export class AppComponent implements AfterViewInit, OnInit {
}
onSave(event: KeyboardEvent) {
let evtMsg = event ? ' Event target is ' + (<HTMLElement>event.target).textContent : '';
let evtMsg = event ? ' Event target is ' + (<HTMLElement>event.target).innerText : '';
this.alert('Saved.' + evtMsg);
if (event) { event.stopPropagation(); }
}
@ -127,7 +127,6 @@ export class AppComponent implements AfterViewInit, OnInit {
resetHeroes() {
this.heroes = Hero.heroes.map(hero => hero.clone());
this.currentHero = this.heroes[0];
this.hero = this.currentHero;
this.heroesWithTrackByCountReset = 0;
}
@ -173,8 +172,8 @@ function trackChanges(views: QueryList<ElementRef>, changed: () => void) {
let oldRefs = views.toArray();
views.changes.subscribe((changes: QueryList<ElementRef>) => {
const changedRefs = changes.toArray();
// Check if every changed Element is the same as old and in the same position
const isSame = oldRefs.every((v, i) => v.nativeElement === changedRefs[i].nativeElement);
// Is every changed ElemRef the same as old and in the same position
const isSame = oldRefs.every((v, i) => v === changedRefs[i]);
if (!isSame) {
oldRefs = changedRefs;
// wait a tick because called after views are constructed

View File

@ -0,0 +1 @@
!src/browser-test-shim.js

View File

@ -1,22 +0,0 @@
/* Master Styles */
h1 {
color: #369;
font-family: Arial, Helvetica, sans-serif;
font-size: 250%;
}
h2, h3 {
color: #444;
font-family: Arial, Helvetica, sans-serif;
font-weight: lighter;
}
body {
margin: 2em;
}
body, input[text], button {
color: #888;
font-family: Cambria, Georgia;
}
/* everywhere else */
* {
font-family: Arial, Helvetica, sans-serif;
}

View File

@ -0,0 +1,8 @@
aot/**/*.ts
**/*.ngfactory.ts
**/*.ngsummary.json
**/*.metadata.json
**/*.js
dist
!app/tsconfig.json
!/*.js

View File

@ -0,0 +1 @@
!karma.conf.ajs.js

View File

@ -0,0 +1,8 @@
aot/**/*
!aot/index.html
dist
!app/tsconfig.json
!rollup-config.js
!karma.conf.ajs.js
!copy-dist-files.js
!systemjs.config.1.js

View File

@ -1,6 +1,11 @@
// #docregion bootstrap
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { UpgradeModule } from '@angular/upgrade/static';
import { AppModule } from './app.module';
platformBrowserDynamic().bootstrapModule(AppModule);
platformBrowserDynamic().bootstrapModule(AppModule).then(platformRef => {
const upgrade = platformRef.injector.get(UpgradeModule) as UpgradeModule;
upgrade.bootstrap(document.documentElement, ['phonecatApp']);
});
// #enddocregion bootstrap

View File

@ -7,6 +7,12 @@ import { browser, element, by } from 'protractor';
describe('PhoneCat Application', function() {
beforeAll(function () {
// Set protractor to hybrid mode.
browser.rootEl = 'body';
browser.ng12Hybrid = true;
});
it('should redirect `index.html` to `index.html#!/phones', function() {
browser.get('index.html');
expect(browser.getLocationAbsUrl()).toBe('/phones');
@ -64,7 +70,7 @@ describe('PhoneCat Application', function() {
query.sendKeys('nexus');
element.all(by.css('.phones li a')).first().click();
browser.sleep(1000); // Not sure why this is needed but it is. The route change works fine.
browser.sleep(200); // Not sure why this is needed but it is. The route change works fine.
expect(browser.getLocationAbsUrl()).toBe('/phones/nexus-s');
});

View File

@ -0,0 +1 @@
!tsconfig.json

View File

@ -0,0 +1,5 @@
dist
!karma.webpack.conf.js
!webpack.config.js
!config/*
!public/css/styles.css

View File

@ -9,14 +9,14 @@
},
"license": "MIT",
"dependencies": {
"@angular/common": "~4.2.0",
"@angular/compiler": "~4.2.0",
"@angular/core": "~4.2.0",
"@angular/forms": "~4.2.0",
"@angular/http": "~4.2.0",
"@angular/platform-browser": "~4.2.0",
"@angular/platform-browser-dynamic": "~4.2.0",
"@angular/router": "~4.2.0",
"@angular/common": "~4.0.0",
"@angular/compiler": "~4.0.0",
"@angular/core": "~4.0.0",
"@angular/forms": "~4.0.0",
"@angular/http": "~4.0.0",
"@angular/platform-browser": "~4.0.0",
"@angular/platform-browser-dynamic": "~4.0.0",
"@angular/router": "~4.0.0",
"core-js": "^2.4.1",
"rxjs": "5.0.1",
"zone.js": "^0.8.4"
@ -41,7 +41,7 @@
"raw-loader": "^0.5.1",
"rimraf": "^2.5.2",
"style-loader": "^0.13.1",
"typescript": "~2.3.1",
"typescript": "~2.0.10",
"webpack": "2.2.1",
"webpack-dev-server": "2.4.1",
"webpack-merge": "^3.0.0"

View File

@ -1,8 +1,8 @@
# Bootstrapping
# AppModule: the root module
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](guide/bootstrapping#main) to launch the application.
Every application has at least one Angular module, the _root_ module
that you [bootstrap](guide/appmodule#main) to launch the application.
You can call it anything you want. The conventional name is `AppModule`.
The [setup](guide/setup) instructions produce a new project with the following minimal `AppModule`.
@ -10,6 +10,7 @@ You'll evolve this module as your application grows.
<code-example path="setup/src/app/app.module.ts" title="src/app/app.module.ts" linenums="false">
</code-example>
@ -25,7 +26,7 @@ The `@NgModule` decorator identifies `AppModule` as an Angular module class (als
* **_bootstrap_** &mdash; the _root_ component that Angular creates and inserts into the `index.html` host web page.
The [Angular Modules (NgModule)](guide/ngmodule) 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.
All you need to know at the moment is a few basics about these three properties.
{@a imports}
@ -34,7 +35,7 @@ All you need to know at the moment is a few basics about these three properties.
### 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.
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.
@ -66,7 +67,7 @@ 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.
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.
@ -85,10 +86,10 @@ that the application needs to function properly.
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.
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 &mdash;
You'll learn to create two other kinds of classes &mdash;
[directives](guide/attribute-directives) and [pipes](guide/pipes) &mdash;
that you must also add to the `declarations` array.
@ -97,7 +98,7 @@ that you must also add to the `declarations` array.
**Only _declarables_** &mdash; _components_, _directives_ and _pipes_ &mdash; belong in the `declarations` array.
**Only _declarables_** &mdash; _components_, _directives_ and _pipes_ &mdash; belong in the `declarations` array.
Do not put any other kind of class in `declarations`; _not_ `NgModule` classes, _not_ service classes, _not_ model classes.
@ -110,14 +111,14 @@ Do not put any other kind of class in `declarations`; _not_ `NgModule` classes,
### The _bootstrap_ array
You launch the application by [_bootstrapping_](guide/bootstrapping#main) the root `AppModule`.
You launch the application by [_bootstrapping_](guide/appmodule#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.
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`.
@ -142,7 +143,7 @@ The variations depend upon how you want to compile the application and where you
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
The recommended place to bootstrap a JIT-compiled browser application is in a separate file
in the `src` folder named `src/main.ts`
<code-example path="setup/src/main.ts" title="src/main.ts" linenums="false">
@ -155,10 +156,10 @@ 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,
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 &mdash; here and in most documentation samples &mdash; is `my-app`
The `AppComponent` selector &mdash; here and in most documentation samples &mdash; is `my-app`
so Angular looks for a `<my-app>` tag in the `index.html` like this one ...
<code-example path="setup/src/index.html" region="my-app" title="setup/src/index.html" linenums="false">

View File

@ -38,7 +38,7 @@ This page introduces modules; the [Angular modules](guide/ngmodule) page covers
<br class="clear">
Every Angular app has at least one Angular module class, [the _root module_](guide/bootstrapping "AppModule: the root module"),
Every Angular app has at least one Angular module class, [the _root module_](guide/appmodule "AppModule: the root module"),
conventionally named `AppModule`.
While the _root module_ may be the only module in a small application, most apps have many more

View File

@ -0,0 +1,617 @@
# CLI QuickStart
Good tools make application development quicker and easier to maintain than
if you did everything by hand.
The [**Angular CLI**](https://cli.angular.io/) is a **_command line interface_** tool
that can create a project, add files, and perform a variety of ongoing development tasks such
as testing, bundling, and deployment.
The goal in this guide is to build and run a simple Angular
application in TypeScript, using the Angular CLI
while adhering to the [Style Guide](guide/styleguide) recommendations that
benefit _every_ Angular project.
By the end of the chapter, you'll have a basic understanding of development with the CLI
and a foundation for both these documentation samples and for real world applications.
<!--
You'll pursue these ends in the following high-level steps:
1. [Set up](guide/cli-quickstart#devenv) the development environment.
2. [Create](guide/cli-quickstart#create-proj) a new project and skeleton application.
3. [Serve](guide/cli-quickstart#serve) the application.
4. [Edit](guide/cli-quickstart#first-component) the application.
-->
And you can also <a href="generated/zips/cli-quickstart/cli-quickstart.zip" target="_blank">download the example.</a>
<h2 id='devenv'>
Step 1. Set up the Development Environment
</h2>
You need to set up your development environment before you can do anything.
Install **[Node.js® and npm](https://nodejs.org/en/download/)**
if they are not already on your machine.
<div class="l-sub-section">
**Verify that you are running at least node `6.9.x` and npm `3.x.x`**
by running `node -v` and `npm -v` in a terminal/console window.
Older versions produce errors, but newer versions are fine.
</div>
Then **install the [Angular CLI](https://github.com/angular/angular-cli)** globally.
<code-example language="sh" class="code-shell">
npm install -g @angular/cli
</code-example>
<h2 id='create-proj'>
Step 2. Create a new project
</h2>
Open a terminal window.
Generate a new project and skeleton application by running the following commands:
<code-example language="sh" class="code-shell">
ng new my-app
</code-example>
<div class="l-sub-section">
Patience please.
It takes time to set up a new project, most of it spent installing npm packages.
</div>
<h2 id='serve'>
Step 3: Serve the application
</h2>
Go to the project directory and launch the server.
<code-example language="sh" class="code-shell">
cd my-app
ng serve --open
</code-example>
The `ng serve` command launches the server, watches your files,
and rebuilds the app as you make changes to those files.
Using the `--open` (or just `-o`) option will automatically open your browser
on `http://localhost:4200/`.
Your app greets you with a message:
<figure>
<img src='generated/images/guide/cli-quickstart/app-works.png' alt="The app works!">
</figure>
<h2 id='first-component'>
Step 4: Edit your first Angular component
</h2>
The CLI created the first Angular component for you.
This is the _root component_ and it is named `app-root`.
You can find it in `./src/app/app.component.ts`.
Open the component file and change the `title` property from _app works!_ to _My First Angular App_:
<code-example path="cli-quickstart/src/app/app.component.ts" region="title" title="src/app/app.component.ts" linenums="false"></code-example>
The browser reloads automatically with the revised title. That's nice, but it could look better.
Open `src/app/app.component.css` and give the component some style.
<code-example path="cli-quickstart/src/app/app.component.css" title="src/app/app.component.css" linenums="false"></code-example>
<figure>
<img src='generated/images/guide/cli-quickstart/my-first-app.png' alt="Output of QuickStart app">
</figure>
Looking good!
## What's next?
That's about all you'd expect to do in a "Hello, World" app.
You're ready to take the [Tour of Heroes Tutorial](tutorial) and build
a small application that demonstrates the great things you can build with Angular.
Or you can stick around a bit longer to learn about the files in your brand new project.
## Project file review
An Angular CLI project is the foundation for both quick experiments and enterprise solutions.
The first file you should check out is `README.md`.
It has some basic information on how to use CLI commands.
Whenever you want to know more about how Angular CLI works make sure to visit
[the Angular CLI repository](https://github.com/angular/angular-cli) and
[Wiki](https://github.com/angular/angular-cli/wiki).
Some of the generated files might be unfamiliar to you.
### The `src` folder
Your app lives in the `src` folder.
All Angular components, templates, styles, images, and anything else your app needs go here.
Any files outside of this folder are meant to support building your app.
<div class='filetree'>
<div class='file'>src</div>
<div class='children'>
<div class='file'>app</div>
<div class='children'>
<div class='file'>app.component.css</div>
<div class='file'>app.component.html</div>
<div class="file">app.component.spec.ts</div>
<div class="file">app.component.ts</div>
<div class="file">app.module.ts</div>
</div>
<div class="file">assets</div>
<div class='children'>
<div class="file">.gitkeep</div>
</div>
<div class="file">environments</div>
<div class='children'>
<div class="file">environment.prod.ts</div>
<div class="file">environment.ts</div>
</div>
<div class="file">favicon.ico</div>
<div class="file">index.html</div>
<div class="file">main.ts</div>
<div class="file">polyfills.ts</div>
<div class="file">styles.css</div>
<div class="file">test.ts</div>
<div class="file">tsconfig.app.json</div>
<div class="file">tsconfig.spec.json</div>
</div>
</div>
<style>
td, th {vertical-align: top}
</style>
<table width="100%">
<col width="20%">
</col>
<col width="80%">
</col>
<tr>
<th>
File
</th>
<th>
Purpose
</th>
</tr>
<tr>
<td>
`app/app.component.{ts,html,css,spec.ts}`
</td>
<td>
Defines the `AppComponent` along with an HTML template, CSS stylesheet, and a unit test.
It is the **root** component of what will become a tree of nested components
as the application evolves.
</td>
</tr>
<tr>
<td>
`app/app.module.ts`
</td>
<td>
Defines `AppModule`, the [root module](guide/appmodule "AppModule: the root module") that tells Angular how to assemble the application.
Right now it declares only the `AppComponent`.
Soon there will be more components to declare.
</td>
</tr>
<tr>
<td>
`assets/*`
</td>
<td>
A folder where you can put images and anything else to be copied wholesale
when you build your application.
</td>
</tr>
<tr>
<td>
`environments/*`
</td>
<td>
This folder contains one file for each of your destination environments,
each exporting simple configuration variables to use in your application.
The files are replaced on-the-fly when you build your app.
You might use a different API endpoint for development than you do for production
or maybe different analytics tokens.
You might even use some mock services.
Either way, the CLI has you covered.
</td>
</tr>
<tr>
<td>
`favicon.ico`
</td>
<td>
Every site wants to look good on the bookmark bar.
Get started with your very own Angular icon.
</td>
</tr>
<tr>
<td>
`index.html`
</td>
<td>
The main HTML page that is served when someone visits your site.
Most of the time you'll never need to edit it.
The CLI automatically adds all `js` and `css` files when building your app so you
never need to add any `&lt;script&gt;` or `&lt;link&gt;` tags here manually.
</td>
</tr>
<tr>
<td>
`main.ts`
</td>
<td>
The main entry point for your app.
Compiles the application with the [JIT compiler](guide/glossary#jit)
and bootstraps the application's root module (`AppModule`) to run in the browser.
You can also use the [AOT compiler](guide/glossary#ahead-of-time-aot-compilation)
without changing any code by passing in `--aot` to `ng build` or `ng serve`.
</td>
</tr>
<tr>
<td>
`polyfills.ts`
</td>
<td>
Different browsers have different levels of support of the web standards.
Polyfills help normalize those differences.
You should be pretty safe with `core-js` and `zone.js`, but be sure to check out
the [Browser Support guide](guide/browser-support) for more information.
</td>
</tr>
<tr>
<td>
`styles.css`
</td>
<td>
Your global styles go here.
Most of the time you'll want to have local styles in your components for easier maintenance,
but styles that affect all of your app need to be in a central place.
</td>
</tr>
<tr>
<td>
`test.ts`
</td>
<td>
This is the main entry point for your unit tests.
It has some custom configuration that might be unfamiliar, but it's not something you'll
need to edit.
</td>
</tr>
<tr>
<td>
`tsconfig.{app|spec}.json`
</td>
<td>
TypeScript compiler configuration for the Angular app (`tsconfig.app.json`)
and for the unit tests (`tsconfig.spec.json`).
</td>
</tr>
</table>
### The root folder
The `src/` folder is just one of the items inside the project's root folder.
Other files help you build, test, maintain, document, and deploy the app.
These files go in the root folder next to `src/`.
<div class='filetree'>
<div class="file">my-app</div>
<div class='children'>
<div class="file">e2e</div>
<div class='children'>
<div class="file">app.e2e-spec.ts</div>
<div class="file">app.po.ts</div>
<div class="file">tsconfig.e2e.json</div>
</div>
<div class="file">node_modules/...</div>
<div class="file">src/...</div>
<div class="file">.angular-cli.json</div>
<div class="file">.editorconfig</div>
<div class="file">.gitignore</div>
<div class="file">karma.conf.js</div>
<div class="file">package.json</div>
<div class="file">protractor.conf.js</div>
<div class="file">README.md</div>
<div class="file">tsconfig.json</div>
<div class="file">tslint.json</div>
</div>
</div>
<style>
td, th {vertical-align: top}
</style>
<table width="100%">
<col width="20%">
</col>
<col width="80%">
</col>
<tr>
<th>
File
</th>
<th>
Purpose
</th>
</tr>
<tr>
<td>
`e2e/`
</td>
<td>
Inside `e2e/` live the End-to-End tests.
They shouldn't be inside `src/` because e2e tests are really a separate app that
just so happens to test your main app.
That's also why they have their own `tsconfig.e2e.json`.
</td>
</tr>
<tr>
<td>
`node_modules/`
</td>
<td>
`Node.js` creates this folder and puts all third party modules listed in
`package.json` inside of it.
</td>
</tr>
<tr>
<td>
`.angular-cli.json`
</td>
<td>
Configuration for Angular CLI.
In this file you can set several defaults and also configure what files are included
when your project is build.
Check out the official documentation if you want to know more.
</td>
</tr>
<tr>
<td>
`.editorconfig`
</td>
<td>
Simple configuration for your editor to make sure everyone that uses your project
has the same basic configuration.
Most editors support an `.editorconfig` file.
See http://editorconfig.org for more information.
</td>
</tr>
<tr>
<td>
`.gitignore`
</td>
<td>
Git configuration to make sure autogenerated files are not commited to source control.
</td>
</tr>
<tr>
<td>
`karma.conf.js`
</td>
<td>
Unit test configuration for the [Karma test runner](https://karma-runner.github.io),
used when running `ng test`.
</td>
</tr>
<tr>
<td>
`package.json`
</td>
<td>
`npm` configuration listing the third party packages your project uses.
You can also add your own [custom scripts](https://docs.npmjs.com/misc/scripts) here.
</td>
</tr>
<tr>
<td>
`protractor.conf.js`
</td>
<td>
End-to-end test configuration for [Protractor](http://www.protractortest.org/),
used when running `ng e2e`.
</td>
</tr>
<tr>
<td>
`README.md`
</td>
<td>
Basic documentation for your project, pre-filled with CLI command information.
Make sure to enhance it with project documentation so that anyone
checking out the repo can build your app!
</td>
</tr>
<tr>
<td>
`tsconfig.json`
</td>
<td>
TypeScript compiler configuration for your IDE to pick up and give you helpful tooling.
</td>
</tr>
<tr>
<td>
`tslint.json`
</td>
<td>
Linting configuration for [TSLint](https://palantir.github.io/tslint/) together with
[Codelyzer](http://codelyzer.com/), used when running `ng lint`.
Linting helps keep your code style consistent.
</td>
</tr>
</table>
<div class="l-sub-section">
### Next Step
If you're new to Angular, continue with the
[tutorial](tutorial "Tour of Heroes tutorial").
You can skip the "Setup" step since you're already using the Angular CLI setup.
</div>

File diff suppressed because it is too large Load Diff

View File

@ -1,21 +1,27 @@
# Form Validation
{@a top}
Improve overall data quality by validating user input for accuracy and completeness.
This page shows how to validate user input in the UI and display useful validation messages
using first the Template Driven Forms and then the Reactive Forms approach.
This cookbook shows how to validate user input in the UI and display useful validation messages
using first the template-driven forms and then the reactive forms approach.
<div class="l-sub-section">
Read more about these choices in the [Forms](guide/forms)
and the [Reactive Forms](guide/reactive-forms) guides.
</div>
{@a toc}
{@a live-example}
@ -28,29 +34,17 @@ and the [Reactive Forms](guide/reactive-forms) guides.
## Built-in validators
Angular forms include a number of built-in validator functions, which are functions
that help you check common user input in forms. In addition to the built-in
validators covered here of `minlength`, `maxlength`,
and `required`, there are others such as `min`, `max`, `email` and `pattern`
for Template Driven as well as Reactive Forms.
For a full list of built-in validators,
see the [Validators](api/forms/Validators) API reference.
{@a template1}
## Simple template-driven forms
## Simple Template Driven Forms
In the Template Driven approach, you arrange
In the template-driven approach, you arrange
[form elements](https://developer.mozilla.org/en-US/docs/Web/Guide/HTML/Forms_in_HTML) in the component's template.
You add Angular form directives (mostly directives beginning `ng...`) to help
Angular construct a corresponding internal control model that implements form functionality.
In Template Driven forms, the control model is _implicit_ in the template.
In template-drive forms, the control model is _implicit_ in the template.
To validate user input, you add [HTML validation attributes](https://developer.mozilla.org/en-US/docs/Web/Guide/HTML/HTML5/Constraint_validation)
to the elements. Angular interprets those as well, adding validator functions to the control model.
@ -82,8 +76,7 @@ This gives you a reference to the Angular `NgModel` directive
associated with this control that you can use _in the template_
to check for control states such as `valid` and `dirty`.
* The `*ngIf` on the `<div>` element reveals a set of nested message `divs`
but only if there are `name` errors and
* The `*ngIf` on the `<div>` element reveals a set of nested message `divs` but only if there are "name" errors and
the control is either `dirty` or `touched`.
* Each nested `<div>` can present a custom message for one of the possible validation errors.
@ -119,9 +112,9 @@ as well as other code to support the view.
Use this Template Driven validation technique when working with static forms with simple, standard validation rules.
Use this template-driven validation technique when working with static forms with simple, standard validation rules.
Here are the complete files for the first version of `HeroFormTemplateCompononent` in the Template Driven approach:
Here are the complete files for the first version of `HeroFormTemplateCompononent` in the template-driven approach:
<code-tabs>
@ -139,8 +132,10 @@ Here are the complete files for the first version of `HeroFormTemplateCompononen
{@a template2}
## Template Driven Forms with validation messages in code
## Template-driven forms with validation messages in code
While the layout is straightforward,
there are obvious shortcomings with the way it's handling validation messages:
@ -157,7 +152,7 @@ In this example, you can move the logic and the messages into the component with
the template and component.
Here's the hero name again, excerpted from the revised template
(template 2), next to the original version:
(Template 2), next to the original version:
<code-tabs>
@ -179,14 +174,14 @@ The `<input>` element HTML is almost the same. There are noteworthy differences:
* There's a new attribute, `forbiddenName`, that is actually a custom validation directive.
It invalidates the control if the user enters "bob" in the name `<input>`([try it](guide/form-validation#live-example)).
See the [custom validation](guide/form-validation#custom-validation) section later in this page for more information
See the [custom validation](guide/form-validation#custom-validation) section later in this cookbook for more information
on custom validation directives.
* The `#name` template variable is gone because the app no longer refers to the Angular control for this element.
* Binding to the new `formErrors.name` property is sufficient to display all name validation error messages.
* Binding to the new `formErrors.name` property is sufficent to display all name validation error messages.
{@a component-class}
@ -224,7 +219,7 @@ the name of that variable as a string (`'heroForm'` in this case).
* The `heroForm` object changes several times during the life of the component, most notably when you add a new hero.
Periodically inspecting it reveals these changes.
* Angular calls the `ngAfterViewChecked()` [lifecycle hook method](guide/lifecycle-hooks#afterview)
* Angular calls the `ngAfterViewChecked` [lifecycle hook method](guide/lifecycle-hooks#afterview)
when anything changes in the view.
That's the right time to see if there's a new `heroForm` object.
@ -251,7 +246,7 @@ For each field, the `onValueChanged` handler does the following:
* If such a control exists _and_ it's been changed ("dirty")
_and_ it's invalid, the handler composes a consolidated error message for all of the control's errors.
Next, the component needs some error messages&mdash;a set for each validated property with
Next, the component needs some error messages of course&mdash;a set for each validated property with
one message per validation rule:
<code-example path="form-validation/src/app/template/hero-form-template2.component.ts" region="messages" title="template/hero-form-template2.component.ts (messages)" linenums="false">
@ -283,6 +278,8 @@ Each field has approximately the same number of lines no matter its number of va
The component also grows proportionally, at the rate of one line per validated field
and one line per validation message.
Both trends are manageable.
Now that the messages are in code, you have more flexibility and can compose messages more efficiently.
You can refactor the messages out of the component, perhaps to a service class that retrieves them from the server.
In short, there are more opportunities to improve message handling now that text and logic have moved from template to code.
@ -291,14 +288,14 @@ In short, there are more opportunities to improve message handling now that text
{@a formmodule}
### _FormModule_ and Template Driven forms
### _FormModule_ and template-driven forms
Angular has two different forms modules&mdash;`FormsModule` and
`ReactiveFormsModule`&mdash;that correspond with the
two approaches to form development. Both modules come
from the same `@angular/forms` library package.
You've been reviewing the Template Driven approach which requires the `FormsModule`.
You've been reviewing the "Template-driven" approach which requires the `FormsModule`.
Here's how you imported it in the `HeroFormTemplateModule`.
@ -326,9 +323,9 @@ They're not germane to the validation story. Look at the [live example](guide/fo
{@a reactive}
## Reactive Forms with validation in code
## Reactive forms with validation in code
In the Template Driven approach, you mark up the template with form elements, validation attributes,
In the template-driven approach, you markup the template with form elements, validation attributes,
and `ng...` directives from the Angular `FormsModule`.
At runtime, Angular interprets the template and derives its _form control model_.
@ -337,21 +334,23 @@ You create the form control model in code. You write the template with form elem
and `form...` directives from the Angular `ReactiveFormsModule`.
At runtime, Angular binds the template elements to your control model based on your instructions.
This approach requires a bit more effort. *You have to write the control model and manage it*.
This allows you to do the following:
* Add, change, and remove validation functions on the fly.
* Manipulate the control model dynamically from within the component.
* [Test](guide/form-validation#testing) validation and control logic with isolated unit tests.
The following sample re-writes the hero form in Reactive Forms style.
The following cookbook sample re-writes the hero form in _reactive forms_ style.
{@a reactive-forms-module}
### Switch to the _ReactiveFormsModule_
The Reactive Forms classes and directives come from the Angular `ReactiveFormsModule`, not the `FormsModule`.
The application module for the Reactive Forms feature in this sample looks like this:
The reactive forms classes and directives come from the Angular `ReactiveFormsModule`, not the `FormsModule`.
The application module for the reactive forms feature in this sample looks like this:
<code-example path="form-validation/src/app/reactive/hero-form-reactive.module.ts" title="src/app/reactive/hero-form-reactive.module.ts" linenums="false">
@ -359,7 +358,7 @@ The application module for the Reactive Forms feature in this sample looks like
The Reactive Forms feature module and component are in the `src/app/reactive` folder.
The reactive forms feature module and component are in the `src/app/reactive` folder.
Focus on the `HeroFormReactiveComponent` there, starting with its template.
@ -379,8 +378,8 @@ The `heroForm` is the control model that the component class builds and maintain
Next, modify the template HTML elements to match the Reactive Forms style.
Here is the "name" portion of the template again, revised for Reactive Forms and compared with the Template Driven version:
Next, modify the template HTML elements to match the _reactive forms_ style.
Here is the "name" portion of the template again, revised for reactive forms and compared with the template-driven version:
<code-tabs>
@ -406,13 +405,15 @@ but rather for css styling and accessibility.
<div class="l-sub-section">
Currently, Reactive Forms doesn't add the `required` or `aria-required`
HTML validation attribute to the DOM element
when the control has the `required` validator function.
A future version of reactive forms will add the `required` HTML validation attribute to the DOM element
(and perhaps the `aria-required` attribute) when the control has the `required` validator function.
Until then, apply the `required` attribute _and_ add the `Validator.required` function
to the control model, as you'll see below.
</div>
@ -425,6 +426,15 @@ The reactive approach does not use data binding to move data into and out of the
That's all in code.
<div class="l-sub-section">
The retreat from data binding is a principle of the reactive paradigm rather than a technical limitation.
</div>
{@a reactive-component-class}
@ -437,7 +447,7 @@ Angular no longer derives the control model from the template so you can no long
You can create the Angular form control model explicitly with
the help of the `FormBuilder` class.
Here's the section of code devoted to that process, paired with the Template Driven code it replaces:
Here's the section of code devoted to that process, paired with the template-driven code it replaces:
<code-tabs>
@ -497,17 +507,18 @@ discussed in a separate [section below](guide/form-validation#custom-validation)
Learn more about `FormBuilder` in the [Introduction to FormBuilder](guide/reactive-forms#formbuilder) section of Reactive Forms guide.
</div>
{@a committing-changes}
#### Committing hero value changes
In two-way data binding, the user's changes flow automatically from the controls back to the data model properties.
A Reactive Forms component should not use data binding to
automatically update data model properties.
Reactive forms do not use data binding to update data model properties.
The developer decides _when and how_ to update the data model from control values.
This sample updates the model twice:
@ -522,6 +533,18 @@ The `onSubmit()` method simply replaces the `hero` object with the combined valu
</code-example>
<div class="l-sub-section">
This example is lucky in that the `heroForm.value` properties _just happen_ to
correspond _exactly_ to the hero data object properties.
</div>
The `addHero()` method discards pending changes and creates a brand new `hero` model object.
<code-example path="form-validation/src/app/reactive/hero-form-reactive.component.ts" region="add-hero" title="form-validation/src/app/reactive/hero-form-reactive.component.ts" linenums="false">
@ -533,7 +556,7 @@ The `addHero()` method discards pending changes and creates a brand new `hero` m
Then it calls `buildForm()` again which replaces the previous `heroForm` control model with a new one.
The `<form>` tag's `[formGroup]` binding refreshes the page with the new control model.
Here's the complete reactive component file, compared to the two Template Driven component files.
Here's the complete reactive component file, compared to the two template-driven component files.
<code-tabs>
@ -558,7 +581,7 @@ Here's the complete reactive component file, compared to the two Template Driven
Run the [live example](guide/form-validation#live-example) to see how the reactive form behaves,
and to compare all of the files in this sample.
and to compare all of the files in this cookbook sample.
</div>
@ -571,7 +594,7 @@ and to compare all of the files in this sample.
## Custom validation
This cookbook sample has a custom `forbiddenNameValidator()` function that's applied to both the
Template Driven and the reactive form controls. It's in the `src/app/shared` folder
template-driven and the reactive form controls. It's in the `src/app/shared` folder
and declared in the `SharedModule`.
Here's the `forbiddenNameValidator()` function:
@ -600,7 +623,7 @@ and whose value is an arbitrary dictionary of values that you could insert into
### Custom validation directive
In the Reactive Forms component, the `'name'` control's validator function list
In the reactive forms component, the `'name'` control's validator function list
has a `forbiddenNameValidator` at the bottom.
<code-example path="form-validation/src/app/reactive/hero-form-reactive.component.ts" region="name-validators" title="reactive/hero-form-reactive.component.ts (name validators)" linenums="false">
@ -609,7 +632,7 @@ has a `forbiddenNameValidator` at the bottom.
In the Template Driven example, the `<input>` has the selector (`forbiddenName`)
In the _template-driven_ example, the `<input>` has the selector (`forbiddenName`)
of a custom _attribute directive_, which rejects "bob".
<code-example path="form-validation/src/app/template/hero-form-template2.component.html" region="name-input" title="template/hero-form-template2.component.html (name input)" linenums="false">
@ -680,7 +703,7 @@ see [Attribute Directives](guide/attribute-directives).
## Testing Considerations
You can write _isolated unit tests_ of validation and control logic in Reactive Forms.
You can write _isolated unit tests_ of validation and control logic in _Reactive Forms_.
_Isolated unit tests_ probe the component class directly, independent of its
interactions with its template, the DOM, other dependencies, or Angular itself.
@ -688,8 +711,8 @@ interactions with its template, the DOM, other dependencies, or Angular itself.
Such tests have minimal setup, are quick to write, and easy to maintain.
They do not require the `Angular TestBed` or asynchronous testing practices.
That's not possible with Template Driven forms.
The Template Driven approach relies on Angular to produce the control model and
That's not possible with _template-driven_ forms.
The template-driven approach relies on Angular to produce the control model and
to derive validation rules from the HTML validation attributes.
You must use the `Angular TestBed` to create component test instances,
write asynchronous tests, and interact with the DOM.

View File

@ -407,9 +407,6 @@ like the Observable-based version.
</div>
First, make sure to import the `toPromise` operator of the RxJS library.
<code-example path="http/src/app/toh/hero.service.promise.ts" region="rxjs-imports" title="src/app/toh/hero.service.promise.ts (import rxjs)" linenums="false"></code-example>
Here is a comparison of the `HeroService` using Promises versus Observables,
highlighting just the parts that are different.

View File

@ -1,12 +1,19 @@
# Internationalization (i18n)
{@a top}
Angular's _internationalization_ (_i18n_) tools help make your app available in multiple languages.
Try this <live-example name="i18n" title="i18n Example in Spanish">live example</live-example>
of a JIT-compiled app, translated into Spanish.
{@a angular-i18n}
## Angular and _i18n_ template translation
Application internationalization is a challenging, many-faceted effort that
@ -16,13 +23,20 @@ Angular's _i18n_ internationalization facilities can help.
This page describes the _i18n_ tools available to assist translation of component template text
into multiple languages.
<div class="l-sub-section">
Practitioners of _internationalization_ refer to a translatable text as a "_message_".
This page uses the words "_text_" and "_message_" interchangeably and in the combination, "_text message_".
This page uses the words "_text_" and "_message_" interchangably and in the combination, "_text message_".
</div>
The _i18n_ template translation process has four phases:
1. Mark static text messages in your component templates for translation.
@ -38,8 +52,11 @@ in the target language.
You need to build and deploy a separate version of the application for each supported language.
{@a i18n-attribute}
## Mark text with the _i18n_ attribute
The Angular `i18n` attribute is a marker for translatable content.
@ -48,112 +65,73 @@ Place it on every element tag whose fixed text should be translated.
<div class="alert is-helpful">
`i18n` is not an Angular _directive_.
It's a custom _attribute_, recognized by Angular tools and compilers.
After translation, the compiler removes it.
</div>
In the accompanying sample, an `<h1>` tag displays a simple English language greeting
that you translate into Spanish:
<code-example path="i18n/src/app/app.component.1.html" region="greeting" title="src/app/app.component.html" linenums="false">
</code-example>
Add the `i18n` attribute to the tag to mark it for translation.
<code-example path="i18n/src/app/app.component.1.html" region="i18n-attribute" title="src/app/app.component.html" linenums="false">
</code-example>
{@a help-translator}
### Help the translator with a _description_ and _meaning_
### Help the translator with a _description_ and _intent_
In order to translate it accurately, the translator may
need a description of the message.
Assign a description to the i18n attribute:
<code-example path="i18n/src/app/app.component.1.html" region="i18n-attribute-desc" title="src/app/app.component.html" linenums="false">
</code-example>
In order to deliver a correct translation, the translator may need to
know the _meaning_ or _intent_ of the text within _this particular_ application context.
know your _intent_&mdash;the true _meaning_ of the text
within _this particular_ application context.
In front of the description, add some contextual meaning to the assigned string,
separating it from the description with the `|` character (`<meaning>|<description>`):
You add context by beginning the string with the _meaning_ and
separating it from the _description_ with the `|` character (`<meaning>|<description>`):
<code-example path="i18n/src/app/app.component.1.html" region="i18n-attribute-meaning" title="src/app/app.component.html" linenums="false">
<code-example path="i18n/src/app/app.component.html" region="i18n-attribute-meaning" title="src/app/app.component.html" linenums="false">
</code-example>
While all appearances of a message with the _same_ meaning have the _same_ translation,
a message with *a variety of possible meanings* could have different translations.
The Angular extraction tool preserves both the _meaning_ and the _description_ in the translation source file
to facilitate contextually-specific translations.
to facilitiate contextually-specific translations.
{@a custom-id}
### Set a custom _id_ to improve search and maintenance
The angular _i18n_ extractor tool generates a file with a _translation unit_ entry for each `i18n` attribute in a template. By default, it assigns each translation unit a unique _id_ such as this one:
<code-example path="i18n/src/locale/messages.es.xlf.html" region="generated-id" linenums="false">
</code-example>
This _id_ is obscure and difficult for humans to read or remember.
Worse, when you change the translatable text, perhaps to fix a typo,
the extractor tool generates a new _id_ for that translation.
You will lose the translation unless you update it with the new _id_.
That [complicates maintenance](#maintenance).
Consider specifying your own, meaningful _id_ in the `i18n` attribute, **prefixed with `@@`**.
<code-example path='i18n/src/app/app.component.1.html' region='i18n-attribute-solo-id' title='app/app.component.html' linenums="false">
</code-example>
Now the extractor tool and compiler will generate a translation unit with _your custom id_ and never change it.
<code-example path="i18n/src/locale/messages.es.xlf.html" region="custom-id" linenums="false">
</code-example>
Here is the `i18n` attribute with a _definition_, followed by the custom `id`:
<code-example path='i18n/src/app/app.component.1.html' region='i18n-attribute-id' title='app/app.component.html' linenums="false">
</code-example>
Here is a _meaning_ and a _description_ and the _id_ at the end:
<code-example path='i18n/src/app/app.component.1.html' region='i18n-attribute-meaning-and-id' title='app/app.component.html' linenums="false">
</code-example>
<div class="l-sub-section">
Be sure to define _unique_ custom ids. If you use the same id for 2 _different_ blocks of text, only the first one will be extracted,
and its translation used in both blocks of text.
For example:
```html
<p i18n="@@myId">Hello</p>
<p i18n="@@myId">Good bye</p>
```
with the translation:
```xml
<trans-unit id="myId" datatype="html">
<source>Hello</source>
<target state="new">Hola</target>
</trans-unit>
```
Both `<p>` elements will contain the text `Hola`.
</div>
{@a no-element}
### Translate text without creating an element
Suppose there is a stretch of text that you'd like to translate.
@ -162,37 +140,58 @@ you don't want to create a new DOM element merely to facilitate translation.
Here are two techniques to try.
(1) Wrap the text in an `<ng-container>` element. The `<ng-container>` is never rendered:
(1) Wrap the text in an `<ng-container>` element. The `<ng-container>` is never renderered:
<code-example path="i18n/src/app/app.component.html" region="i18n-ng-container" title="src/app/app.component.html" linenums="false">
</code-example>
(2) Wrap the text in a pair of HTML comments:
<code-example path="i18n/src/app/app.component.html" region="i18n-with-comment" title="src/app/app.component.html" linenums="false">
</code-example>
{@a translate-attributes}
## Add _i18n_ translation attributes
## Add _i18n-..._ translation attributes
You've added an image to your template. You care about accessibility too so you add a `title` attribute:
<code-example path="i18n/src/app/app.component.1.html" region="i18n-title" title="src/app/app.component.html" linenums="false">
</code-example>
The `title` attribute needs to be translated.
Angular i18n support has more translation attributes in the form,`i18n-x`, where `x` is the
name of the attribute to translate.
To translate the `title` on the `img` tag from the previous example, write:
<code-example path="i18n/src/app/app.component.html" region="i18n-title-translate" title="src/app/app.component.html" linenums="false">
</code-example>
You can also assign a meaning and a description with the `i18n-x="<meaning>|<description>"` syntax.
{@a cardinality}
## Handle singular and plural
Different languages have different pluralization rules.
@ -203,9 +202,13 @@ Other languages might express the _cardinality_ differently.
Here's how you could mark up the component template to display the phrase appropriate to the number of wolves:
<code-example path="i18n/src/app/app.component.html" region="i18n-plural" title="src/app/app.component.html" linenums="false">
</code-example>
* The first parameter is the key. It is bound to the component property (`wolves`)
that determines the number of wolves.
* The second parameter identifies this as a `plural` translation type.
@ -214,41 +217,43 @@ categories and their matching values.
Pluralization categories include:
* =0 (or any other number)
* zero
* one
* two
* =0
* =1
* =5
* few
* many
* other
Put the default _English_ translation in braces (`{}`) next to the pluralization category.
* When you're talking about one wolf, you could write `=1 {one wolf}`.
* For zero wolves, you could write `=0 {no wolves}`.
* For two wolves, you could write `=2 {two wolves}`.
You could keep this up for three, four, and every other number of wolves.
Or you could specify the **`other`** category as a catch-all for any unmatched cardinality
and write something like: `other {a wolf pack}`.
<div class="l-sub-section">
This syntax conforms to the
<a href="http://userguide.icu-project.org/formatparse/messages" title="ICU Message Format">ICU Message Format</a>
that derives from the
<a href="http://cldr.unicode.org/" title="CLDR">Common Locale Data Repository (CLDR)</a>,
which specifies the
<a href="http://cldr.unicode.org/index/cldr-spec/plural-rules" title="Pluralization Rules">pluralization rules</a>.
<a href="http://unicode.org/reports/tr35/tr35-numbers.html#Language_Plural_Rules" title="Pluralization Rules">pluralization rules</a>.
</div>
{@a select}
## Select among alternative texts
## Select among alternative texts
The application displays different text depending upon whether the hero is male or female.
These text alternatives require translation too.
@ -261,18 +266,17 @@ The following format message in the component template binds to the component's
property, which outputs either an "m" or an "f".
The message maps those values to the appropriate translation:
<code-example path="i18n/src/app/app.component.html" region="i18n-select" title="src/app/app.component.html" linenums="false">
</code-example>
## Nesting pluralization and selection expressions
You can also nest different ICU expressions together. For example:
<code-example path="i18n/src/app/app.component.html" region="i18n-nested" title="src/app/app.component.html">
</code-example>
{@a ng-xi18n}
## Create a translation source file with the _ng-xi18n_ tool
Use the **_ng-xi18n_ extraction tool** to extract the `i18n`-marked texts
@ -281,46 +285,63 @@ into a translation source file in an industry standard format.
This is an Angular CLI tool in the `@angular/compiler-cli` npm package.
If you haven't already installed the CLI and its `platform-server` peer dependency, do so now:
<code-example language="sh" class="code-shell">
npm install @angular/compiler-cli @angular/platform-server --save
</code-example>
Open a terminal window at the root of the application project and enter the `ng-xi18n` command:
<code-example language="sh" class="code-shell">
./node_modules/.bin/ng-xi18n
</code-example>
<div class="l-sub-section">
Windows users may have to quote the command like this: `"./node_modules/.bin/ng-xi18n"`
</div>
By default, the tool generates a translation file named **`messages.xlf`** in the
<a href="https://en.wikipedia.org/wiki/XLIFF">XML Localization Interchange File Format (XLIFF, version 1.2)</a>.
<a href="https://en.wikipedia.org/wiki/XLIFF">XML Localisation Interchange File Format (XLIFF, version 1.2)</a>.
{@a other-formats}
### Other translation formats
Angular i18n tooling supports XLIFF 1.2 and XLIFF 2 as well as the
<a href="http://cldr.unicode.org/development/development-process/design-proposals/xmb" >XML Message Bundle (XMB)</a>.
You can generate a file named **`messages.xmb`** in the
<a href="http://cldr.unicode.org/development/development-process/design-proposals/xmb" >XML Message Bundle (XMB)</a> format
by adding the `--i18nFormat=xmb` flag.
You can specify your choice of format _explicitly_ with the `--i18nFormat` flag as illustrated in these example commands
<code-example language="sh" class="code-shell">
./node_modules/.bin/ng-xi18n --i18nFormat=xlf --outFile=messages.xlf
./node_modules/.bin/ng-xi18n --i18nFormat=xlf2 --outFile=messages.xliff2.xlf
./node_modules/.bin/ng-xi18n --i18nFormat=xmb --outFile=messages.xmb
./node_modules/.bin/ng-xi18n --i18nFormat=xmb
</code-example>
The sample in _this_ guide sticks with the default _XLIFF 1.2_ format.
This sample sticks with the _XLIFF_ format.
{@a ng-xi18n-options}
### Other options
### Other options
You may have to specify additional options.
For example, if the `tsconfig.json` TypeScript configuration
file is located somewhere other than in the root folder,
@ -329,10 +350,15 @@ you must identify the path to it with the `-p` option:
<code-example language="sh" class="code-shell">
./node_modules/.bin/ng-xi18n -p path/to/tsconfig.json
./node_modules/.bin/ng-xi18n --i18nFormat=xmb -p path/to/tsconfig.json
</code-example>
{@a npm-i18n-script}
### Add an _npm_ script for convenience
Consider adding a convenience shortcut to the `scripts` section of the `package.json`
@ -345,6 +371,8 @@ to make the command easier to remember and run:
}
</code-example>
Now you can issue command variations such as these:
<code-example language="sh" class="code-shell">
@ -353,21 +381,28 @@ Now you can issue command variations such as these:
npm run i18n -- --i18nFormat=xmb -p path/to/tsconfig.json
</code-example>
Note the `--` flag before the options.
It tells _npm_ to pass every flag thereafter to `ng-xi18n`.
{@a translate}
## Translate text messages
The `ng-xi18n` command generates a translation source file
in the project root folder named `messages.xlf`.
The next step is to translate the English language template
text into the specific language translation
files. The guide sample creates a Spanish translation file.
files. The cookbook sample creates a Spanish translation file.
{@a localization-folder}
### Create a localization folder
You will probably translate into more than one other language so it's a good idea
@ -378,12 +413,16 @@ such as internationalization files, there.
<div class="l-sub-section">
Localization and internationalization are
<a href="https://en.wikipedia.org/wiki/Internationalization_and_localization">different but closely related terms</a>.
</div>
This guide follows that suggestion. It has a `locale` folder under `src/`.
This cookbook follows that suggestion. It has a `locale` folder under the `src/`.
Assets within the folder carry a filename extension that matches a language-culture code from a
<a href="https://msdn.microsoft.com/en-us/library/ee825488(v=cs.20).aspx">well-known codeset</a>.
@ -393,6 +432,7 @@ Do the same for each target language.
{@a translate-text-nodes}
### Translate text nodes
In the real world, you send the `messages.es.xlf` file to a Spanish translator who fills in the translations
using one of the
@ -401,41 +441,50 @@ using one of the
This sample file is easy to translate without a special editor or knowledge of Spanish.
Open `messages.es.xlf` and find the first `<trans-unit>` section:
<code-example path="i18n/src/locale/messages.es.xlf.html" region="translated-hello" title="src/locale/messages.es.xlf (&lt;trans-unit&gt;)" linenums="false">
</code-example>
This XML element represents the translation of the `<h1>` greeting tag you marked with the `i18n` attribute.
<div class="l-sub-section">
Note that the translation unit `id=introductionHeader` is derived from the _custom_ `id`](#custom-id "Set a custom id") that you set earlier, but **without the `@@` prefix** required in the source HTML.
</div>
Using the _source_, _description_, and _meaning_ elements to guide your translation,
replace the `<target/>` tag with the Spanish greeting:
<code-example path="i18n/src/locale/messages.es.xlf.html" region="translated-hello" title="src/locale/messages.es.xlf (&lt;trans-unit&gt;, after translation)" linenums="false">
</code-example>
Translate the other text nodes the same way:
<code-example path="i18n/src/locale/messages.es.xlf.html" region="translated-other-nodes" title="src/locale/messages.es.xlf (&lt;trans-unit&gt;)" linenums="false">
</code-example>
<div class="alert is-important">
**The tool generated the `id`s for _these_ translation units. Don't touch them.**
Each `id` depends upon the content of the message and its assigned meaning.
Change either factor and the `id` changes as well.
See the **[translation file maintenance discussion](#maintenance)**.
This is why you should **[specify custom ids](#custom-id "Set a custom id")** and avoid tool generated ids.
Note that the tool generates the `id`. **Don't touch it.**
Its value depends on the content of the message and its assigned meaning.
Change either factor and the `id` changes as well.
See the **[translation file maintenance discussion](guide/i18n#maintenance)**.
</div>
Translate the other text nodes the same way:
<code-example path="i18n/src/locale/messages.es.xlf.html" region="translated-other-nodes" title="src/locale/messages.es.xlf (&lt;trans-unit&gt;)" linenums="false">
</code-example>
{@a translate-plural-select}
## Translate _plural_ and _select_
Translating _plural_ and _select_ messages is a little tricky.
@ -447,92 +496,121 @@ However, the `XMB` format does support the ICU rules.
You'll just have to look for them in relation to other translation units that you recognize from elsewhere in the source template.
In this example, you know the translation unit for the `select` must be just below the translation unit for the logo.
{@a translate-plural}
### Translate _plural_
To translate a `plural`, translate its ICU format match values:
<code-example path="i18n/src/locale/messages.es.xlf.html" region="translated-plural" title="src/locale/messages.es.xlf (&lt;trans-unit&gt;)" linenums="false">
</code-example>
{@a translate-select}
### Translate _select_
The `select` behaves a little differently. Here again is the ICU format message in the component template:
<code-example path="i18n/src/app/app.component.html" region="i18n-select" title="src/app/app.component.html" linenums="false">
</code-example>
The extraction tool broke that into _two_ translation units.
The first unit contains the text that was _outside_ the `select`.
In place of the `select` is a placeholder, `<x id="ICU">`, that represents the `select` message.
Translate the text and leave the placeholder where it is.
<code-example path="i18n/src/locale/messages.es.xlf.html" region="translate-select-1" title="src/locale/messages.es.xlf (&lt;trans-unit&gt;)" linenums="false">
</code-example>
The second translation unit, immediately below the first one, contains the `select` message. Translate that.
<code-example path="i18n/src/locale/messages.es.xlf.html" region="translate-select-2" title="src/locale/messages.es.xlf (&lt;trans-unit&gt;)" linenums="false">
</code-example>
Here they are together, after translation:
<code-example path="i18n/src/locale/messages.es.xlf.html" region="translated-select" title="src/locale/messages.es.xlf (&lt;trans-unit&gt;)" linenums="false">
</code-example>
### Translate a nested expression
A nested expression is not different from the previous ones. As in the previous example, we have _two_ translation units.
The first one contains the text outside the nested expression:
<div class='l-main-content'>
<code-example path="i18n/src/locale/messages.es.xlf.html" region="translate-nested-1" title="src/locale/messages.es.xlf (&lt;trans-unit&gt;)" linenums="false">
</code-example>
The second unit contains the complete nested expression:
<code-example path="i18n/src/locale/messages.es.xlf.html" region="translate-nested-2" title="src/locale/messages.es.xlf (&lt;trans-unit&gt;)" linenums="false">
</code-example>
And both together:
<code-example path="i18n/src/locale/messages.es.xlf.html" region="translate-nested" title="src/locale/messages.es.xlf (&lt;trans-unit&gt;)" linenums="false">
</code-example>
</div>
The entire template translation is complete. It's
time to incorporate that translation into the application.
<a id='app-pre-translation'></a>
<div id='app-pre-translation'>
</div>
### The app before translation
When the previous steps finish, the sample app _and_ its translation file are as follows:
<code-tabs>
<code-pane title="src/app/app.component.html" path="i18n/src/app/app.component.html">
</code-pane>
<code-pane title="src/app/app.component.ts" path="i18n/src/app/app.component.ts">
</code-pane>
<code-pane title="src/app/app.module.ts" path="i18n/src/app/app.module.ts">
</code-pane>
<code-pane title="src/main.ts" path="i18n/src/main.1.ts">
</code-pane>
<code-pane title="src/locale/messages.es.xlf" path="i18n/src/locale/messages.es.xlf.html">
</code-pane>
</code-tabs>
{@a merge}
## Merge the completed translation file into the app
To merge the translated text into component templates,
compile the application with the completed translation file.
The process is the same whether the file is in `.xlf` format or
in another format that Angular understands, such as `.xtb`.
in another format that Angular understands, such as `.xlif` or `.xtb`.
You provide the Angular compiler with three new pieces of information:
@ -547,8 +625,11 @@ the JIT (_Just-in-Time_) compiler or the AOT (_Ahead-of-Time_) compiler.
* With [JIT](guide/i18n#jit), you provide the information at bootstrap time.
* With [AOT](guide/i18n#aot), you pass the information as `ngc` options.
{@a jit}
### Merge with the JIT compiler
The JIT compiler compiles the application in the browser as the application loads.
@ -562,22 +643,20 @@ Translation with the JIT compiler is a dynamic process of:
Open `index.html` and revise the launch script as follows:
<code-example path="i18n/src/index.html" region="i18n" title="index.html (launch script)" linenums="false">
</code-example>
In this sample, the user's language is hard-coded as a global `document.locale` variable
In this sample, the user's language is hardcoded as a global `document.locale` variable
in the `index.html`.
{@a text-plugin}
### SystemJS text plugin
<div class="alert is-important">
This plugin only applies to an application using SystemJS. If you are using the Angular CLI, please refer to their
[docs](https://github.com/angular/angular-cli/wiki/xi18n).
</div>
Notice the SystemJS mapping of `text` to a `systemjs-text-plugin.js`.
With the help of a text plugin, SystemJS can read any file as raw text and
return the contents as a string.
@ -587,26 +666,33 @@ SystemJS doesn't ship with a raw text plugin but it's easy to add.
Create the following `systemjs-text-plugin.js` in the `src/` folder:
<code-example path="i18n/src/systemjs-text-plugin.js" title="src/systemjs-text-plugin.js" linenums="false">
</code-example>
{@a create-translation-providers}
### Create translation providers
Three providers tell the JIT compiler how to translate the template texts for a particular language
while compiling the application:
* `TRANSLATIONS` is a string containing the content of the translation file.
* `TRANSLATIONS_FORMAT` is the format of the file: `xlf`, `xlf2`, or `xtb`.
* `TRANSLATIONS_FORMAT` is the format of the file: `xlf`, `xlif`, or `xtb`.
* `LOCALE_ID` is the locale of the target language.
The `getTranslationProviders()` function in the following `src/app/i18n-providers.ts`
creates those providers based on the user's _locale_
and the corresponding translation file:
<code-example path="i18n/src/app/i18n-providers.ts" region="without-missing-translation" title="src/app/i18n-providers.ts">
<code-example path="i18n/src/app/i18n-providers.ts" title="src/app/i18n-providers.ts">
</code-example>
1. It gets the locale from the global `document.locale` variable that was set in `index.html`.
1. If there is no locale or the language is U.S. English (`en-US`), there is no need to translate.
@ -623,15 +709,10 @@ Notice that it appends `!text` to the filename, telling SystemJS to use the [tex
1. Finally, `getTranslationProviders()` returns the entire effort as a promise.
<div class="alert is-important">
The `LOCALE_ID` has to be a valid locale id as explained in [here](http://userguide.icu-project.org/locale).
</div>
{@a bootstrap-the-app}
### Bootstrap with translation providers
### Bootstrap the app with translation providers
The Angular `bootstrapModule()` method has a second _options_ parameter
that can influence the behavior of the compiler.
@ -641,16 +722,22 @@ and pass it to `bootstrapModule`.
Open the `src/main.ts` and modify the bootstrap code as follows:
<code-example path="i18n/src/main.ts" title="src/main.ts" linenums="false">
</code-example>
Notice that it waits for the `getTranslationProviders()` promise to resolve before
bootstrapping the app.
The app is now _internationalized_ for English and Spanish and there is a clear path for adding
more languages.
{@a aot}
### _Internationalization_ with the AOT compiler
The JIT compiler translates the application into the target language
@ -665,7 +752,7 @@ language. Then in the host web page, in this case `index.html`,
you determine which language the user needs
and serve the appropriate application package.
This guide doesn't cover how to build multiple application packages and
This cookbook doesn't cover how to build multiple application packages and
serve them according to the user's language preference.
It does explain the few steps necessary to tell the AOT compiler to apply a translations file.
@ -673,7 +760,7 @@ Internationalization with the AOT compiler requires
some setup specifically for AOT compilation.
Start with the application project as shown
[just before merging the translation file](guide/i18n#app-pre-translation)
and refer to the [AOT guide](guide/aot-compiler) to make it _AOT-ready_.
and refer to the [AOT cookbook](guide/aot-compiler) to make it _AOT-ready_.
Next, issue an `ngc` compile command for each supported language, including English.
The result is a separate version of the application for each language.
@ -688,65 +775,45 @@ For this sample, the Spanish language command would be:
<code-example language="sh" class="code-shell">
./node_modules/.bin/ngc --i18nFile=./locale/messages.es.xlf --locale=es --i18nFormat=xlf
</code-example>
<div class="l-sub-section">
Windows users may have to quote the command:
<code-example language="sh" class="code-shell">
"./node_modules/.bin/ngc" --i18nFile=./locale/messages.es.xlf --locale=es --i18nFormat=xlf
</code-example>
</div>
### Report missing translations
If you forgot to provide a translation, the build will succeed with a warning that you might easily overlook.
You can configure the Angular compiler for different "missing translation" behaviors:
* Error
* Warning (default)
* Ignore
To change the behavior in JIT, you can use the following configuration:
<code-example language="typescript">
{ provide: CompilerConfig, useValue: new CompilerConfig({ missingTranslation: MissingTranslationStrategy.Error }) }
</code-example>
A good place to use it is the translation providers:
<code-example path="i18n/src/app/i18n-providers.ts" region="missing-translation" title="src/app/i18n-providers.ts"></code-example>
To change the behavior in AOT, add the `--missingTranslation` flag to the compilation command:
<code-example language="sh" class="code-shell">
./node_modules/.bin/ngc --i18nFile=./locale/messages.es.xlf --locale=es --i18nFormat=xlf --missingTranslation=error
</code-example>
{@a maintenance}
## File maintenance and _id_ changes
## Translation file maintenance and _id_ changes
As the application evolves, you will change the _i18n_ markup
and re-run the `ng-xi18n` extraction tool many times.
The _new_ markup that you add is not a problem.
But the `id` _can be a serious problem!_
If the `id` is generated by the tool, _most_ changes to _existing_ markup
cause the tool to generate a _new_ `id` for the affected translation unit.
The _new_ markup that you add is not a problem;
but _most_ changes to existing markup trigger
generation of new `id`s for the affected translation units.
After an `id` changes, the translation files are no longer in sync.
Because of that, you get some warning messages during re-compilation.
The warning messages identify that some translations are missing, but they don't tell you which
old `ids` are no longer valid.
**All translated versions of the application will fail** during re-compilation.
The error messages identify the old `id`s that are no longer valid but
they don't tell you what the new `id`s should be.
If you use a [custom id](#custom-id "Set a custom id"),
the tooling preserves the custom `id` as you make changes to the corresponding translation unit. **Use custom _ids_ unless you have a very good reason to do otherwise.**
Whether you use generated or custom `ids`, **always commit all translation message files to source control**,
**Commit all translation message files to source control**,
especially the English source `messages.xlf`.
The difference between the old and the new `messages.xlf` file
will help you find and update `ids` and other changes across your translation files.
help you find and update `id` changes across your translation files.

View File

@ -12,7 +12,7 @@ making some of them public so external components can use them.
And there are many more options covered here.
Before reading this page, read the
[The Root Module](guide/bootstrapping) page, which introduces NgModules and the essentials
[The Root Module](guide/appmodule) page, which introduces NgModules and the essentials
of creating and maintaining a single root `AppModule` for the entire application.
This page covers NgModules in greater depth.

View File

@ -1,617 +1,79 @@
# QuickStart
<h1 class="no-toc">QuickStart</h1>
Good tools make application development quicker and easier to maintain than
if you did everything by hand.
The [**Angular CLI**](https://cli.angular.io/) is a **_command line interface_** tool
that can create a project, add files, and perform a variety of ongoing development tasks such
as testing, bundling, and deployment.
The goal in this guide is to build and run a simple Angular
application in TypeScript, using the Angular CLI
while adhering to the [Style Guide](guide/styleguide) recommendations that
benefit _every_ Angular project.
By the end of the chapter, you'll have a basic understanding of development with the CLI
and a foundation for both these documentation samples and for real world applications.
<!--
You'll pursue these ends in the following high-level steps:
1. [Set up](guide/cli-quickstart#devenv) the development environment.
2. [Create](guide/cli-quickstart#create-proj) a new project and skeleton application.
3. [Serve](guide/cli-quickstart#serve) the application.
4. [Edit](guide/cli-quickstart#first-component) the application.
-->
And you can also <a href="generated/zips/cli-quickstart/cli-quickstart.zip" target="_blank">download the example.</a>
Angular applications are made up of _components_.
A _component_ is the combination of an HTML template and a component class that controls a portion of the screen. Here is an example of a component that displays a simple string:
<h2 id='devenv'>
Step 1. Set up the Development Environment
</h2>
You need to set up your development environment before you can do anything.
Install **[Node.js® and npm](https://nodejs.org/en/download/)**
if they are not already on your machine.
<div class="l-sub-section">
**Verify that you are running at least node `6.9.x` and npm `3.x.x`**
by running `node -v` and `npm -v` in a terminal/console window.
Older versions produce errors, but newer versions are fine.
</div>
Then **install the [Angular CLI](https://github.com/angular/angular-cli)** globally.
<code-example language="sh" class="code-shell">
npm install -g @angular/cli
<code-example path="quickstart/src/app/app.component.ts" title="src/app/app.component.ts" linenums="false">
</code-example>
<h2 id='create-proj'>
Step 2. Create a new project
</h2>
Open a terminal window.
Generate a new project and skeleton application by running the following commands:
<code-example language="sh" class="code-shell">
ng new my-app
</code-example>
<div class="l-sub-section">
Patience please.
It takes time to set up a new project, most of it spent installing npm packages.
Try this **<live-example noDownload>QuickStart example on Plunker</live-example>** without installing anything.
Try it locally with the [***QuickStart seed***](guide/setup "Setup for local development with the QuickStart seed")
and prepare for development of a real Angular application.
</div>
Every component begins with an `@Component` [decorator](guide/glossary#decorator '"decorator" explained')
function that takes a _metadata_ object. The metadata object describes how the HTML template and component class work together.
<h2 id='serve'>
Step 3: Serve the application
</h2>
The `selector` property tells Angular to display the component inside a custom `<my-app>` tag in the `index.html`.
Go to the project directory and launch the server.
<code-example language="sh" class="code-shell">
cd my-app
ng serve --open
<code-example path="quickstart/src/index.html" region="my-app" title="index.html (inside &lt;body&gt;)" linenums="false">
</code-example>
The `ng serve` command launches the server, watches your files,
and rebuilds the app as you make changes to those files.
Using the `--open` (or just `-o`) option will automatically open your browser
on `http://localhost:4200/`.
Your app greets you with a message:
The `template` property defines a message inside an `<h1>` header.
The message starts with "Hello" and ends with `{{name}}`,
which is an Angular [interpolation binding](guide/displaying-data) expression.
At runtime, Angular replaces `{{name}}` with the value of the component's `name` property.
Interpolation binding is one of many Angular features you'll discover in this documentation.
<figure>
<img src='generated/images/guide/cli-quickstart/app-works.png' alt="The app works!">
</figure>
In the example, change the component class's `name` property from `'Angular'` to `'World'` and see what happens.
<div class="callout is-helpful">
<h2 id='first-component'>
Step 4: Edit your first Angular component
</h2>
<header>
A word about TypeScript
</header>
The CLI created the first Angular component for you.
This is the _root component_ and it is named `app-root`.
You can find it in `./src/app/app.component.ts`.
<p>
This example is written in <a href="http://www.typescriptlang.org/" title="TypeScript">TypeScript</a>, a superset of JavaScript. Angular
uses TypeScript because its types make it easy to support developer productivity with tooling. You can also write Angular code in JavaScript; [this guide](guide/ts-to-js] explains how.
Open the component file and change the `title` property from _app works!_ to _My First Angular App_:
<code-example path="cli-quickstart/src/app/app.component.ts" region="title" title="src/app/app.component.ts" linenums="false"></code-example>
</p>
The browser reloads automatically with the revised title. That's nice, but it could look better.
Open `src/app/app.component.css` and give the component some style.
<code-example path="cli-quickstart/src/app/app.component.css" title="src/app/app.component.css" linenums="false"></code-example>
<figure>
<img src='generated/images/guide/cli-quickstart/my-first-app.png' alt="Output of QuickStart app">
</figure>
Looking good!
## What's next?
That's about all you'd expect to do in a "Hello, World" app.
You're ready to take the [Tour of Heroes Tutorial](tutorial) and build
a small application that demonstrates the great things you can build with Angular.
Or you can stick around a bit longer to learn about the files in your brand new project.
## Project file review
An Angular CLI project is the foundation for both quick experiments and enterprise solutions.
The first file you should check out is `README.md`.
It has some basic information on how to use CLI commands.
Whenever you want to know more about how Angular CLI works make sure to visit
[the Angular CLI repository](https://github.com/angular/angular-cli) and
[Wiki](https://github.com/angular/angular-cli/wiki).
Some of the generated files might be unfamiliar to you.
### The `src` folder
Your app lives in the `src` folder.
All Angular components, templates, styles, images, and anything else your app needs go here.
Any files outside of this folder are meant to support building your app.
<div class='filetree'>
<div class='file'>src</div>
<div class='children'>
<div class='file'>app</div>
<div class='children'>
<div class='file'>app.component.css</div>
<div class='file'>app.component.html</div>
<div class="file">app.component.spec.ts</div>
<div class="file">app.component.ts</div>
<div class="file">app.module.ts</div>
</div>
<div class="file">assets</div>
<div class='children'>
<div class="file">.gitkeep</div>
</div>
<div class="file">environments</div>
<div class='children'>
<div class="file">environment.prod.ts</div>
<div class="file">environment.ts</div>
</div>
<div class="file">favicon.ico</div>
<div class="file">index.html</div>
<div class="file">main.ts</div>
<div class="file">polyfills.ts</div>
<div class="file">styles.css</div>
<div class="file">test.ts</div>
<div class="file">tsconfig.app.json</div>
<div class="file">tsconfig.spec.json</div>
</div>
</div>
<style>
td, th {vertical-align: top}
</style>
<table width="100%">
<col width="20%">
</col>
<col width="80%">
</col>
<tr>
<th>
File
</th>
<th>
Purpose
</th>
</tr>
<tr>
<td>
`app/app.component.{ts,html,css,spec.ts}`
</td>
<td>
Defines the `AppComponent` along with an HTML template, CSS stylesheet, and a unit test.
It is the **root** component of what will become a tree of nested components
as the application evolves.
</td>
</tr>
<tr>
<td>
`app/app.module.ts`
</td>
<td>
Defines `AppModule`, the [root module](guide/bootstrapping "AppModule: the root module") that tells Angular how to assemble the application.
Right now it declares only the `AppComponent`.
Soon there will be more components to declare.
</td>
</tr>
<tr>
<td>
`assets/*`
</td>
<td>
A folder where you can put images and anything else to be copied wholesale
when you build your application.
</td>
</tr>
<tr>
<td>
`environments/*`
</td>
<td>
This folder contains one file for each of your destination environments,
each exporting simple configuration variables to use in your application.
The files are replaced on-the-fly when you build your app.
You might use a different API endpoint for development than you do for production
or maybe different analytics tokens.
You might even use some mock services.
Either way, the CLI has you covered.
</td>
</tr>
<tr>
<td>
`favicon.ico`
</td>
<td>
Every site wants to look good on the bookmark bar.
Get started with your very own Angular icon.
</td>
</tr>
<tr>
<td>
`index.html`
</td>
<td>
The main HTML page that is served when someone visits your site.
Most of the time you'll never need to edit it.
The CLI automatically adds all `js` and `css` files when building your app so you
never need to add any `&lt;script&gt;` or `&lt;link&gt;` tags here manually.
</td>
</tr>
<tr>
<td>
`main.ts`
</td>
<td>
The main entry point for your app.
Compiles the application with the [JIT compiler](guide/glossary#jit)
and bootstraps the application's root module (`AppModule`) to run in the browser.
You can also use the [AOT compiler](guide/glossary#ahead-of-time-aot-compilation)
without changing any code by passing in `--aot` to `ng build` or `ng serve`.
</td>
</tr>
<tr>
<td>
`polyfills.ts`
</td>
<td>
Different browsers have different levels of support of the web standards.
Polyfills help normalize those differences.
You should be pretty safe with `core-js` and `zone.js`, but be sure to check out
the [Browser Support guide](guide/browser-support) for more information.
</td>
</tr>
<tr>
<td>
`styles.css`
</td>
<td>
Your global styles go here.
Most of the time you'll want to have local styles in your components for easier maintenance,
but styles that affect all of your app need to be in a central place.
</td>
</tr>
<tr>
<td>
`test.ts`
</td>
<td>
This is the main entry point for your unit tests.
It has some custom configuration that might be unfamiliar, but it's not something you'll
need to edit.
</td>
</tr>
<tr>
<td>
`tsconfig.{app|spec}.json`
</td>
<td>
TypeScript compiler configuration for the Angular app (`tsconfig.app.json`)
and for the unit tests (`tsconfig.spec.json`).
</td>
</tr>
</table>
### The root folder
The `src/` folder is just one of the items inside the project's root folder.
Other files help you build, test, maintain, document, and deploy the app.
These files go in the root folder next to `src/`.
<div class='filetree'>
<div class="file">my-app</div>
<div class='children'>
<div class="file">e2e</div>
<div class='children'>
<div class="file">app.e2e-spec.ts</div>
<div class="file">app.po.ts</div>
<div class="file">tsconfig.e2e.json</div>
</div>
<div class="file">node_modules/...</div>
<div class="file">src/...</div>
<div class="file">.angular-cli.json</div>
<div class="file">.editorconfig</div>
<div class="file">.gitignore</div>
<div class="file">karma.conf.js</div>
<div class="file">package.json</div>
<div class="file">protractor.conf.js</div>
<div class="file">README.md</div>
<div class="file">tsconfig.json</div>
<div class="file">tslint.json</div>
</div>
</div>
<style>
td, th {vertical-align: top}
</style>
<table width="100%">
<col width="20%">
</col>
<col width="80%">
</col>
<tr>
<th>
File
</th>
<th>
Purpose
</th>
</tr>
<tr>
<td>
`e2e/`
</td>
<td>
Inside `e2e/` live the End-to-End tests.
They shouldn't be inside `src/` because e2e tests are really a separate app that
just so happens to test your main app.
That's also why they have their own `tsconfig.e2e.json`.
</td>
</tr>
<tr>
<td>
`node_modules/`
</td>
<td>
`Node.js` creates this folder and puts all third party modules listed in
`package.json` inside of it.
</td>
</tr>
<tr>
<td>
`.angular-cli.json`
</td>
<td>
Configuration for Angular CLI.
In this file you can set several defaults and also configure what files are included
when your project is build.
Check out the official documentation if you want to know more.
</td>
</tr>
<tr>
<td>
`.editorconfig`
</td>
<td>
Simple configuration for your editor to make sure everyone that uses your project
has the same basic configuration.
Most editors support an `.editorconfig` file.
See http://editorconfig.org for more information.
</td>
</tr>
<tr>
<td>
`.gitignore`
</td>
<td>
Git configuration to make sure autogenerated files are not commited to source control.
</td>
</tr>
<tr>
<td>
`karma.conf.js`
</td>
<td>
Unit test configuration for the [Karma test runner](https://karma-runner.github.io),
used when running `ng test`.
</td>
</tr>
<tr>
<td>
`package.json`
</td>
<td>
`npm` configuration listing the third party packages your project uses.
You can also add your own [custom scripts](https://docs.npmjs.com/misc/scripts) here.
</td>
</tr>
<tr>
<td>
`protractor.conf.js`
</td>
<td>
End-to-end test configuration for [Protractor](http://www.protractortest.org/),
used when running `ng e2e`.
</td>
</tr>
<tr>
<td>
`README.md`
</td>
<td>
Basic documentation for your project, pre-filled with CLI command information.
Make sure to enhance it with project documentation so that anyone
checking out the repo can build your app!
</td>
</tr>
<tr>
<td>
`tsconfig.json`
</td>
<td>
TypeScript compiler configuration for your IDE to pick up and give you helpful tooling.
</td>
</tr>
<tr>
<td>
`tslint.json`
</td>
<td>
Linting configuration for [TSLint](https://palantir.github.io/tslint/) together with
[Codelyzer](http://codelyzer.com/), used when running `ng lint`.
Linting helps keep your code style consistent.
</td>
</tr>
</table>
<div class="l-sub-section">
### Next Step
If you're new to Angular, continue with the
[tutorial](tutorial "Tour of Heroes tutorial").
You can skip the "Setup" step since you're already using the Angular CLI setup.
### Next step
Start the [**tutorial**](tutorial "Tour of Heroes tutorial").
</div>

View File

@ -3,11 +3,11 @@
{@a develop-locally}
The <live-example name=quickstart>QuickStart live-coding</live-example> example is an Angular _playground_.
It's not where you'd develop a real application.
It's not where you'd develop a real application.
You [should develop locally](guide/setup#why-locally "Why develop locally") on your own machine ... and that's also how we think you should learn Angular.
Setting up a new project on your machine is quick and easy with the **QuickStart seed**,
maintained [on github](https://github.com/angular/quickstart "Install the github QuickStart repo").
maintained [on github](https://github.com/angular/quickstart "Install the github QuickStart repo").
Make sure you have [node and npm installed](guide/setup#install-prerequisites "What if you don't have node and npm?").
@ -124,7 +124,7 @@ Open a terminal window in the project folder and enter the following commands fo
The **QuickStart seed** contains the same application as the QuickStart playground.
But its true purpose is to provide a solid foundation for _local_ development.
Consequently, there are _many more files_ in the project folder on your machine,
Consequently, there are _many more files_ in the project folder on your machine,
most of which you can [learn about later](guide/setup-systemjs-anatomy "Setup Anatomy").
@ -187,7 +187,7 @@ Focus on the following three TypeScript (`.ts`) files in the **`/src`** folder.
All guides and cookbooks have _at least these core files_.
All guides and cookbooks have _at least these core files_.
Each file has a distinct purpose and evolves independently as the application grows.
Files outside `src/` concern building, deploying, and testing your app.
@ -239,7 +239,7 @@ The following are all in `src/`
Defines the same `AppComponent` as the one in the QuickStart playground.
It is the **root** component of what will become a tree of nested components
as the application evolves.
as the application evolves.
</td>
</tr>
@ -253,7 +253,7 @@ The following are all in `src/`
<td>
Defines `AppModule`, the [root module](guide/bootstrapping "AppModule: the root module") that tells Angular how to assemble the application.
Defines `AppModule`, the [root module](guide/appmodule "AppModule: the root module") that tells Angular how to assemble the application.
Right now it declares only the `AppComponent`.
Soon there will be more components to declare.
</td>
@ -270,7 +270,7 @@ The following are all in `src/`
Compiles the application with the [JIT compiler](guide/glossary#jit) and
[bootstraps](guide/bootstrapping#main "bootstrap the application")
[bootstraps](guide/appmodule#main "bootstrap the application")
the application's main module (`AppModule`) to run in the browser.
The JIT compiler is a reasonable choice during the development of most projects and
it's the only viable choice for a sample running in a _live-coding_ environment like Plunker.
@ -315,8 +315,8 @@ Get them now</a> if they're not already installed on your machine.
by running the commands `node -v` and `npm -v` in a terminal/console window.
Older versions produce errors.
We recommend [nvm](https://github.com/creationix/nvm) for managing multiple versions of node and npm.
You may need [nvm](https://github.com/creationix/nvm) if you already have projects running on your machine that
We recommend [nvm](https://github.com/creationix/nvm) for managing multiple versions of node and npm.
You may need [nvm](https://github.com/creationix/nvm) if you already have projects running on your machine that
use other versions of node and npm.
@ -334,7 +334,7 @@ You can play with the sample code, share your changes with friends, and download
The [QuickStart](guide/quickstart "Angular QuickStart Playground") shows just the `AppComponent` file.
It creates the equivalent of `app.module.ts` and `main.ts` internally _for the playground only_.
so the reader can discover Angular without distraction.
The other samples are based on the QuickStart seed.
The other samples are based on the QuickStart seed.
As much fun as this is ...
@ -343,7 +343,7 @@ As much fun as this is ...
* transpiling TypeScript in the browser is slow
* the type support, refactoring, and code completion only work in your local IDE
Use the <live-example title="QuickStart Seed in Plunker">live coding</live-example> environment as a _playground_,
Use the <live-example title="QuickStart Seed in Plunker">live coding</live-example> environment as a _playground_,
a place to try the documentation samples and experiment on your own.
It's the perfect place to reproduce a bug when you want to
<a href="https://github.com/angular/angular/issues/new" title="File a documentation issue">file a documentation issue</a> or

View File

@ -12,13 +12,6 @@ component class instance (the *component*) and its user-facing template.
You may be familiar with the component/template duality from your experience with model-view-controller (MVC) or model-view-viewmodel (MVVM).
In Angular, the component plays the part of the controller/viewmodel, and the template represents the view.
This page is a comprehensive technical reference to the Angular template language.
It explains basic principles of the template language and describes most of the syntax that you'll encounter elsewhere in the documentation.
Many code snippets illustrate the points and concepts, all of them available
in the <live-example title="Template Syntax Live Code"></live-example>.
{@a html}
## HTML in templates
@ -1934,7 +1927,6 @@ The display is blank, but the app keeps rolling without errors.
</code-example>
It works perfectly with long property paths such as `a?.b?.c?.d`.
<a href="#top-of-page">back to top</a>
<hr/>
@ -1943,36 +1935,22 @@ It works perfectly with long property paths such as `a?.b?.c?.d`.
### The non-null assertion operator ( <span class="syntax">!</span> )
As of Typescript 2.0, you can enforce [strict null checking](http://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-0.html "Strict null checking in TypeScript") with the `--strictNullChecks` flag. TypeScript then ensures that no variable is _unintentionally_ null or undefined.
The Angular **non-null assertion operator (`!`)** is a post-fix operator that asserts that the preceeding property path
will never be null or undefined.
In this mode, typed variables disallow null and undefined by default. The type checker throws an error if you leave a variable unassigned or try to assign null or undefined to a variable whose type disallows null and undefined.
Unlike the [_safe navigation operator_](guide/template-syntax#safe-navigation-operator "Safe naviation operator (?.)")
the **non-null assertion operator** does not guard against a null or undefined; rather, it informs the TypeScript type
checker that there is something it might be unaware of that ensures that this property path is defined. This prevents
TypeScript from reporting that the path is possibly null or undefined when strict null checking is enabled.
The type checker also throws an error if it can't determine whether a variable will be null or undefined at runtime.
You may know that can't happen but the type checker doesn't know.
You tell the type checker that it can't happen by applying the post-fix
[_non-null assertion operator (!)_]((http://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-0.html#non-null-assertion-operator "Non-null assertion operator").
The _Angular_ **non-null assertion operator (`!`)** serves the same purpose in an Angular template.
For example, after you use [*ngIf](guide/template-syntax#ngIf) to check that `hero` is defined, you can assert that
`hero` properties are also defined.
For example, if you use [*ngIf](guide/template-syntax#ngIf) to check if `hero` is defined, you can assert the uses of
`hero` are defined in the body of the template.
<code-example path="template-syntax/src/app/app.component.html" region="non-null-assertion-1" title="src/app/app.component.html" linenums="false">
</code-example>
When the Angular compiler turns your template into TypeScript code,
it prevents TypeScript from reporting that `hero.name` might be null or undefined.
Unlike the [_safe navigation operator_](guide/template-syntax#safe-navigation-operator "Safe naviation operator (?.)"),
the **non-null assertion operator** does not guard against null or undefined.
Rather it tells the TypeScript type checker to suspend strict null checks for a specific property expression.
You'll need this template operator when you turn on strict null checks. It's optional otherwise.
<a href="#top-of-page">back to top</a>
<hr/>
The Angular **non-null assertion operator (`!`)** is like TypeScript's _non-null assertion operator (!)_
introduced in [TypeScript 2.0](http://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-0.html).
## Summary
You've completed this survey of template syntax.

View File

@ -160,7 +160,6 @@ This guide describes specific choices that are known to work well.
### Setup
There are two fast paths to getting started with unit testing.
1. Start a new project following the instructions in [Setup](guide/setup "Setup").
1. Start a new project with the

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.2 KiB

After

Width:  |  Height:  |  Size: 9.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.7 KiB

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.0 KiB

After

Width:  |  Height:  |  Size: 8.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 66 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.8 KiB

After

Width:  |  Height:  |  Size: 10 KiB

BIN
aio/content/images/bios/deborah.jpg Executable file → Normal file

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.2 KiB

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.0 KiB

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.3 KiB

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.9 KiB

After

Width:  |  Height:  |  Size: 8.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.7 KiB

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.9 KiB

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.2 KiB

After

Width:  |  Height:  |  Size: 11 KiB

BIN
aio/content/images/bios/jeffwhelpley.jpg Executable file → Normal file

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.4 KiB

After

Width:  |  Height:  |  Size: 46 KiB

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