Compare commits
2 Commits
Author | SHA1 | Date | |
---|---|---|---|
1c04b83ea3 | |||
429bc9d3cd |
@ -3,7 +3,7 @@ jobs:
|
||||
build:
|
||||
working_directory: ~/ng
|
||||
docker:
|
||||
- image: angular/ngcontainer
|
||||
- image: alexeagle/ngcontainer
|
||||
steps:
|
||||
- checkout
|
||||
- restore_cache:
|
||||
|
64
.github/ISSUE_TEMPLATE.md
vendored
@ -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` =
|
||||
|
27
.github/PULL_REQUEST_TEMPLATE.md
vendored
@ -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
@ -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",
|
||||
|
56
CHANGELOG.md
@ -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:** don’t 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:** don’t 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)
|
||||
|
||||
|
@ -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")
|
||||
|
@ -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
@ -0,0 +1,5 @@
|
||||
{
|
||||
"projects": {
|
||||
"staging": "aio-staging"
|
||||
}
|
||||
}
|
3
aio/.gitignore
vendored
@ -43,6 +43,3 @@ protractor-results*.txt
|
||||
# System Files
|
||||
.DS_Store
|
||||
Thumbs.db
|
||||
|
||||
# copied dependencies
|
||||
src/assets/js/lunr*
|
3
aio/content/examples/.gitignore
vendored
@ -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
|
||||
|
1
aio/content/examples/animations/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
**/*.js
|
@ -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%)'
|
||||
}))
|
||||
|
7
aio/content/examples/aot-compiler/.gitignore
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
**/*.ngfactory.ts
|
||||
**/*.ngsummary.json
|
||||
**/*.shim.ngstyle.ts
|
||||
**/*.metadata.json
|
||||
dist
|
||||
!app/tsconfig.json
|
||||
!rollup-config.js
|
45
aio/content/examples/cli-quickstart/.gitignore
vendored
Normal 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
|
116
aio/content/examples/cli-quickstart/src/styles.css
Normal 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;
|
||||
}
|
1
aio/content/examples/component-interaction/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
**/*.js
|
1
aio/content/examples/deployment/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
!systemjs.config.server.js
|
@ -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);
|
||||
});
|
||||
});
|
@ -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"
|
||||
}
|
||||
}
|
@ -1,10 +0,0 @@
|
||||
{
|
||||
"description": "Authors style guide",
|
||||
"basePath": "src/",
|
||||
"files": [
|
||||
"!**/*.d.ts",
|
||||
"!**/*.js",
|
||||
"!**/*.[1,2,3].*"
|
||||
],
|
||||
"tags": ["author", "style guide"]
|
||||
}
|
@ -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"]
|
||||
}
|
@ -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;
|
||||
}
|
@ -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>
|
@ -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
|
@ -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
|
@ -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' }
|
||||
];
|
@ -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>
|
@ -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>
|
@ -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
@ -0,0 +1,6 @@
|
||||
**/*.ngfactory.ts
|
||||
**/*.metadata.json
|
||||
dist
|
||||
!app/tsconfig.json
|
||||
!rollup.js
|
||||
!src/systemjs-text-plugin.js
|
@ -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');
|
||||
});
|
||||
|
||||
});
|
||||
|
@ -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'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'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>
|
||||
|
@ -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
|
||||
|
@ -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>
|
||||
|
@ -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));
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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'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>
|
||||
|
@ -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'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>
|
||||
|
@ -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;
|
||||
}
|
@ -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>
|
||||
|
@ -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"');
|
||||
});
|
||||
});
|
||||
|
2
aio/content/examples/styleguide/.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
*.js
|
||||
!systemjs.custom.js
|
@ -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 -->
|
||||
|
@ -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
|
||||
|
1
aio/content/examples/testing/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
!src/browser-test-shim.js
|
@ -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;
|
||||
}
|
8
aio/content/examples/universal/.gitignore
vendored
Normal file
@ -0,0 +1,8 @@
|
||||
aot/**/*.ts
|
||||
**/*.ngfactory.ts
|
||||
**/*.ngsummary.json
|
||||
**/*.metadata.json
|
||||
**/*.js
|
||||
dist
|
||||
!app/tsconfig.json
|
||||
!/*.js
|
1
aio/content/examples/upgrade-phonecat-1-typescript/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
!karma.conf.ajs.js
|
8
aio/content/examples/upgrade-phonecat-2-hybrid/.gitignore
vendored
Normal 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
|
@ -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
|
||||
|
@ -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');
|
||||
});
|
||||
|
||||
|
1
aio/content/examples/visual-studio-2015/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
!tsconfig.json
|
5
aio/content/examples/webpack/.gitignore
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
dist
|
||||
!karma.webpack.conf.js
|
||||
!webpack.config.js
|
||||
!config/*
|
||||
!public/css/styles.css
|
@ -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"
|
||||
|
@ -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_** — 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 —
|
||||
You'll learn to create two other kinds of classes —
|
||||
[directives](guide/attribute-directives) and [pipes](guide/pipes) —
|
||||
that you must also add to the `declarations` array.
|
||||
|
||||
@ -97,7 +98,7 @@ that you must also add to the `declarations` array.
|
||||
|
||||
|
||||
|
||||
**Only _declarables_** — _components_, _directives_ and _pipes_ — belong in the `declarations` array.
|
||||
**Only _declarables_** — _components_, _directives_ and _pipes_ — belong in the `declarations` array.
|
||||
Do not put any other kind of class in `declarations`; _not_ `NgModule` classes, _not_ service classes, _not_ model classes.
|
||||
|
||||
|
||||
@ -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 — here and in most documentation samples — is `my-app`
|
||||
The `AppComponent` selector — here and in most documentation samples — is `my-app`
|
||||
so Angular looks for a `<my-app>` tag in the `index.html` like this one ...
|
||||
|
||||
<code-example path="setup/src/index.html" region="my-app" title="setup/src/index.html" linenums="false">
|
@ -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
|
||||
|
617
aio/content/guide/cli-quickstart.md
Normal 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 `<script>` or `<link>` 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>
|
@ -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—a set for each validated property with
|
||||
Next, the component needs some error messages of course—a set for each validated property with
|
||||
one message per validation rule:
|
||||
|
||||
<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—`FormsModule` and
|
||||
`ReactiveFormsModule`—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.
|
||||
|
@ -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.
|
||||
|
@ -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_—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 (<trans-unit>)" 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 (<trans-unit>, 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 (<trans-unit>)" 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 (<trans-unit>)" 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 (<trans-unit>)" 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 (<trans-unit>)" 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 (<trans-unit>)" 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 (<trans-unit>)" 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 (<trans-unit>)" 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 (<trans-unit>)" 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 (<trans-unit>)" 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.
|
||||
|
@ -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.
|
||||
|
@ -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 <body>)" 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 `<script>` or `<link>` 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>
|
||||
|
||||
|
@ -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
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
|
Before Width: | Height: | Size: 3.4 KiB |
BIN
aio/content/images/bios/_no-one.png
Normal file
After Width: | Height: | Size: 2.1 KiB |
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 14 KiB |
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 13 KiB |
Before Width: | Height: | Size: 8.2 KiB After Width: | Height: | Size: 9.1 KiB |
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 16 KiB |
Before Width: | Height: | Size: 7.3 KiB |
Before Width: | Height: | Size: 5.4 KiB |
BIN
aio/content/images/bios/angular-gde-bio-placeholder.png
Normal file
After Width: | Height: | Size: 10 KiB |
Before Width: | Height: | Size: 8.7 KiB After Width: | Height: | Size: 11 KiB |
Before Width: | Height: | Size: 7.0 KiB After Width: | Height: | Size: 8.6 KiB |
Before Width: | Height: | Size: 8.1 KiB |
Before Width: | Height: | Size: 10 KiB |
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 66 KiB |
Before Width: | Height: | Size: 6.4 KiB |
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 16 KiB |
Before Width: | Height: | Size: 6.0 KiB |
Before Width: | Height: | Size: 8.8 KiB After Width: | Height: | Size: 10 KiB |
BIN
aio/content/images/bios/deborah.jpg
Executable file → Normal file
Before Width: | Height: | Size: 9.2 KiB After Width: | Height: | Size: 14 KiB |
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 26 KiB |
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 54 KiB |
Before Width: | Height: | Size: 7.0 KiB After Width: | Height: | Size: 24 KiB |
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 34 KiB |
Before Width: | Height: | Size: 8.6 KiB |
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 20 KiB |
Before Width: | Height: | Size: 7.3 KiB After Width: | Height: | Size: 12 KiB |
Before Width: | Height: | Size: 8.9 KiB After Width: | Height: | Size: 8.2 KiB |
Before Width: | Height: | Size: 8.7 KiB After Width: | Height: | Size: 11 KiB |
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 24 KiB |
Before Width: | Height: | Size: 9.9 KiB After Width: | Height: | Size: 12 KiB |
Before Width: | Height: | Size: 7.1 KiB |
Before Width: | Height: | Size: 9.2 KiB After Width: | Height: | Size: 11 KiB |
BIN
aio/content/images/bios/jeffwhelpley.jpg
Executable file → Normal file
Before Width: | Height: | Size: 7.4 KiB After Width: | Height: | Size: 46 KiB |