Merge remote-tracking branch 'origin/master'

# Conflicts:
#	README.md
#	public/docs/js/latest/cookbook/ts-to-js.jade
#	public/docs/ts/latest/cookbook/a1-a2-quick-reference.jade
#	public/docs/ts/latest/guide/architecture.jade
#	public/docs/ts/latest/guide/attribute-directives.jade
#	public/docs/ts/latest/guide/forms.jade
#	public/docs/ts/latest/guide/lifecycle-hooks.jade
#	public/docs/ts/latest/guide/router.jade
#	public/docs/ts/latest/guide/server-communication.jade
#	public/docs/ts/latest/guide/style-guide.jade
#	public/docs/ts/latest/guide/template-syntax.jade
#	public/docs/ts/latest/testing/first-app-tests.jade
#	public/docs/ts/latest/tutorial/toh-pt5.jade
#	public/docs/ts/latest/tutorial/toh-pt6.jade
#	public/news.jade
This commit is contained in:
Zhicheng Wang 2016-07-01 08:24:23 +08:00
commit 21fe9dc1d2
112 changed files with 1588 additions and 537 deletions

View File

@ -11,13 +11,19 @@ env:
- DISPLAY=:99.0
- CHROME_BIN=chromium-browser
matrix:
- SCRIPT="lint"
- SCRIPT=lint
- SCRIPT="run-e2e-tests --fast"
- SCRIPT="run-e2e-tests --fast" PREVIEW=true
matrix:
fast_finish: true
allow_failures:
- env: "SCRIPT=\"run-e2e-tests --fast\" PREVIEW=true"
before_install:
- npm install -g gulp --no-optional
before_script:
- sh -e /etc/init.d/xvfb start
install:
- ./script/install.sh
- if [[ $PREVIEW == true ]]; then npm install --prefix public/docs/_examples angular/{core,common,compiler,platform-browser,platform-browser-dynamic,http,forms,router-deprecated,router,upgrade}-builds; fi
script:
- gulp $SCRIPT

View File

@ -75,6 +75,7 @@
"name": "Victor Savkin",
"picture": "/resources/images/bios/victor.jpg",
"twitter": "victorsavkin",
"website": "http://victorsavkin.com/",
"bio": "Victor works on Angular at Google. He is interested in functional programming and client-side applications. Being a language nerd he spends a lot of his time playing with TypeScript, Dart, Elm, Haskell, and Clojure.",
"type": "Google"
},
@ -101,6 +102,7 @@
"name": "David East",
"picture": "/resources/images/bios/david-east.jpg",
"twitter": "_davideast",
"website":"https://github.com/davideast",
"bio": "David East is a Developer Programs Engineer at Google. He works full-time on the Firebase team and part-time on the Angular core team.",
"type": "Google"
},
@ -217,6 +219,7 @@
"name": "Lucas Mirelmann",
"picture": "/resources/images/bios/lucas.jpg",
"twitter": "lgalfaso",
"website": "https://github.com/lgalfaso",
"bio": "Lucas works as a Software Engineer at Google and is a core Angular contributor.",
"type": "Google"
},
@ -243,6 +246,7 @@
"name": "Robert Messerle",
"picture": "/resources/images/bios/rmesserle.jpg",
"twitter": "Bobbo_O",
"website": "https://github.com/robertmesserle",
"bio": "Robert is a software engineer on the Angular team at Google, working primarily on the Angular Material project.",
"type": "Google"
},
@ -258,6 +262,8 @@
"scott": {
"name": "Scott Hyndman",
"picture": "/resources/images/bios/scott.jpg",
"twitter": "scotthyndman",
"website": "https://github.com/shyndman",
"bio": "Scott works for Google on the Material Design team, where he brings designers' dreams to life on the web.",
"type": "Google"
},
@ -266,6 +272,7 @@
"name": "Kara Erickson",
"picture": "/resources/images/bios/kara-erickson.jpg",
"twitter": "karaforthewin",
"website": "https://github.com/kara",
"bio": "Kara is a software engineer on the Angular team at Google and a co-organizer of the Angular-SF Meetup. Prior to Google, she helped build UI components in Angular for guest management systems at OpenTable. She enjoys snacking indiscriminately and probably other things too.",
"type": "Google"
},
@ -294,6 +301,14 @@
"bio": "Rob is a Developer Advocate on the Angular team at Google. He's the Angular team's resident reactive programming geek and founded the Reactive Extensions for Angular project, ngrx.",
"type": "Google"
},
"maxsills": {
"name": "Max Sills",
"picture": "/resources/images/bios/max-sills.jpg",
"twitter": "angularjs",
"website": "http://google-opensource.blogspot.com/",
"bio": "Max Sills is Angular's Open Source lawyer.",
"type": "Google"
},
"pawel": {
"name": "Pawel Kozlowski",
@ -447,6 +462,21 @@
"website": "http://eric.to/",
"bio": "Eric is a gamer, writer, and programmer.",
"type": "Community"
},
"mikeryan": {
"name": "Mike Ryan",
"picture": "/resources/images/bios/mikeryan.jpg",
"twitter": "mikeryan52",
"website": "https://medium.com/@MikeRyan52",
"bio": "Mike Ryan is a Software Engineer at Synapse Wireless, working on solving challenging problems in the internet-of-things space. He is an advocate of reactive programming and a core contributor to the ngrx project.",
"type": "Community"
},
"rex": {
"name": "Rex Ye",
"picture": "/resources/images/bios/rex.jpg",
"twitter": "rexebin",
"bio": "Rex is a full-stack developer. He maintains the Angular.cn website with his old pal Ralph Wang and he plays a key role in bridging between the Chinese Angular community and the world-wide community. He loves playing with flashy new technologies and enjoys the challenge of mastering new skills. His biggest challenge to date is figuring out how to sooth a crying 4-month-old baby.",
"type": "Community"
}
}
}

View File

@ -2,39 +2,41 @@
// #docregion full
import 'package:angular2/core.dart';
@Directive(selector: '[myHighlight]', host: const {
'(mouseenter)': 'onMouseEnter()',
'(mouseleave)': 'onMouseLeave()'
})
// #docregion class-1
@Directive(selector: '[myHighlight]')
// #docregion class
class HighlightDirective {
String _defaultColor = 'red';
final dynamic _el;
HighlightDirective(ElementRef elRef) : _el = elRef.nativeElement;
// #enddocregion class-1
// #enddocregion class
// #docregion defaultColor
@Input() set defaultColor(String colorName) {
@Input()
set defaultColor(String colorName) {
_defaultColor = (colorName ?? _defaultColor);
}
// #enddocregion defaultColor
// #docregion class-1
// #docregion class
// #docregion color
@Input('myHighlight') String highlightColor;
@Input('myHighlight')
String highlightColor;
// #enddocregion color
// #docregion mouse-enter
void onMouseEnter() { _highlight(highlightColor ?? _defaultColor); }
@HostListener('mouseenter')
void onMouseEnter() => _highlight(highlightColor ?? _defaultColor);
// #enddocregion mouse-enter
void onMouseLeave() { _highlight(); }
@HostListener('mouseleave')
void onMouseLeave() => _highlight();
void _highlight([String color]) {
if (_el != null) _el.style.backgroundColor = color;
}
}
// #enddocregion class-1
// #enddocregion class
// #enddocregion full
/*
// #docregion highlight

View File

@ -1,14 +1,7 @@
// #docregion
import 'package:angular2/core.dart';
@Directive(selector: '[myHighlight]',
// #docregion host
host: const {
'(mouseenter)': 'onMouseEnter()',
'(mouseleave)': 'onMouseLeave()'
}
// #enddocregion host
)
@Directive(selector: '[myHighlight]')
class HighlightDirective {
// #docregion ctor
final dynamic _el;
@ -16,9 +9,21 @@ class HighlightDirective {
HighlightDirective(ElementRef elRef) : _el = elRef.nativeElement;
// #enddocregion ctor
// #docregion mouse-methods
void onMouseEnter() { _highlight("yellow"); }
void onMouseLeave() { _highlight(); }
// #docregion mouse-methods, host
@HostListener('mouseenter')
void onMouseEnter() {
// #enddocregion host
_highlight('yellow');
// #docregion host
}
@HostListener('mouseleave')
void onMouseLeave() {
// #enddocregion host
_highlight();
// #docregion host
}
// #enddocregion host
void _highlight([String color]) {
if (_el != null) _el.style.backgroundColor = color;

View File

@ -1,5 +1,4 @@
/* tslint:disable:no-unused-variable */
// #docplaster
// #docregion
import { Directive, ElementRef, HostListener, Input } from '@angular/core';
@ -8,9 +7,9 @@ import { Directive, ElementRef, HostListener, Input } from '@angular/core';
})
export class HighlightDirective {
// #docregion ctor
private el: HTMLElement;
constructor(el: ElementRef) { this.el = el.nativeElement; }
// #enddocregion ctor

View File

@ -5,20 +5,20 @@ import { Directive, ElementRef, HostListener, Input } from '@angular/core';
@Directive({
selector: '[myHighlight]'
})
// #docregion class-1
// #docregion class
export class HighlightDirective {
private _defaultColor = 'red';
private el: HTMLElement;
constructor(el: ElementRef) { this.el = el.nativeElement; }
// #enddocregion class-1
// #enddocregion class
// #docregion defaultColor
@Input() set defaultColor(colorName: string){
this._defaultColor = colorName || this._defaultColor;
}
// #enddocregion defaultColor
// #docregion class-1
// #docregion class
// #docregion color
@Input('myHighlight') highlightColor: string;
@ -37,7 +37,7 @@ export class HighlightDirective {
this.el.style.backgroundColor = color;
}
}
// #enddocregion class-1
// #enddocregion class
// #enddocregion full
/*
// #docregion highlight

View File

@ -10,10 +10,10 @@
<!-- #docregion ngSwitch-->
<span [ngSwitch]="favoriteHero &&
checkMovieHero(favoriteHero)">
<p *ngSwitchWhen="true">
<p *ngSwitchCase="true">
Excellent choice!
</p>
<p *ngSwitchWhen="false">
<p *ngSwitchCase="false">
No movie, sorry!
</p>
<p *ngSwitchDefault>

View File

@ -4,10 +4,10 @@
<div [ngSwitch]="question.controlType">
<input *ngSwitchWhen="'textbox'" [ngControl]="question.key"
<input *ngSwitchCase="'textbox'" [ngControl]="question.key"
[id]="question.key" [type]="question.type">
<select [id]="question.key" *ngSwitchWhen="'dropdown'" [ngControl]="question.key">
<select [id]="question.key" *ngSwitchCase="'dropdown'" [ngControl]="question.key">
<option *ngFor="let opt of question.options" [value]="opt.key">{{opt.value}}</option>
</select>

View File

@ -18,10 +18,10 @@ const template = '{{log}}';
providers: const [Logger]
// #enddocregion providers-1, providers-logger
)
class ProviderComponent1 {
class Provider1Component {
String log;
ProviderComponent1(Logger logger) {
Provider1Component(Logger logger) {
logger.log('Hello from logger provided with Logger class');
log = logger.logs[0];
}
@ -36,10 +36,10 @@ class ProviderComponent1 {
const [const Provider(Logger, useClass: Logger)]
// #enddocregion providers-3
)
class ProviderComponent3 {
class Provider3Component {
String log;
ProviderComponent3(Logger logger) {
Provider3Component(Logger logger) {
logger.log('Hello from logger provided with useClass:Logger');
log = logger.logs[0];
}
@ -56,10 +56,10 @@ class BetterLogger extends Logger {}
const [const Provider(Logger, useClass: BetterLogger)]
// #enddocregion providers-4
)
class ProviderComponent4 {
class Provider4Component {
String log;
ProviderComponent4(Logger logger) {
Provider4Component(Logger logger) {
logger.log('Hello from logger provided with useClass:BetterLogger');
log = logger.logs[0];
}
@ -87,10 +87,10 @@ class EvenBetterLogger extends Logger {
const [UserService, const Provider(Logger, useClass: EvenBetterLogger)]
// #enddocregion providers-5
)
class ProviderComponent5 {
class Provider5Component {
String log;
ProviderComponent5(Logger logger) {
Provider5Component(Logger logger) {
logger.log('Hello from EvenBetterlogger');
log = logger.logs[0];
}
@ -116,10 +116,10 @@ class OldLogger extends Logger {
const Provider(OldLogger, useClass: NewLogger)]
// #enddocregion providers-6a
)
class ProviderComponent6a {
class Provider6aComponent {
String log;
ProviderComponent6a(NewLogger newLogger, OldLogger oldLogger) {
Provider6aComponent(NewLogger newLogger, OldLogger oldLogger) {
if (newLogger == oldLogger) {
throw new Exception('expected the two loggers to be different instances');
}
@ -140,10 +140,10 @@ class ProviderComponent6a {
const Provider(OldLogger, useExisting: NewLogger)]
// #enddocregion providers-6b
)
class ProviderComponent6b {
class Provider6bComponent {
String log;
ProviderComponent6b(NewLogger newLogger, OldLogger oldLogger) {
Provider6bComponent(NewLogger newLogger, OldLogger oldLogger) {
if (newLogger != oldLogger) {
throw new Exception('expected the two loggers to be the same instance');
}
@ -178,10 +178,10 @@ const silentLogger = const SilentLogger();
const [const Provider(Logger, useValue: silentLogger)]
// #enddocregion providers-7
)
class ProviderComponent7 {
class Provider7Component {
String log;
ProviderComponent7(Logger logger) {
Provider7Component(Logger logger) {
logger.log('Hello from logger provided with useValue');
log = logger.logs[0];
}
@ -191,13 +191,13 @@ class ProviderComponent7 {
selector: 'provider-8',
template: '{{log}}',
providers: const [heroServiceProvider, Logger, UserService])
class ProviderComponent8 {
// #docregion provider-8-ctor
ProviderComponent8(HeroService heroService);
// #enddocregion provider-8-ctor
class Provider8Component {
// must be true else this component would have blown up at runtime
var log = 'Hero service injected successfully via heroServiceProvider';
// #docregion provider-8-ctor
Provider8Component(HeroService heroService);
// #enddocregion provider-8-ctor
}
@Component(
@ -208,12 +208,12 @@ class ProviderComponent8 {
const Provider(APP_CONFIG, useValue: heroDiConfig)]
// #enddocregion providers-9
)
class ProviderComponent9 implements OnInit {
class Provider9Component implements OnInit {
Map _config;
String log;
// #docregion provider-9-ctor
ProviderComponent9(@Inject(APP_CONFIG) this._config);
Provider9Component(@Inject(APP_CONFIG) this._config);
// #enddocregion provider-9-ctor
@override
@ -225,7 +225,7 @@ class ProviderComponent9 implements OnInit {
// Sample providers 1 to 7 illustrate a required logger dependency.
// Optional logger, can be null.
@Component(selector: 'provider-10', template: '{{log}}')
class ProviderComponent10 implements OnInit {
class Provider10Component implements OnInit {
final Logger _logger;
String log;
@ -234,11 +234,10 @@ class ProviderComponent10 implements OnInit {
HeroService(@Optional() this._logger) {
// #enddocregion provider-10-ctor
*/
ProviderComponent10(@Optional() this._logger) {
Provider10Component(@Optional() this._logger) {
const someMessage = 'Hello from the injected logger';
// #docregion provider-10-ctor
if (_logger != null)
_logger.log(someMessage);
_logger?.log(someMessage);
}
// #enddocregion provider-10-ctor
@ -263,15 +262,15 @@ class ProviderComponent10 implements OnInit {
<div id="p9"><provider-9></provider-9></div>
<div id="p10"><provider-10></provider-10></div>''',
directives: const [
ProviderComponent1,
ProviderComponent3,
ProviderComponent4,
ProviderComponent5,
ProviderComponent6a,
ProviderComponent6b,
ProviderComponent7,
ProviderComponent8,
ProviderComponent9,
ProviderComponent10
Provider1Component,
Provider3Component,
Provider4Component,
Provider5Component,
Provider6aComponent,
Provider6bComponent,
Provider7Component,
Provider8Component,
Provider9Component,
Provider10Component
])
class ProvidersComponent {}

View File

@ -20,7 +20,7 @@ class ChildComponent {
<div>-- projected content begins --</div>
<ng-content></ng-content>
<div>-- projected content ends --</div>
<p *ngIf="comment != null" class="comment">{{comment}}</p>
<p *ngIf="comment.isNotEmpty" class="comment">{{comment}}</p>
'''
// #enddocregion template
)

View File

@ -22,7 +22,7 @@ class ChildViewComponent {
<div>-- child view begins --</div>
<my-child></my-child>
<div>-- child view ends --</div>
<p *ngIf="comment != null" class="comment">{{comment}}</p>''',
<p *ngIf="comment.isNotEmpty" class="comment">{{comment}}</p>''',
// #enddocregion template
directives: const [ChildViewComponent])
// #docregion hooks

View File

@ -17,8 +17,8 @@ import 'spy_directive.dart';
styles: const [
'.counter {background: LightYellow; padding: 8px; margin-top: 8px}'
],
directives: const [Spy])
class MyCounter implements OnChanges {
directives: const [SpyDirective])
class MyCounterComponent implements OnChanges {
@Input() num counter;
List<String> changeLog = [];
@ -53,7 +53,7 @@ class MyCounter implements OnChanges {
</div>
''',
styles: const ['.parent {background: gold;}'],
directives: const [MyCounter],
directives: const [MyCounterComponent],
providers: const [LoggerService])
class CounterParentComponent {
final LoggerService _logger;

View File

@ -11,7 +11,7 @@ import 'spy_directive.dart';
'.parent {background: khaki}',
'.heroes {background: LightYellow; padding: 0 8px}'
],
directives: const [Spy],
directives: const [SpyDirective],
providers: const [LoggerService])
class SpyParentComponent {
final LoggerService _logger;

View File

@ -9,10 +9,10 @@ int _nextId = 1;
// Spy on any element to which it is applied.
// Usage: <div mySpy>...</div>
@Directive(selector: '[mySpy]')
class Spy implements OnInit, OnDestroy {
class SpyDirective implements OnInit, OnDestroy {
final LoggerService _logger;
Spy(this._logger);
SpyDirective(this._logger);
ngOnInit() => _logIt('onInit');

View File

@ -32,7 +32,7 @@
"@angular/http": "2.0.0-rc.3",
"@angular/platform-browser": "2.0.0-rc.3",
"@angular/platform-browser-dynamic": "2.0.0-rc.3",
"@angular/router": "3.0.0-alpha.7",
"@angular/router": "3.0.0-alpha.8",
"@angular/router-deprecated": "2.0.0-rc.2",
"@angular/upgrade": "2.0.0-rc.3",
"angular2-in-memory-web-api": "0.0.12",
@ -72,7 +72,7 @@
"style-loader": "^0.13.1",
"ts-loader": "^0.8.2",
"ts-node": "^0.7.3",
"typescript": "^1.9.0-dev.20160409",
"typescript": "^1.8.10",
"typings": "^1.0.4",
"webpack": "^1.13.0",
"webpack-dev-server": "^1.14.1",

View File

@ -16,11 +16,11 @@ import 'power_booster_component.dart';
FlyingHeroesComponent,
FlyingHeroesImpureComponent,
HeroAsyncMessageComponent,
HeroBirthday,
HeroBirthday2,
HeroBirthdayComponent,
HeroBirthday2Component,
HeroListComponent,
PowerBoostCalculator,
PowerBooster,
PowerBoostCalculatorComponent,
PowerBoosterComponent,
])
class AppComponent {
DateTime birthday = new DateTime(1988, 4, 15); // April 15, 1988

View File

@ -7,6 +7,6 @@ import 'package:angular2/angular2.dart';
template: "<p>The hero's birthday is {{ birthday | date }}</p>"
// #enddocregion hero-birthday-template
)
class HeroBirthday {
class HeroBirthdayComponent {
DateTime birthday = new DateTime(1988, 4, 15); // April 15, 1988
}

View File

@ -11,7 +11,7 @@ import 'package:angular2/angular2.dart';
// #enddocregion template
)
// #docregion class
class HeroBirthday2 {
class HeroBirthday2Component {
DateTime birthday = new DateTime(1988, 4, 15); // April 15, 1988
bool toggle = true;

View File

@ -13,7 +13,7 @@ import 'exponential_strength_pipe.dart';
</p>
''',
pipes: const [ExponentialStrengthPipe])
class PowerBoostCalculator {
class PowerBoostCalculatorComponent {
num power = 5;
num factor = 1;
}

View File

@ -9,4 +9,4 @@ import 'exponential_strength_pipe.dart';
<p>Super power boost: {{2 | exponentialStrength: 10}}</p>
''',
pipes: const [ExponentialStrengthPipe])
class PowerBooster {}
class PowerBoosterComponent {}

View File

@ -5,5 +5,5 @@ import 'package:pipe_examples/hero_birthday1_component.dart';
main() {
bootstrap(AppComponent);
bootstrap(HeroBirthday);
bootstrap(HeroBirthdayComponent);
}

View File

@ -14,7 +14,7 @@
"@angular/http": "2.0.0-rc.3",
"@angular/platform-browser": "2.0.0-rc.3",
"@angular/platform-browser-dynamic": "2.0.0-rc.3",
"@angular/router": "3.0.0-alpha.7",
"@angular/router": "3.0.0-alpha.8",
"@angular/router-deprecated": "2.0.0-rc.2",
"@angular/upgrade": "2.0.0-rc.3",

View File

@ -18,7 +18,7 @@
"@angular/http": "2.0.0-rc.3",
"@angular/platform-browser": "2.0.0-rc.3",
"@angular/platform-browser-dynamic": "2.0.0-rc.3",
"@angular/router": "3.0.0-alpha.7",
"@angular/router": "3.0.0-alpha.8",
"@angular/router-deprecated": "2.0.0-rc.2",
"@angular/upgrade": "2.0.0-rc.3",

View File

@ -9,8 +9,8 @@
<!-- #enddocregion asterisk -->
<!-- #docregion ngSwitch -->
<div [ngSwitch]="status">
<template [ngSwitchWhen]="'in-mission'">In Mission</template>
<template [ngSwitchWhen]="'ready'">Ready</template>
<template [ngSwitchCase]="'in-mission'">In Mission</template>
<template [ngSwitchCase]="'ready'">Ready</template>
<template ngSwitchDefault>Unknown</template>
</div>
<!-- #enddocregion ngSwitch -->

View File

@ -54,7 +54,7 @@ nav a:hover {
color: #039be5;
background-color: #CFD8DC;
}
nav a.router-link-active {
nav a.active {
color: #039be5;
}

View File

@ -8,6 +8,7 @@
var ngVer = '@2.0.0-rc.3'; // lock in the angular package version; do not let it float to current!
var routerVer = '@3.0.0-alpha.7'; // lock router version
var formsVer = '@0.1.1'; // lock forms version
var routerDeprecatedVer = '@2.0.0-rc.2'; // temporarily until we update all the guides
//map tells the System loader where to look for things
var map = {
@ -16,6 +17,7 @@
'@angular': 'https://npmcdn.com/@angular', // sufficient if we didn't pin the version
'@angular/router': 'https://npmcdn.com/@angular/router' + routerVer,
'@angular/forms': 'https://npmcdn.com/@angular/forms' + formsVer,
'@angular/router-deprecated': 'https://npmcdn.com/@angular/router-deprecated' + routerDeprecatedVer,
'angular2-in-memory-web-api': 'https://npmcdn.com/angular2-in-memory-web-api', // get latest
'rxjs': 'https://npmcdn.com/rxjs@5.0.0-beta.6',
'ts': 'https://npmcdn.com/plugin-typescript@4.0.10/lib/plugin.js',
@ -36,7 +38,6 @@
'http',
'platform-browser',
'platform-browser-dynamic',
'router-deprecated',
'upgrade',
];
@ -62,6 +63,9 @@
// Forms not on rc yet
packages['@angular/forms'] = { main: 'index.js', defaultExtension: 'js' };
// Temporarily until we update the guides
packages['@angular/router-deprecated'] = { main: '/bundles/router-deprecated' + '.umd.js', defaultExtension: 'js' };
var config = {
// DEMO ONLY! REAL CODE SHOULD NOT TRANSPILE IN THE BROWSER
transpiler: 'ts',

View File

@ -4,8 +4,6 @@ import 'package:angular2/core.dart';
import 'hero.dart';
var nextHeroDetailId = 1;
// #docregion input-output-2
@Component(
// #enddocregion input-output-2

View File

@ -498,18 +498,18 @@ bindon-ngModel
<!-- with *NgSwitch -->
<!-- #docregion NgSwitch -->
<span *ngSwitchWhen="'Eenie'">Eenie</span>
<span *ngSwitchWhen="'Meanie'">Meanie</span>
<span *ngSwitchWhen="'Miney'">Miney</span>
<span *ngSwitchWhen="'Moe'">Moe</span>
<span *ngSwitchCase="'Eenie'">Eenie</span>
<span *ngSwitchCase="'Meanie'">Meanie</span>
<span *ngSwitchCase="'Miney'">Miney</span>
<span *ngSwitchCase="'Moe'">Moe</span>
<span *ngSwitchDefault>other</span>
<!-- #enddocregion NgSwitch -->
<!-- with <template> -->
<template [ngSwitchWhen]="'Eenie'"><span>Eenie</span></template>
<template [ngSwitchWhen]="'Meanie'"><span>Meanie</span></template>
<template [ngSwitchWhen]="'Miney'"><span>Miney</span></template>
<template [ngSwitchWhen]="'Moe'"><span>Moe</span></template>
<template [ngSwitchCase]="'Eenie'"><span>Eenie</span></template>
<template [ngSwitchCase]="'Meanie'"><span>Meanie</span></template>
<template [ngSwitchCase]="'Miney'"><span>Miney</span></template>
<template [ngSwitchCase]="'Moe'"><span>Moe</span></template>
<template ngSwitchDefault><span>other</span></template>
<!-- #docregion NgSwitch -->

View File

@ -8,6 +8,21 @@ class Hero {
Hero(this.id, this.name);
}
// #docregion hero-array
final List<Hero> mockHeroes = [
new Hero(11, 'Mr. Nice'),
new Hero(12, 'Narco'),
new Hero(13, 'Bombasto'),
new Hero(14, 'Celeritas'),
new Hero(15, 'Magneta'),
new Hero(16, 'RubberMan'),
new Hero(17, 'Dynama'),
new Hero(18, 'Dr IQ'),
new Hero(19, 'Magma'),
new Hero(20, 'Tornado')
];
// #enddocregion hero-array
@Component(
selector: 'my-app',
template: '''
@ -94,18 +109,3 @@ class AppComponent {
}
// #enddocregion on-select
}
// #enddocregion
// #docregion hero-array
final List<Hero> mockHeroes = [
new Hero(11, 'Mr. Nice'),
new Hero(12, 'Narco'),
new Hero(13, 'Bombasto'),
new Hero(14, 'Celeritas'),
new Hero(15, 'Magneta'),
new Hero(16, 'RubberMan'),
new Hero(17, 'Dynama'),
new Hero(18, 'Dr IQ'),
new Hero(19, 'Magma'),
new Hero(20, 'Tornado')
];

View File

@ -8,6 +8,19 @@ import 'hero.dart';
import 'hero_detail_component.dart';
// #enddocregion hero-detail-import
final List<Hero> mockHeroes = [
new Hero(11, 'Mr. Nice'),
new Hero(12, 'Narco'),
new Hero(13, 'Bombasto'),
new Hero(14, 'Celeritas'),
new Hero(15, 'Magneta'),
new Hero(16, 'RubberMan'),
new Hero(17, 'Dynama'),
new Hero(18, 'Dr IQ'),
new Hero(19, 'Magma'),
new Hero(20, 'Tornado')
];
@Component(
selector: 'my-app',
// #docregion hero-detail-template
@ -87,16 +100,3 @@ class AppComponent {
selectedHero = hero;
}
}
final List<Hero> mockHeroes = [
new Hero(11, 'Mr. Nice'),
new Hero(12, 'Narco'),
new Hero(13, 'Bombasto'),
new Hero(14, 'Celeritas'),
new Hero(15, 'Magneta'),
new Hero(16, 'RubberMan'),
new Hero(17, 'Dynama'),
new Hero(18, 'Dr IQ'),
new Hero(19, 'Magma'),
new Hero(20, 'Tornado')
];

View File

@ -32,7 +32,7 @@ class DashboardComponent implements OnInit {
// #enddocregion ctor
Future<Null> ngOnInit() async {
heroes = (await _heroService.getHeroes()).getRange(1, 5).toList();
heroes = (await _heroService.getHeroes()).skip(1).take(4).toList();
}
// #docregion goto-detail

View File

@ -19,7 +19,7 @@ class DashboardComponent implements OnInit {
DashboardComponent(this._heroService);
Future<Null> ngOnInit() async {
heroes = (await _heroService.getHeroes()).getRange(1, 5).toList();
heroes = (await _heroService.getHeroes()).skip(1).take(4).toList();
}
gotoDetail() {/* not implemented yet */}

View File

@ -1,6 +1,5 @@
// #docplaster
// #docregion
// #docregion v2
// #docregion , v2
import 'dart:async';
import 'dart:html';

View File

@ -6,7 +6,7 @@
margin: 0 0 2em 0;
list-style-type: none;
padding: 0;
width: 10em;
width: 15em;
}
.heroes li {
cursor: pointer;

View File

@ -15,9 +15,8 @@ import 'hero_service.dart';
// #enddocregion heroes-component-renaming
templateUrl: 'heroes_component.html',
styleUrls: const ['heroes_component.css'],
directives: const [HeroDetailComponent]
directives: const [HeroDetailComponent])
// #docregion heroes-component-renaming
)
// #enddocregion heroes-component-renaming, metadata
// #docregion class, heroes-component-renaming
class HeroesComponent implements OnInit {
@ -37,9 +36,13 @@ class HeroesComponent implements OnInit {
getHeroes();
}
void onSelect(Hero hero) { selectedHero = hero; }
void onSelect(Hero hero) {
selectedHero = hero;
}
Future<Null> gotoDetail() =>
_router.navigate(['HeroDetail', {'id': selectedHero.id.toString()}]);
Future<Null> gotoDetail() => _router.navigate([
'HeroDetail',
{'id': selectedHero.id.toString()}
]);
// #docregion heroes-component-renaming
}

View File

@ -8,7 +8,7 @@ import { HeroesComponent } from './heroes.component';
// #enddocregion
// For testing only
import { RouteConfig, ROUTER_DIRECTIVES, ROUTER_PROVIDERS } from '@angular/router-deprecated';
import { ROUTER_DIRECTIVES } from '@angular/router';
// #docregion
@Component({
@ -20,7 +20,6 @@ import { RouteConfig, ROUTER_DIRECTIVES, ROUTER_PROVIDERS } from '@angular/route
directives: [HeroesComponent],
providers: [
// #enddocregion
ROUTER_PROVIDERS,
// #docregion
HeroService
]

View File

@ -2,38 +2,27 @@
// #docregion
import { Component } from '@angular/core';
// #docregion import-router
import { RouteConfig, ROUTER_DIRECTIVES, ROUTER_PROVIDERS } from '@angular/router-deprecated';
import { ROUTER_DIRECTIVES } from '@angular/router';
// #enddocregion import-router
import { HeroService } from './hero.service';
import { HeroesComponent } from './heroes.component';
@Component({
selector: 'my-app',
// #docregion template
template: `
<h1>{{title}}</h1>
<a [routerLink]="['Heroes']">Heroes</a>
<a [routerLink]="['/heroes']">Heroes</a>
<router-outlet></router-outlet>
`,
// #enddocregion template
// #docregion directives-and-providers
directives: [ROUTER_DIRECTIVES],
providers: [
ROUTER_PROVIDERS,
HeroService
]
// #enddocregion directives-and-providers
})
// #docregion route-config
@RouteConfig([
{
path: '/heroes',
name: 'Heroes',
component: HeroesComponent
}
])
// #enddocregion route-config
export class AppComponent {
title = 'Tour of Heroes';
}

View File

@ -0,0 +1,33 @@
// #docplaster
// #docregion
import { Component } from '@angular/core';
import { ROUTER_DIRECTIVES } from '@angular/router';
import { HeroService } from './hero.service';
@Component({
selector: 'my-app',
// #docregion template
template: `
<h1>{{title}}</h1>
<nav>
// #docregion router-link-active
<a [routerLink]="['/dashboard']" routerLinkActive="active">Dashboard</a>
<a [routerLink]="['/heroes']" routerLinkActive="active">Heroes</a>
// #enddocregion router-link-active
</nav>
<router-outlet></router-outlet>
`,
// #enddocregion template
// #docregion style-urls
styleUrls: ['app/app.component.css'],
// #enddocregion style-urls
directives: [ROUTER_DIRECTIVES],
providers: [
HeroService
]
})
export class AppComponent {
title = 'Tour of Heroes';
}
// #enddocregion

View File

@ -24,6 +24,6 @@ nav a:hover {
color: #039be5;
background-color: #CFD8DC;
}
nav a.router-link-active {
nav a.active {
color: #039be5;
}

View File

@ -1,13 +1,8 @@
// #docplaster
// #docregion
import { Component } from '@angular/core';
import { RouteConfig, ROUTER_DIRECTIVES, ROUTER_PROVIDERS } from '@angular/router-deprecated';
import { ROUTER_DIRECTIVES } from '@angular/router';
import { DashboardComponent } from './dashboard.component';
import { HeroesComponent } from './heroes.component';
// #docregion hero-detail-import
import { HeroDetailComponent } from './hero-detail.component';
// #enddocregion hero-detail-import
import { HeroService } from './hero.service';
@Component({
@ -16,8 +11,8 @@ import { HeroService } from './hero.service';
template: `
<h1>{{title}}</h1>
<nav>
<a [routerLink]="['Dashboard']">Dashboard</a>
<a [routerLink]="['Heroes']">Heroes</a>
<a [routerLink]="['/dashboard']" routerLinkActive="active">Dashboard</a>
<a [routerLink]="['/heroes']" routerLinkActive="active">Heroes</a>
</nav>
<router-outlet></router-outlet>
`,
@ -27,32 +22,9 @@ import { HeroService } from './hero.service';
// #enddocregion style-urls
directives: [ROUTER_DIRECTIVES],
providers: [
ROUTER_PROVIDERS,
HeroService
]
})
@RouteConfig([
// #docregion dashboard-route
{
path: '/dashboard',
name: 'Dashboard',
component: DashboardComponent,
useAsDefault: true
},
// #enddocregion dashboard-route
// #docregion hero-detail-route
{
path: '/detail/:id',
name: 'HeroDetail',
component: HeroDetailComponent
},
// #enddocregion hero-detail-route
{
path: '/heroes',
name: 'Heroes',
component: HeroesComponent
}
])
export class AppComponent {
title = 'Tour of Heroes';
}

View File

@ -0,0 +1,37 @@
// #docregion
import { provideRouter, RouterConfig } from '@angular/router';
import { DashboardComponent } from './dashboard.component';
import { HeroesComponent } from './heroes.component';
// #docregion hero-detail-import
import { HeroDetailComponent } from './hero-detail.component';
// #enddocregion hero-detail-import
export const routes: RouterConfig = [
// #docregion redirect-route
{
path: '',
redirectTo: '/dashboard',
terminal: true
},
// #enddocregion redirect-route
// #docregion dashboard-route
{
path: 'dashboard',
component: DashboardComponent
},
// #enddocregion dashboard-route
// #docregion hero-detail-route
{
path: 'detail/:id',
component: HeroDetailComponent
},
// #enddocregion hero-detail-route
{
path: 'heroes',
component: HeroesComponent
}
];
export const APP_ROUTER_PROVIDERS = [
provideRouter(routes)
];

View File

@ -0,0 +1,14 @@
// #docregion
import { provideRouter, RouterConfig } from '@angular/router';
import { HeroesComponent } from './heroes.component';
const routes: RouterConfig = [
{
path: '/heroes',
component: HeroesComponent
}
];
export const APP_ROUTER_PROVIDERS = [
provideRouter(routes)
];

View File

@ -0,0 +1,32 @@
// #docregion
import { provideRouter, RouterConfig } from '@angular/router';
import { DashboardComponent } from './dashboard.component';
import { HeroesComponent } from './heroes.component';
// #docregion hero-detail-import
import { HeroDetailComponent } from './hero-detail.component';
// #enddocregion hero-detail-import
export const routes: RouterConfig = [
{
path: '',
redirectTo: '/dashboard',
terminal: true
},
{
path: 'dashboard',
component: DashboardComponent
},
{
path: 'detail/:id',
component: HeroDetailComponent
},
{
path: 'heroes',
component: HeroesComponent
}
];
export const APP_ROUTER_PROVIDERS = [
provideRouter(routes)
];

View File

@ -2,7 +2,7 @@
// #docregion
import { Component, OnInit } from '@angular/core';
// #docregion import-router
import { Router } from '@angular/router-deprecated';
import { Router } from '@angular/router';
// #enddocregion import-router
import { Hero } from './hero';
@ -36,7 +36,7 @@ export class DashboardComponent implements OnInit {
// #docregion goto-detail
gotoDetail(hero: Hero) {
let link = ['HeroDetail', { id: hero.id }];
let link = ['/detail', hero.id];
this.router.navigate(link);
}
// #enddocregion goto-detail

View File

@ -1,11 +1,11 @@
// #docplaster
// #docregion
// #docregion import-oninit, v2
import { Component, OnInit } from '@angular/core';
import { Component, OnInit, OnDestroy } from '@angular/core';
// #enddocregion import-oninit
// #docregion import-route-params
import { RouteParams } from '@angular/router-deprecated';
// #enddocregion import-route-params
// #docregion import-activated-route
import { ActivatedRoute } from '@angular/router';
// #enddocregion import-activated-route
import { Hero } from './hero';
// #docregion import-hero-service
@ -23,27 +23,36 @@ import { HeroService } from './hero.service';
})
// #enddocregion extract-template
// #docregion implement
export class HeroDetailComponent implements OnInit {
export class HeroDetailComponent implements OnInit, OnDestroy {
// #enddocregion implement
hero: Hero;
sub: any;
// #docregion ctor
constructor(
private heroService: HeroService,
private routeParams: RouteParams) {
private route: ActivatedRoute) {
}
// #enddocregion ctor
// #docregion ng-oninit
ngOnInit() {
// #docregion get-id
let id = +this.routeParams.get('id');
// #enddocregion get-id
this.sub = this.route.params.subscribe(params => {
let id = +params['id'];
this.heroService.getHero(id)
.then(hero => this.hero = hero);
});
// #enddocregion get-id
}
// #enddocregion ng-oninit
// #docregion ng-ondestroy
ngOnDestroy() {
this.sub.unsubscribe();
}
// #enddocregion ng-ondestroy
// #docregion go-back
goBack() {
window.history.back();

View File

@ -1,7 +1,7 @@
// #docplaster
// #docregion
import { Component, OnInit } from '@angular/core';
import { Router } from '@angular/router-deprecated';
import { Router } from '@angular/router';
import { Hero } from './hero';
import { HeroService } from './hero.service';
@ -36,7 +36,7 @@ export class HeroesComponent implements OnInit {
onSelect(hero: Hero) { this.selectedHero = hero; }
gotoDetail() {
this.router.navigate(['HeroDetail', { id: this.selectedHero.id }]);
this.router.navigate(['/detail', this.selectedHero.id]);
}
// #docregion heroes-component-renaming
}

View File

@ -1,5 +1,9 @@
// #docregion
import { bootstrap } from '@angular/platform-browser-dynamic';
import { AppComponent } from './app.component';
import { APP_ROUTER_PROVIDERS } from './app.routes';
bootstrap(AppComponent);
bootstrap(AppComponent, [
APP_ROUTER_PROVIDERS
]);

View File

@ -3,7 +3,7 @@
"files":[
"!**/*.d.ts",
"!**/*.js",
"!**/*.[1,2].*"
"!**/*.[1,2,3].*"
],
"tags": ["tutorial", "tour", "heroes", "router"]
}

View File

@ -0,0 +1,5 @@
{
"title": "Tour of Heroes: HTTP",
"docPart": "tutorial",
"docHref": "toh-pt6.html"
}

View File

@ -0,0 +1,29 @@
/* #docregion */
h1 {
font-size: 1.2em;
color: #999;
margin-bottom: 0;
}
h2 {
font-size: 2em;
margin-top: 0;
padding-top: 0;
}
nav a {
padding: 5px 10px;
text-decoration: none;
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.router-link-active {
color: #039be5;
}

View File

@ -0,0 +1,45 @@
// #docplaster
// #docregion
import 'package:angular2/core.dart';
import 'package:angular2/router.dart';
import 'package:angular2_tour_of_heroes/heroes_component.dart';
import 'package:angular2_tour_of_heroes/hero_service.dart';
import 'package:angular2_tour_of_heroes/dashboard_component.dart';
// #docregion hero-detail-import
import 'package:angular2_tour_of_heroes/hero_detail_component.dart';
// #enddocregion hero-detail-import
@Component(
selector: 'my-app',
// #docregion template
template: '''
<h1>{{title}}</h1>
<nav>
<a [routerLink]="['Dashboard']">Dashboard</a>
<a [routerLink]="['Heroes']">Heroes</a>
</nav>
<router-outlet></router-outlet>''',
// #enddocregion template
// #docregion style-urls
styleUrls: const ['app_component.css'],
// #enddocregion style-urls
directives: const [ROUTER_DIRECTIVES],
providers: const [HeroService, ROUTER_PROVIDERS])
@RouteConfig(const [
// #docregion dashboard-route
const Route(
path: '/dashboard',
name: 'Dashboard',
component: DashboardComponent,
useAsDefault: true),
// #enddocregion dashboard-route
// #docregion hero-detail-route
const Route(
path: '/detail/:id', name: 'HeroDetail', component: HeroDetailComponent),
// #enddocregion hero-detail-route
const Route(path: '/heroes', name: 'Heroes', component: HeroesComponent)
])
class AppComponent {
String title = 'Tour of Heroes';
}

View File

@ -0,0 +1,61 @@
/* #docregion */
[class*='col-'] {
float: left;
}
*, *:after, *:before {
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
}
h3 {
text-align: center; margin-bottom: 0;
}
[class*='col-'] {
padding-right: 20px;
padding-bottom: 20px;
}
[class*='col-']:last-of-type {
padding-right: 0;
}
.grid {
margin: 0;
}
.col-1-4 {
width: 25%;
}
.module {
padding: 20px;
text-align: center;
color: #eee;
max-height: 120px;
min-width: 120px;
background-color: #607D8B;
border-radius: 2px;
}
h4 {
position: relative;
}
.module:hover {
background-color: #EEE;
cursor: pointer;
color: #607d8b;
}
.grid-pad {
padding: 10px 0;
}
.grid-pad > [class*='col-']:last-of-type {
padding-right: 20px;
}
@media (max-width: 600px) {
.module {
font-size: 10px;
max-height: 75px; }
}
@media (max-width: 1024px) {
.grid {
margin: 0;
}
.module {
min-width: 60px;
}
}

View File

@ -0,0 +1,47 @@
// #docplaster
// #docregion
import 'dart:async';
import 'package:angular2/core.dart';
// #docregion import-router
import 'package:angular2/router.dart';
// #enddocregion import-router
import 'hero.dart';
import 'hero_service.dart';
@Component(
selector: 'my-dashboard',
// #docregion template-url
templateUrl: 'dashboard_component.html',
// #enddocregion template-url
// #docregion css
styleUrls: const ['dashboard_component.css']
// #enddocregion css
)
// #docregion component
class DashboardComponent implements OnInit {
List<Hero> heroes;
// #docregion ctor
final Router _router;
final HeroService _heroService;
DashboardComponent(this._heroService, this._router);
// #enddocregion ctor
Future<Null> ngOnInit() async {
heroes = (await _heroService.getHeroes()).skip(1).take(4).toList();
}
// #docregion goto-detail
void gotoDetail(Hero hero) {
var link = [
'HeroDetail',
{'id': hero.id.toString()}
];
_router.navigate(link);
}
// #enddocregion goto-detail
}

View File

@ -0,0 +1,11 @@
<!-- #docregion -->
<h3>Top Heroes</h3>
<div class="grid grid-pad">
<!-- #docregion click -->
<div *ngFor="let hero of heroes" (click)="gotoDetail(hero)" class="col-1-4" >
<!-- #enddocregion click -->
<div class="module hero">
<h4>{{hero.name}}</h4>
</div>
</div>
</div>

View File

@ -0,0 +1,14 @@
// #docregion
class Hero {
final int id;
String name;
Hero(this.id, this.name);
factory Hero.fromJson(Map<String, dynamic> hero) =>
new Hero(_toInt(hero['id']), hero['name']);
Map toJson() => {'id': id, 'name': name};
}
int _toInt(id) => id is int ? id : int.parse(id);

View File

@ -0,0 +1,30 @@
/* #docregion */
label {
display: inline-block;
width: 3em;
margin: .5em 0;
color: #607D8B;
font-weight: bold;
}
input {
height: 2em;
font-size: 1em;
padding-left: .4em;
}
button {
margin-top: 20px;
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: #ccc;
cursor: auto;
}

View File

@ -0,0 +1,61 @@
// #docplaster
// #docregion , v2
import 'dart:async';
import 'dart:html';
// #docregion import-oninit
import 'package:angular2/core.dart';
// #enddocregion import-oninit
// #docregion import-route-params
import 'package:angular2/router.dart';
// #enddocregion import-route-params
import 'hero.dart';
// #docregion import-hero-service
import 'hero_service.dart';
// #enddocregion import-hero-service
// #docregion extract-template
@Component(
selector: 'my-hero-detail',
// #docregion template-url
templateUrl: 'hero_detail_component.html',
// #enddocregion template-url, v2
styleUrls: const ['hero_detail_component.css']
// #docregion v2
)
// #enddocregion extract-template
// #docregion implement
class HeroDetailComponent implements OnInit {
// #enddocregion implement
Hero hero;
// #docregion ctor
final HeroService _heroService;
final RouteParams _routeParams;
HeroDetailComponent(this._heroService, this._routeParams);
// #enddocregion ctor
// #docregion ng-oninit
Future<Null> ngOnInit() async {
// #docregion get-id
var idString = _routeParams.get('id');
var id = int.parse(idString, onError: (_) => null);
// #enddocregion get-id
if (id != null) hero = await (_heroService.getHero(id));
}
// #enddocregion ng-oninit
// #docregion save
Future<Null> save() async {
await _heroService.save(hero);
goBack();
}
// #enddocregion save
// #docregion go-back
void goBack() {
window.history.back();
}
// #enddocregion go-back
}

View File

@ -0,0 +1,15 @@
<!-- #docplaster -->
<!-- #docregion -->
<div *ngIf="hero != null">
<h2>{{hero.name}} details!</h2>
<div>
<label>id: </label>{{hero.id}}</div>
<div>
<label>name: </label>
<input [(ngModel)]="hero.name" placeholder="name" />
</div>
<button (click)="goBack()">Back</button>
<!-- #docregion save -->
<button (click)="save()">Save</button>
<!-- #enddocregion save -->
</div>

View File

@ -0,0 +1,91 @@
// #docregion
import 'dart:async';
import 'dart:convert';
import 'package:angular2/core.dart';
import 'package:http/http.dart';
import 'hero.dart';
@Injectable()
class HeroService {
// #docregion post
static final _headers = {'Content-Type': 'application/json'};
// #enddocregion post
// #docregion getHeroes
static const _heroesUrl = 'app/heroes'; // URL to web API
final Client _http;
HeroService(this._http);
Future<List<Hero>> getHeroes() async {
try {
final response = await _http.get(_heroesUrl);
final heroes = _extractData(response)
.map((value) => new Hero.fromJson(value))
.toList();
return heroes;
// #docregion catch
} catch (e) {
throw _handleError(e);
}
// #enddocregion catch
}
// #docregion extract-data
dynamic _extractData(Response resp) => JSON.decode(resp.body)['data'];
// #enddocregion extract-data, getHeroes
Future<Hero> getHero(int id) async =>
(await getHeroes()).firstWhere((hero) => hero.id == id);
// #docregion save
Future<Hero> save(dynamic heroOrName) =>
heroOrName is Hero ? _put(heroOrName) : _post(heroOrName);
// #enddocregion save
// #docregion handleError
Exception _handleError(dynamic e) {
print(e); // for demo purposes only
return new Exception('Server error; cause: $e');
}
// #enddocregion handleError
// #docregion post
Future<Hero> _post(String name) async {
try {
final response = await _http.post(_heroesUrl,
headers: _headers, body: JSON.encode({'name': name}));
return new Hero.fromJson(_extractData(response));
} catch (e) {
throw _handleError(e);
}
}
// #enddocregion post
// #docregion put
Future<Hero> _put(Hero hero) async {
try {
var url = '$_heroesUrl/${hero.id}';
final response =
await _http.put(url, headers: _headers, body: JSON.encode(hero));
return new Hero.fromJson(_extractData(response));
} catch (e) {
throw _handleError(e);
}
}
// #enddocregion put
// #docregion delete
Future<Null> delete(int id) async {
try {
var url = '$_heroesUrl/$id';
await _http.delete(url, headers: _headers);
} catch (e) {
throw _handleError(e);
}
}
// #enddocregion delete
}

View File

@ -0,0 +1,59 @@
.selected {
background-color: #CFD8DC !important;
color: white;
}
.heroes {
margin: 0 0 2em 0;
list-style-type: none;
padding: 0;
width: 15em;
}
.heroes li {
cursor: pointer;
position: relative;
left: 0;
background-color: #EEE;
margin: .5em;
padding: .3em 0;
height: 1.6em;
border-radius: 4px;
}
.heroes li:hover {
color: #607D8B;
background-color: #DDD;
left: .1em;
}
.heroes li.selected:hover {
background-color: #BBD8DC !important;
color: white;
}
.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;
}
button {
font-family: Arial;
background-color: #eee;
border: none;
padding: 5px 10px;
border-radius: 4px;
cursor: pointer;
cursor: hand;
}
button:hover {
background-color: #cfd8dc;
}

View File

@ -0,0 +1,69 @@
// #docplaster
// #docregion
import 'dart:async';
import 'package:angular2/core.dart';
import 'package:angular2/router.dart';
import 'hero.dart';
import 'hero_detail_component.dart';
import 'hero_service.dart';
@Component(
selector: 'my-heroes',
templateUrl: 'heroes_component.html',
styleUrls: const ['heroes_component.css'],
directives: const [HeroDetailComponent])
class HeroesComponent implements OnInit {
final Router _router;
final HeroService _heroService;
List<Hero> heroes;
Hero selectedHero;
// #docregion error
String errorMessage;
// #enddocregion error
HeroesComponent(this._heroService, this._router);
// #docregion addHero
Future<Null> addHero(String name) async {
name = name.trim();
if (name.isEmpty) return;
try {
heroes.add(await _heroService.save(name));
} catch (e) {
errorMessage = e.toString();
}
}
// #enddocregion addHero
// #docregion deleteHero
Future<Null> deleteHero(int id, event) async {
try {
event.stopPropagation();
await _heroService.delete(id);
heroes.removeWhere((hero) => hero.id == id);
if (selectedHero?.id == id) selectedHero = null;
} catch (e) {
errorMessage = e.toString();
}
}
// #enddocregion deleteHero
Future<Null> getHeroes() async {
heroes = await _heroService.getHeroes();
}
void ngOnInit() {
getHeroes();
}
void onSelect(Hero hero) {
selectedHero = hero;
}
Future<Null> gotoDetail() => _router.navigate([
'HeroDetail',
{'id': selectedHero.id.toString()}
]);
}

View File

@ -0,0 +1,31 @@
<!-- #docplaster -->
<!-- #docregion -->
<h2>My Heroes</h2>
<!-- #docregion add-and-error -->
<div class="error" *ngIf="errorMessage != null">{{errorMessage}}</div>
<div>
Name: <input #newHeroName />
<button (click)="addHero(newHeroName.value); newHeroName.value=''">
Add New Hero
</button>
</div>
<!-- #enddocregion add-and-error -->
<ul class="heroes">
<li *ngFor="let hero of heroes"
[class.selected]="hero === selectedHero"
(click)="onSelect(hero)">
<span class="badge">{{hero.id}}</span> {{hero.name}}
<!-- #docregion delete -->
<button class="delete-button" (click)="deleteHero(hero.id, $event)">x</button>
<!-- #enddocregion delete -->
</li>
</ul>
<!-- #docregion mini-detail -->
<div *ngIf="selectedHero != null">
<h2>
<!-- #docregion pipe -->
{{selectedHero.name | uppercase}} is my hero
<!-- #enddocregion pipe -->
</h2>
<button (click)="gotoDetail()">View Details</button>
</div>

View File

@ -0,0 +1,64 @@
// #docregion
import 'dart:async';
import 'dart:convert';
// #docregion init
import 'package:angular2/core.dart';
import 'package:http/http.dart';
import 'package:http/testing.dart';
import 'hero.dart';
@Injectable()
class InMemoryDataService extends MockClient {
static final _initialHeroes = [
{'id': 11, 'name': 'Mr. Nice'},
{'id': 12, 'name': 'Narco'},
{'id': 13, 'name': 'Bombasto'},
{'id': 14, 'name': 'Celeritas'},
{'id': 15, 'name': 'Magneta'},
{'id': 16, 'name': 'RubberMan'},
{'id': 17, 'name': 'Dynama2'},
{'id': 18, 'name': 'Dr IQ'},
{'id': 19, 'name': 'Magma'},
{'id': 20, 'name': 'Tornado'}
];
// #enddocregion init
static final List<Hero> _heroesDb =
_initialHeroes.map((json) => new Hero.fromJson(json)).toList();
static int _nextId = 21;
static Future<Response> _handler(Request request) async {
var data;
switch (request.method) {
case 'GET':
data = _heroesDb;
break;
case 'POST':
var name = JSON.decode(request.body)['name'];
var newHero = new Hero(_nextId++, name);
_heroesDb.add(newHero);
data = newHero;
break;
case 'PUT':
var heroChanges = new Hero.fromJson(JSON.decode(request.body));
var targetHero = _heroesDb.firstWhere((h) => h.id == heroChanges.id);
targetHero.name = heroChanges.name;
data = targetHero;
break;
case 'DELETE':
var id = int.parse(request.url.pathSegments.last);
_heroesDb.removeWhere((hero) => hero.id == id);
// No data, so leave it as null.
break;
default:
throw 'Unimplemented HTTP method ${request.method}';
}
return new Response(JSON.encode({'data': data}), 200,
headers: {'content-type': 'application/json'});
}
InMemoryDataService() : super(_handler);
// #docregion init
}

View File

@ -0,0 +1,28 @@
# #docregion , additions
name: angular2_tour_of_heroes
# #enddocregion additions
description: Tour of Heroes
version: 0.0.1
environment:
sdk: '>=1.13.0 <2.0.0'
# #docregion additions
dependencies:
angular2: 2.0.0-beta.17
# #enddocregion additions
browser: ^0.10.0
dart_to_js_script_rewriter: ^1.0.1
# #docregion additions
http: ^0.11.0
transformers:
- angular2:
# #enddocregion additions
platform_directives:
- 'package:angular2/common.dart#COMMON_DIRECTIVES'
platform_pipes:
- 'package:angular2/common.dart#COMMON_PIPES'
# #docregion additions
entry_points: web/main.dart
resolved_identifiers:
BrowserClient: 'package:http/browser_client.dart'
Client: 'package:http/http.dart'
- dart_to_js_script_rewriter

View File

@ -0,0 +1,18 @@
<!DOCTYPE html>
<!-- #docregion -->
<html>
<head>
<base href="/">
<title>Angular 2 Tour of Heroes</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="styles.css">
<link rel="stylesheet" href="sample.css">
<script defer src="main.dart" type="application/dart"></script>
<script defer src="packages/browser/dart.js"></script>
</head>
<body>
<my-app>Loading...</my-app>
</body>
</html>

View File

@ -0,0 +1,29 @@
// #docplaster
// #docregion final
// #docregion v1
import 'package:angular2/core.dart';
import 'package:angular2/platform/browser.dart';
import 'package:angular2_tour_of_heroes/app_component.dart';
// #enddocregion v1
import 'package:http/http.dart';
import 'package:angular2_tour_of_heroes/in_memory_data_service.dart';
void main() {
bootstrap(AppComponent,
const [const Provider(Client, useClass: InMemoryDataService)]);
}
// #enddocregion final
/*
// #docregion v1
import 'package:http/browser_client.dart';
void main() {
bootstrap(AppComponent, [
provide(BrowserClient, useFactory: () => new BrowserClient(), deps: [])
]);
// Simplify bootstrap provider list to [BrowserClient]
// once there is a fix for:
// https://github.com/angular/angular/issues/9673
}
// #enddocregion v1
*/

View File

@ -0,0 +1,7 @@
/* #docregion */
.error {color:red;}
button.delete-button {
float:right;
background-color: gray !important;
color:white;
}

View File

@ -24,6 +24,6 @@ nav a:hover {
color: #039be5;
background-color: #CFD8DC;
}
nav a.router-link-active {
nav a.active {
color: #039be5;
}

View File

@ -1,11 +1,8 @@
// #docplaster
// #docregion
import { Component } from '@angular/core';
import { RouteConfig, ROUTER_DIRECTIVES, ROUTER_PROVIDERS } from '@angular/router-deprecated';
import { ROUTER_DIRECTIVES } from '@angular/router';
import { DashboardComponent } from './dashboard.component';
import { HeroesComponent } from './heroes.component';
import { HeroDetailComponent } from './hero-detail.component';
import { HeroService } from './hero.service';
@Component({
@ -14,23 +11,17 @@ import { HeroService } from './hero.service';
template: `
<h1>{{title}}</h1>
<nav>
<a [routerLink]="['Dashboard']">Dashboard</a>
<a [routerLink]="['Heroes']">Heroes</a>
<a [routerLink]="['/dashboard']" routerLinkActive="active">Dashboard</a>
<a [routerLink]="['/heroes']" routerLinkActive="active">Heroes</a>
</nav>
<router-outlet></router-outlet>
`,
styleUrls: ['app/app.component.css'],
directives: [ROUTER_DIRECTIVES],
providers: [
ROUTER_PROVIDERS,
HeroService,
]
})
@RouteConfig([
{ path: '/dashboard', name: 'Dashboard', component: DashboardComponent, useAsDefault: true },
{ path: '/detail/:id', name: 'HeroDetail', component: HeroDetailComponent },
{ path: '/heroes', name: 'Heroes', component: HeroesComponent }
])
export class AppComponent {
title = 'Tour of Heroes';
}

View File

@ -0,0 +1,30 @@
// #docregion
import { provideRouter, RouterConfig } from '@angular/router';
import { DashboardComponent } from './dashboard.component';
import { HeroesComponent } from './heroes.component';
import { HeroDetailComponent } from './hero-detail.component';
export const routes: RouterConfig = [
{
path: '',
redirectTo: '/dashboard',
terminal: true
},
{
path: 'dashboard',
component: DashboardComponent
},
{
path: 'detail/:id',
component: HeroDetailComponent
},
{
path: 'heroes',
component: HeroesComponent
}
];
export const APP_ROUTER_PROVIDERS = [
provideRouter(routes)
];

View File

@ -1,7 +1,7 @@
// #docplaster
// #docregion
import { Component, OnInit } from '@angular/core';
import { Router } from '@angular/router-deprecated';
import { Router } from '@angular/router';
import { Hero } from './hero';
import { HeroService } from './hero.service';
@ -26,7 +26,7 @@ export class DashboardComponent implements OnInit {
}
gotoDetail(hero: Hero) {
let link = ['HeroDetail', { id: hero.id }];
let link = ['/detail', hero.id];
this.router.navigate(link);
}
}

View File

@ -1,9 +1,9 @@
// #docplaster
// #docregion, variables-imports
import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
import { Component, EventEmitter, Input, OnInit, OnDestroy, Output } from '@angular/core';
// #enddocregion variables-imports
import { RouteParams } from '@angular/router-deprecated';
import { ActivatedRoute } from '@angular/router';
import { Hero } from './hero';
import { HeroService } from './hero.service';
@ -14,22 +14,24 @@ import { HeroService } from './hero.service';
styleUrls: ['app/hero-detail.component.css']
})
// #docregion variables-imports
export class HeroDetailComponent implements OnInit {
export class HeroDetailComponent implements OnInit, OnDestroy {
@Input() hero: Hero;
@Output() close = new EventEmitter();
error: any;
sub: any;
navigated = false; // true if navigated here
// #enddocregion variables-imports
constructor(
private heroService: HeroService,
private routeParams: RouteParams) {
private route: ActivatedRoute) {
}
// #docregion ngOnInit
ngOnInit() {
if (this.routeParams.get('id') !== null) {
let id = +this.routeParams.get('id');
this.sub = this.route.params.subscribe(params => {
if (params['id'] !== undefined) {
let id = +params['id'];
this.navigated = true;
this.heroService.getHero(id)
.then(hero => this.hero = hero);
@ -37,8 +39,14 @@ export class HeroDetailComponent implements OnInit {
this.navigated = false;
this.hero = new Hero();
}
});
}
// #enddocregion ngOnInit
ngOnDestroy() {
this.sub.unsubscribe();
}
// #docregion save
save() {
this.heroService
@ -57,4 +65,3 @@ export class HeroDetailComponent implements OnInit {
}
// #enddocregion goBack
}

View File

@ -1,6 +1,6 @@
// #docregion
import { Component, OnInit } from '@angular/core';
import { Router } from '@angular/router-deprecated';
import { Router } from '@angular/router';
import { Hero } from './hero';
import { HeroService } from './hero.service';
@ -68,6 +68,6 @@ export class HeroesComponent implements OnInit {
}
gotoDetail() {
this.router.navigate(['HeroDetail', { id: this.selectedHero.id }]);
this.router.navigate(['/detail', this.selectedHero.id]);
}
}

View File

@ -12,15 +12,20 @@ import { bootstrap } from '@angular/platform-browser-dynamic';
import { HTTP_PROVIDERS } from '@angular/http';
import { AppComponent } from './app.component';
import { APP_ROUTER_PROVIDERS } from './app.routes';
// #enddocregion v1, final
/*
// #docregion v1
bootstrap(AppComponent, [ HTTP_PROVIDERS ]);
bootstrap(AppComponent, [
APP_ROUTER_PROVIDERS,
HTTP_PROVIDERS
]);
// #enddocregion v1
*/
// #docregion final
bootstrap(AppComponent, [
APP_ROUTER_PROVIDERS,
HTTP_PROVIDERS,
{ provide: XHRBackend, useClass: InMemoryBackendService }, // in-mem server
{ provide: SEED_DATA, useClass: InMemoryDataService } // in-mem server data

View File

@ -2,7 +2,7 @@
import 'package:angular2/core.dart';
import 'click_me_component.dart';
import 'click_me_component_2.dart';
import 'click_me2_component.dart';
import 'keyup_components.dart';
import 'little_tour_component.dart';
import 'loop_back_component.dart';
@ -12,7 +12,7 @@ import 'loop_back_component.dart';
templateUrl: 'app_component.html',
directives: const [
ClickMeComponent,
ClickMeComponent2,
ClickMe2Component,
KeyUpComponentV1,
KeyUpComponentV2,
KeyUpComponentV3,

View File

@ -0,0 +1,18 @@
// #docregion
import 'package:angular2/core.dart';
@Component(
selector: 'click-me2',
template: '''
<button (click)="onClickMe2(\$event)">No! .. Click me!</button>
{{clickMessage}}''')
class ClickMe2Component {
String clickMessage = '';
int _clicks = 1;
void onClickMe2(dynamic event) {
var evtMsg =
event != null ? ' Event target is ' + event.target.tagName : '';
clickMessage = ('Click #${_clicks++}. ${evtMsg}');
}
}

View File

@ -1,3 +1,9 @@
/* FOR DOCS ... MUST MATCH ClickMeComponent template
// #docregion click-me-button
<button (click)="onClickMe()">Click me!</button>
// #enddocregion click-me-button
*/
// #docregion
import 'package:angular2/core.dart';
@ -5,15 +11,12 @@ import 'package:angular2/core.dart';
@Component(
selector: 'click-me',
template: '''
// #docregion click-me-button
<button (click)="onClickMe()">Click me!</button>
// #enddocregion click-me-button
{{clickMessage}}''')
class ClickMeComponent {
String clickMessage = '';
onClickMe() {
void onClickMe() {
clickMessage = 'You are my hero!';
}
}
// #enddocregion click-me-component

View File

@ -1,17 +0,0 @@
// #docregion
import 'package:angular2/core.dart';
@Component(
selector: 'click-me2',
template: '''<button (click)="onClickMe2(\$event)">No! .. Click me!</button>
{{clickMessage}}''')
class ClickMeComponent2 {
String clickMessage = '';
int clicks = 1;
onClickMe2(dynamic event) {
var evtMsg =
event != null ? ' Event target is ' + event.target.tagName : '';
clickMessage = ('Click #${clicks++}. ${evtMsg}');
}
}

View File

@ -17,7 +17,7 @@
"@angular/http": "2.0.0-rc.3",
"@angular/platform-browser": "2.0.0-rc.3",
"@angular/platform-browser-dynamic": "2.0.0-rc.3",
"@angular/router-deprecated": "2.0.0-rc.2",
"@angular/router": "3.0.0-alpha.8",
"core-js": "^2.4.0",
"reflect-metadata": "0.1.2",
"rxjs": "5.0.0-beta.6",

View File

@ -5,7 +5,7 @@ import '@angular/platform-browser-dynamic';
import '@angular/core';
import '@angular/common';
import '@angular/http';
import '@angular/router-deprecated';
import '@angular/router';
// RxJS
import 'rxjs';

View File

@ -73,6 +73,12 @@
"intro": "Learn how to apply CSS styles to components."
},
"glossary": {
"title": "Glossary",
"intro": "Brief definitions of the most important words in the Angular 2 vocabulary",
"basics": true
},
"security": {
"title": "Security",
"intro": "Prevent security vulnerabilities"

View File

@ -1 +1,141 @@
!= partial("../../../_includes/_ts-temp")
extends ../../../ts/latest/tutorial/toh-pt6.jade
block includes
include ../_util-fns
- var _Http = 'BrowserClient';
- var _Angular_Http = 'Dart <code>BrowserClient</code>'
- var _httpUrl = 'https://pub.dartlang.org/packages/http'
- var _Angular_http_library = 'Dart <a href="' + _httpUrl + '"><b>http</b></a> package'
- var _HTTP_PROVIDERS = 'BrowserClient'
- var _JSON_stringify = 'JSON.encode'
block start-server-and-watch
:marked
### Keep the app compiling and running
Open a terminal/console window.
Start the Dart compiler, watch for changes, and start our server by entering the command:
code-example(language="bash").
pub serve
block http-library
:marked
We'll be using the !{_Angular_http_library}'s
`BrowserClient` class to communicate with a server.
### Pubspec updates
We need to add a package dependency for the !{_Angular_http_library}.
We also need to add a `resolved_identifiers` entry, to inform the [angular2
transformer][ng2x] that we'll be using `BrowserClient`. (For an explanation of why
this extra configuration is needed, see the [HTTP client chapter][guide-http].) We'll
also need to use `Client` from http, so let's add that now as well.
Update `pubspec.yaml` to look like this (additions are highlighted):
[guide-http]: ../guide/server-communication.html#!#http-providers
[ng2x]: https://github.com/angular/angular/wiki/Angular-2-Dart-Transformer
- var stylePattern = { pnk: /(http.*|resolved_identifiers:|Browser.*|Client.*)/gm };
+makeExcerpt('pubspec.yaml', 'additions', null, stylePattern)
block http-providers
:marked
Before our app can use `#{_Http}`, we have to register it as a service provider.
block backend
:marked
We want to replace `BrowserClient`, the service that talks to the remote server,
with the in-memory web API service.
Our in-memory web API service, shown below, is implemented using the
`http` library `MockClient` class.
All `http` client implementations share a common `Client` interface, so
we'll have our app use the `Client` type so that we can freely switch between
implementations.
block dont-be-distracted-by-backend-subst
//- N/A
block get-heroes-details
:marked
To get the list of heroes, we first make an asynchronous call to
`http.get()`. Then we use the `_extractData` helper method to decode the
response payload (`body`).
block hero-detail-comp-extra-imports-and-vars
//- N/A
block hero-detail-comp-updates
:marked
### Edit in the *HeroDetailComponent*
We already have `HeroDetailComponent` for viewing details about a specific hero.
Supporting edit functionality is a natural extension of the detail view,
so we are able to reuse `HeroDetailComponent` with a few tweaks.
block hero-detail-comp-save-and-goback
//- N/A
block add-new-hero-via-detail-comp
//- N/A
block heroes-comp-directives
//- N/A
block heroes-comp-add
//- N/A
block review
//- Not showing animated gif due to differences between TS and Dart implementations.
block filetree
.filetree
.file angular2-tour-of-heroes
.children
.file lib
.children
.file app_component.dart
.file app_component.css
.file dashboard_component.css
.file dashboard_component.html
.file dashboard_component.dart
.file hero.dart
.file hero_detail_component.css
.file hero_detail_component.html
.file hero_detail_component.dart
.file hero_service.dart
.file heroes_component.css
.file heroes_component.html
.file heroes_component.dart
.file main.dart
.file in_memory_data_service.dart (new)
.file web
.children
.file main.dart
.file index.html
.file sample.css (new)
.file styles.css
.file pubspec.yaml
block file-summary
+makeTabs(
`toh-6/dart/lib/hero.dart,
toh-6/dart/lib/hero_detail_component.dart,
toh-6/dart/lib/hero_detail_component.html,
toh-6/dart/lib/hero_service.dart,
toh-6/dart/lib/heroes_component.dart,
toh-6/dart/web/index.html,
toh-6/dart/web/main.dart,
toh-6/dart/web/sample.css`,
`,,,,,,final,`,
`lib/hero.dart,
lib/hero_detail_component.dart,
lib/hero_detail_component.html,
lib/hero_service.dart,
lib/heroes_component.dart,
web/index.html,
web/main.dart,
web/sample.css`)
+makeExample('pubspec.yaml')

View File

@ -222,10 +222,11 @@ table(width="100%")
Most Angular 2 classes have one or more TypeScript *decorators*
attached to provide configuration and metadata. For example,
a component must have a [`@Component`](../api/core/Component-decorator.html) decorator.
a component must have a [`@Component`](../api/core/index/Component-decorator.html) decorator.
大部分Angular 2中的类都会附加一个或多个TypeScript*装饰器*,用来提供配置和元数据。比如组件必须要有一个[`@Component`](../api/core/index/Component-decorator.html)装饰器。
+makeExample('cb-ts-to-js/ts/app/hero.component.ts', 'metadata')(format="." )
td
@ -242,7 +243,7 @@ table(width="100%")
数组里的每一个条目都对应一个TypeScript装饰器。
In the following example, we create a new instance of `Component` that corresponds
to the [`@Component`](../api/core/Component-decorator.html) TypeScript decorator.
to the [`@Component`](../api/core/index/Component-decorator.html) TypeScript decorator.
在下面的例子中,我们新建了一个`Component`的新实例,与[`@Component`](../api/core/index/Component-decorator.html)TypeScript装饰器相对应。
@ -356,8 +357,8 @@ table(width="100%")
在TypeScript里属性装饰器经常被用来为组件和指令提供额外的元数据。
For [inputs and outputs](../guide/template-syntax.html#inputs-outputs),
we use [`@Input`](../api/core/Input-var.html)
and [`@Output`](../api/core/Output-var.html) property decorators.
we use [`@Input`](../api/core/index/Input-var.html)
and [`@Output`](../api/core/index/Output-var.html) property decorators.
They may optionally specify input and output binding names if we want them to be
different from the class property names.
@ -497,10 +498,10 @@ table(width="100%")
We can attach additional decorators to constructor parameters
to qualify the injection behavior. We can mark
optional dependencies with the [`@Optional`](../api/core/Optional-var.html),
inject host element attributes with [`@Attribute`](../api/core/Attribute-var.html),
inject content child queries with [`@Query`](../api/core/Query-var.html)
and inject view child queries with [`@ViewQuery`](../api/core/ViewQuery-var.html).
optional dependencies with the [`@Optional`](../api/core/index/Optional-var.html),
inject host element attributes with [`@Attribute`](../api/core/index/Attribute-var.html),
inject content child queries with [`@Query`](../api/core/index/Query-var.html)
and inject view child queries with [`@ViewQuery`](../api/core/index/ViewQuery-var.html).
我们可以往构造函数中附加额外的装饰器来调整注入行为。比如使用[`@Optional`](../api/core/index/Optional-var.html)来标记依赖是可选的,
用[`@Attribute`](../api/core/index/Attribute-var.html)来注入宿主元素的属性(Attribute)
@ -533,8 +534,8 @@ table(width="100%")
:marked
We can apply other additional parameter decorators such as
[`@Host`](../api/core/Host-var.html) and
[`@SkipSelf`](../api/core/SkipSelf-var.html) in the same way -
[`@Host`](../api/core/index/Host-var.html) and
[`@SkipSelf`](../api/core/index/SkipSelf-var.html) in the same way -
by adding `new ng.core.Host()` or `ng.core.SkipSelf()` in the
parameters array.
@ -565,9 +566,9 @@ table(width="100%")
### `Host`(宿主)装饰器
We can use host property decorators to bind a host element to a component or directive.
The [`@HostBinding`](../api/core/HostBinding-var.html) decorator
The [`@HostBinding`](../api/core/index/HostBinding-var.html) decorator
binds host element properties to component data properties.
The [`@HostListener`](../api/core/HostListener-var.html) decorator binds
The [`@HostListener`](../api/core/index/HostListener-var.html) decorator bimds
host element events to component event handlers.
我们可以使用宿主属性装饰器来把宿主元素绑定到组件或指令。
@ -620,8 +621,8 @@ table(width="100%")
有好几个属性装饰器可以用来查询组件或指令的各级子节点。
The [`@ViewChild`](../api/core/ViewChild-var.html) and
[`@ViewChildren`](../api/core/ViewChildren-var.html) property decorators
The [`@ViewChild`](../api/core/index/ViewChild-var.html) and
[`@ViewChildren`](../api/core/index/ViewChildren-var.html) property decorators
allow a component to query instances of other components that are used in
its view.
@ -633,8 +634,8 @@ table(width="100%")
+makeExample('cb-ts-to-js/ts/app/heroes-queries.component.ts', 'view')(format="." )
:marked
The [`@ContentChild`](../api/core/ContentChild-var.html) and
[`@ContentChildren`](../api/core/ContentChildren-var.html) property decorators
The [`@ContentChild`](../api/core/index/ContentChild-var.html) and
[`@ContentChildren`](../api/core/index/ContentChildren-var.html) property decorators
allow a component to query instances of other components that have been projected
into its view from elsewhere.

View File

@ -73,6 +73,12 @@
"intro": "Learn how to apply CSS styles to components."
},
"glossary": {
"title": "Glossary",
"intro": "Brief definitions of the most important words in the Angular 2 vocabulary",
"basics": true
},
"hierarchical-dependency-injection": {
"title": "Hierarchical Dependency Injectors",
"navTitle": "Hierarchical Injectors",

View File

@ -722,10 +722,10 @@ table(width="100%")
+makeExample('cb-a1-a2-quick-reference/ts/app/movie-list.component.html', 'ngSwitch')(format="." )
:marked
In Angular&nbsp;2, the `ngSwitch` directive works similarly.
It displays an element whose `*ngSwitchWhen` matches the current `ngSwitch` expression value.
It displays an element whose `*ngSwitchCase` matches the current `ngSwitch` expression value.
在Angular 2中`ngSwitch`指令的工作方式与此类似。
它会显示那个与`ngSwitch`表达式的当前值匹配的那个`*ngSwitchWhen`所在的元素。
它会显示那个与`ngSwitch`表达式的当前值匹配的那个`*ngSwitchCase`所在的元素。
In this example, if `favoriteHero` is not set, the `ngSwitch` value is `null`
and we see the `*ngSwitchDefault` paragraph, "Please enter ...".
@ -739,9 +739,9 @@ table(width="100%")
如果该方法返回`true`我们就会看到“Excellent choice!”。
如果该方法返回`false`我们就会看到“No movie, sorry!”。
The (*) before `ngSwitchWhen` and `ngSwitchDefault` is required in this example.
The (*) before `ngSwitchCase` and `ngSwitchDefault` is required in this example.
在这个例子中,`ngSwitchWhen`和`ngSwitchDefault`前面的星号(*)是必须的。
在这个例子中,`ngSwitchCase`和`ngSwitchDefault`前面的星号(*)是必须的。
For more information on the ngSwitch directive see [Template Syntax](../guide/template-syntax.html#ngSwitch).

View File

@ -86,6 +86,12 @@
"intro": "学习如何给组件应用CSS样式。"
},
"glossary": {
"title": "Glossary",
"intro": "Brief definitions of the most important words in the Angular 2 vocabulary",
"basics": true
},
"hierarchical-dependency-injection": {
"title": "多级依赖注入器",
"navTitle": "多级注入器",

View File

@ -107,7 +107,7 @@ figure
:marked
With these we can now define an *animation trigger* called `heroState` in the component
metadata. It has animated transitions between two states: `active` and `inactive`. When a
hero is active, we display a the element in slightly larger size and lighter color.
hero is active, we display the element in a slightly larger size and lighter color.
通过这些,可以在组件元数据中定义一个名叫`heroState`的*动画触发器*。它在两个状态`active`和`inactive`之间进行转场。
当英雄处于激活状态时,它会把该元素显示得稍微大一点、亮一点。

View File

@ -727,10 +727,10 @@ figure
+makeExample('architecture/ts/app/logger.service.ts', 'class', 'app/logger.service.ts (只有类)')(format=".")
:marked
Here's a `HeroService` that fetches heroes and returns them in a resolved [promise](http://exploringjs.com/es6/ch_promises.html).
The `HeroService` depends on the `LoggerService` and another `BackendService` that handles the server communication grunt work.
The `HeroService` depends on the `Logger` service and another `BackendService` that handles the server communication grunt work.
下面是`HeroService`类,用于获取英雄数据,并通过一个已解析的[承诺Promise](http://exploringjs.com/es6/ch_promises.html)返回它们。
`HeroService`还依赖于`LoggerService`和另一个用来处理服务器通讯工作的`BackendService`。
`HeroService`还依赖于`Logger`服务和另一个用来处理服务器通讯工作的`BackendService`服务
+makeExample('architecture/ts/app/hero.service.ts', 'class', 'app/hero.service.ts (只有类)')(format=".")
:marked

View File

@ -108,7 +108,8 @@ include ../_quickstart_repo
Create the following source file in the indicated folder with the given code:
在指定的文件夹下创建下列源码文件:
+makeExample('attribute-directives/ts/app/highlight.directive.1.ts', null, 'app/highlight.directive.ts')
+makeExample('app/highlight.directive.1.ts')
block highlight-directive-1
:marked
@ -165,7 +166,7 @@ block highlight-directive-1
我们需要一个自己的前缀,最好短点儿,目前用的这个`my`前缀就不错。
p
| After the `@Directive` metadata comes the directive's controller class, which contains the logic for the directive.
| After the #[code @Directive] metadata comes the directive's controller class, which contains the logic for the directive.
+ifDocsFor('ts')
| We export `HighlightDirective` to make it accessible to other components.
p
@ -270,6 +271,7 @@ figure.image-display
a#respond-to-user
:marked
## Respond to user action
## 响应用户的操作
We are not satisfied to simply set an element color.
@ -283,20 +285,23 @@ a#respond-to-user
We'll need to
我们需要:
1. detect when the user hovers into and out of the element,
1. 检测用户的鼠标啥时候进入和离开这个元素。
2. respond to those actions by setting and clearing the highlight color, respectively.
2. 通过设置和清除高亮色来响应这些操作。
We use the `@HostListener` decorator on a method which is called when the event is raised.
We apply the `@HostListener` !{_decorator} to methods which are called when an event is raised.
从事件检测开始吧。
把`host`属性加入指令的元数据中,并给它一个配置对象,用来指定两个鼠标事件,并在它们被触发时,调用指令中的方法:
+makeExample('attribute-directives/ts/app/highlight.directive.2.ts','host')(format=".")
.l-sub-section
:marked
The `@HostListener` decorator refers to the DOM element that hosts our attribute directive, the `<p>` in our case.
The `@HostListener` !{_decorator} refers to the DOM element that hosts our attribute directive, the `<p>` in our case.
`@HostListener`装饰器引用的是我们这个属性型指令的宿主元素,在这个例子中就是`<p>`。
@ -312,14 +317,17 @@ a#respond-to-user
1. We'd be talking to DOM API directly which, we learned, is something to avoid.
1. 必须直接和DOM API打交道但正如我们学过的那样应该避免这样做。
Let's roll with the `@HostListener` decorator.
Let's roll with the `@HostListener` !{_decorator}.
我们还是围绕`@HostListener`装饰器来吧。
:marked
Now we implement the two mouse event handlers:
现在,我们实现那两个鼠标事件处理器:
+makeExample('attribute-directives/ts/app/highlight.directive.2.ts','mouse-methods')(format=".")
:marked
Notice that they delegate to a helper method that sets the color via a private local variable, `#{_priv}el`.
We revise the constructor to capture the `ElementRef.nativeElement` in this variable.
@ -328,11 +336,14 @@ a#respond-to-user
我们要修改构造函数,来把`ElementRef.nativeElement`存进这个私有变量。
+makeExample('attribute-directives/ts/app/highlight.directive.2.ts','ctor')(format=".")
:marked
Here's the updated directive:
这里是更新过的指令:
+makeExample('attribute-directives/ts/app/highlight.directive.2.ts',null, 'app/highlight.directive.ts')
+makeExample('app/highlight.directive.2.ts')
:marked
We run the app and confirm that the background color appears as we move the mouse over the `p` and
disappears as we move out.
@ -361,7 +372,8 @@ a#bindings
这里是该类的最终版:
+makeExample('attribute-directives/ts/app/highlight.directive.ts', 'class-1', 'app/highlight.directive.ts (class only)')
+makeExcerpt('app/highlight.directive.ts', 'class')
a#input
:marked
The new `highlightColor` property is called an *input* property because data flows from the binding expression into our directive.
@ -369,7 +381,9 @@ a#input
新的`highlightColor`属性被称为“输入”属性,这是因为数据流是从绑定表达式到这个指令的。
注意,在定义这个属性的时候,我们调用了`@Input()`#{_decoratorCn}。
+makeExample('attribute-directives/ts/app/highlight.directive.ts', 'color')
+makeExcerpt('app/highlight.directive.ts', 'color')
:marked
`@Input` adds metadata to the class that makes the `highlightColor` property available for
property binding under the `myHighlight` alias.
@ -393,7 +407,7 @@ a#input
我们可以通过把属性名改为`myHighlight`来解决这个矛盾,就像这样:
+makeExample('attribute-directives/ts/app/highlight.directive.ts', 'highlight')
+makeExcerpt('app/highlight.directive.ts', 'highlight', '')
:marked
Maybe we don't want that property name inside the directive perhaps because it
doesn't express our intention well.
@ -402,7 +416,9 @@ a#input
但我们可能在指令中不想要那样一个属性名,因为它不能很好的表示我们的意图。
可以通过把`myHighlight`传给`@Input`#{_decoratorCn}来把这个属性名作为`highlightColor`属性的别名。
+makeExample('attribute-directives/ts/app/highlight.directive.ts', 'color')
+makeExcerpt('app/highlight.directive.ts', 'color', '')
:marked
Now that we're getting the highlight color as an input, we modify the `onMouseEnter()` method to use
it instead of the hard-coded color name.
@ -411,7 +427,9 @@ a#input
现在,通过输入型属性得到了高亮的颜色,然后修改`onMouseEnter()`来使用它代替硬编码的那个颜色名。
我们还把红色定义为默认颜色,以便在用户忘了绑定颜色时作为备用。
+makeExample('attribute-directives/ts/app/highlight.directive.ts', 'mouse-enter')
+makeExcerpt('attribute-directives/ts/app/highlight.directive.ts', 'mouse-enter', '')
:marked
Now we'll update our `AppComponent` template to let
users pick the highlight color and bind their choice to our directive.
@ -422,7 +440,7 @@ a#input
这里是更新后的模板:
+makeExample('attribute-directives/ts/app/app.component.html', 'v2')
+makeExcerpt('attribute-directives/ts/app/app.component.html', 'v2', '')
.l-sub-section
:marked

View File

@ -1172,7 +1172,7 @@ block what-should-we-use-as-token
// end Typescript only
//- FIXME simplify once APIs are defined for Dart.
- var opaquetoken = _docsFor == 'dart' ? '<b>OpaqueToken</b>' : '<a href="../api/core/OpaqueToken-class.html"><b>OpaqueToken</b></a>'
- var opaquetoken = _docsFor == 'dart' ? '<b>OpaqueToken</b>' : '<a href="../api/core/index/OpaqueToken-class.html"><b>OpaqueToken</b></a>'
:marked
### OpaqueToken

View File

@ -2,11 +2,13 @@ include ../_util-fns
.alert.is-important
:marked
This guide is using the new forms API.
This guide is using the new forms API. To use this API, you must opt in by adding special
providers to your bootstrap file (see the Bootstrap seection below).
这份指南使用新的表单API。
The old forms API is deprecated, but we still maintain a separate version of the guide using the deprecated forms API <a href='/docs/ts/latest/guide/forms-deprecated.html'>here</a>.
The old forms API is deprecated, but we still maintain a separate version of the guide using
the deprecated forms API <a href='/docs/ts/latest/guide/forms-deprecated.html'>here</a>.
旧的表单API已经废弃了但是在本指南中仍然维护着一个独立的版本它使用已废弃的表单API参见<a href='/docs/ts/latest/guide/forms-deprecated.html'>这里</a>。
@ -883,7 +885,7 @@ figure.image-display
.l-sub-section
:marked
Why "ngModel"?
A directive's [exportAs](../api/core/DirectiveMetadata-class.html#!#exportAs) property
A directive's [exportAs](../api/core/index/DirectiveMetadata-class.html#!#exportAs-anchor) property
tells Angular how to link the reference variable to the directive.
We set `name` to `ngModel` because the `ngModel` directive's `exportAs` property happens to be "ngModel".

View File

@ -657,7 +657,7 @@ figure.image-display
+makeExample('lifecycle-hooks/ts/app/on-changes.component.ts', 'ng-on-changes', 'OnChangesComponent (ngOnChanges)')(format=".")
:marked
The `ngOnChanges` method takes an object that maps each changed property name to a
[SimpleChange](../api/core/SimpleChange-class.html) object with the current and previous property values.
[SimpleChange](../api/core/index/SimpleChange-class.html) object with the current and previous property values.
We iterate over the changed properties and log them.
`ngOnChanges`方法获取了一个对象,它把每个发生变化的属性名都映射到了一个[SimpleChange](../api/core/index/SimpleChange-class.html)对象,
@ -754,7 +754,7 @@ figure.image-display
.l-sub-section
:marked
We also see that the `ngOnChanges` method is called in contradiction of the
[incorrect API documentation](../api/core/DoCheck-interface.html).
[incorrect API documentation](../api/core/index/DoCheck-class.html).
我们还看到,`ngOnChanges`方法的调用方式与[API文档](../api/core/index/DoCheck-interface.html)中是不一样的这是因为API文档过时了。
(译注这是经过与官方开发组沟通得到的消息由于代码快速迭代因此API文档现在的更新不够及时将来会进行一次系统的梳理和更正)
@ -778,7 +778,7 @@ figure.image-display
:marked
The following hooks take action based on changing values *within the child view*
which we can only reach by querying for the child view via the property decorated with
[@ViewChild](../api/core/ViewChild-var.html).
[@ViewChild](../api/core/index/ViewChild-var.html).
下列钩子基于*子视图中*的每一次数据变更采取行动,我们只能通过带[@ViewChild](../api/core/index/ViewChild-var.html)装饰器的属性来访问子视图。
@ -907,7 +907,7 @@ figure.image-display
The following *AfterContent* hooks take action based on changing values in a *content child*
which we can only reach by querying for it via the property decorated with
[@ContentChild](../api/core/ContentChild-var.html).
[@ContentChild](../api/core/index/ContentChild-var.html).
下列*AfterContent*钩子基于*子级内容*中值的变化而采取相应的行动,这里我们只能通过带有[@ContentChild](../api/core/index/ContentChild-var.html)装饰器的属性来查询到“子级内容”。

View File

@ -402,7 +402,7 @@ figure.image-display
More often we don't know when the data have changed,
especially in applications that mutate data in many ways,
perhaps in application locations far away.
A component is such an application usually can't know about those changes.
A component in such an application usually can't know about those changes.
Moreover, it's unwise to distort our component design to accommodate a pipe.
We strive as much as possible to keep the component class independent of the HTML.
The component should be unaware of pipes.

View File

@ -892,7 +892,7 @@ code-example(format="").
## Router Lifecycle Hooks
Angular components have [lifecycle hooks](lifecycle-hooks.html). For example, Angular calls the hook methods of the
[OnInit](../api/core/OnInit-interface.html) and [OnDestroy](../api/core/OnDestroy-interface.html)
[OnInit](../api/core/index/OnInit-class.html) and [OnDestroy](../api/core/index/OnDestroy-class.html)
interfaces when it creates and destroys components.
The router also has hooks for *its* lifecycle such as
@ -1369,8 +1369,8 @@ code-example(format="." language="bash").
How do we ensure that happens if not in the constructor?
Angular detects when a component has certain lifecycle methods like
[ngOnInit](../api/core/OnInit-interface.html) and
[ngOnDestroy](../api/core/OnDestroy-interface.html) and calls
[ngOnInit](../api/core/index/OnInit-class.html) and
[ngOnDestroy](../api/core/index/OnDestroy-class.html) and calls
them
at the appropriate moment.

View File

@ -413,9 +413,9 @@ table
p <code><i>路由组件</i></code>
td
p An Angular component with a *RouterOutlet* that displays views based on router navigations.
p An Angular component with a <code>RouterOutlet</code> that displays views based on router navigations.
p 一个带有*RouterOutlet*的Angular组件它根据路由器的导航来显示相应的视图。
p 一个带有<code>RouterOutlet</code>的Angular组件它根据路由器的导航来显示相应的视图。
:marked
We've barely touched the surface of the router and its capabilities.
@ -1996,7 +1996,7 @@ h2#guards 路由守卫
守卫可能会向用户问一个问题、把更改保存到服务器,或者获取新数据,而这些都是异步操作。
Accordingly, a routing guard can return an `Observable<boolean>` and the
router will wait for the observable to resolve to `true` or `false.
router will wait for the observable to resolve to `true` or `false`.
因此,路由的守卫可以返回一个`Observable<boolean>`,并且路由器会等待这个可观察对象被解析为`true`或`false`。
@ -2907,8 +2907,8 @@ code-example(format="." language="bash").
然而我们还是需要该类的实例在创建完之后尽快从`HeroService`中获取英雄数据。如果不能放在构造函数中又该怎么办?
Angular detects when a component has certain lifecycle methods like
[ngOnInit](../api/core/OnInit-interface.html) and
[ngOnDestroy](../api/core/OnDestroy-interface.html) and calls
[ngOnInit](../api/core/index/OnInit-class.html) and
[ngOnDestroy](../api/core/index/OnDestroy-class.html) and calls
them
at the appropriate moment.
@ -3079,7 +3079,7 @@ code-example(format=".", language="bash").
.l-sub-section
:marked
Learn about the [APP_BASE_HREF](../api/router/APP_BASE_HREF-let.html)
Learn about the [APP_BASE_HREF](../api/common/index/APP_BASE_HREF-let.html)
in the API Guide.
你可以到API指南中学习关于[APP_BASE_HREF](../api/router/APP_BASE_HREF-let.html)的更多知识。

View File

@ -150,6 +150,7 @@ block system-config-of-http
Before we can use the `#{_Http}` client , we'll have to register it as a service provider with the Dependency Injection system.
要想使用`#{_Http}`客户端,我们得先通过依赖注入系统把它注册成一个服务供应商。
.l-sub-section
:marked
Learn about providers in the [Dependency Injection](dependency-injection.html) chapter.

View File

@ -2028,7 +2028,7 @@ a(href="#toc") 回到顶部
.s-rule.do
:marked
**Do** use [`@Input`](https://angular.io/docs/ts/latest/api/core/Input-var.html) and [`@Output`](https://angular.io/docs/ts/latest/api/core/Output-var.html) instead of the `inputs` and `outputs` properties of the [`@Directive`](https://angular.io/docs/ts/latest/api/core/Directive-decorator.html) and [`@Component`](https://angular.io/docs/ts/latest/api/core/Component-decorator.html) decorators:
**Do** use [`@Input`](https://angular.io/docs/ts/latest/api/core/index/Input-var.html) and [`@Output`](https://angular.io/docs/ts/latest/api/core/index/Output-var.html) instead of the `inputs` and `outputs` properties of the [`@Directive`](https://angular.io/docs/ts/latest/api/core/index/Directive-decorator.html) and [`@Component`](https://angular.io/docs/ts/latest/api/core/index/Component-decorator.html) decorators:
**坚持**使用[`@Input`](https://angular.io/docs/ts/latest/api/core/Input-var.html)和[`@Output`](https://angular.io/docs/ts/latest/api/core/Output-var.html), 而非[`@Directive`](https://angular.io/docs/ts/latest/api/core/Directive-decorator.html) 和 [`@Component`](https://angular.io/docs/ts/latest/api/core/Component-decorator.html) 装饰器里面的`inputs`和`outputs`属性。
@ -2046,7 +2046,7 @@ a(href="#toc") 回到顶部
.s-why
:marked
**Why?** If we ever need to rename the property or event name associated to [`@Input`](https://angular.io/docs/ts/latest/api/core/Input-var.html) or [`@Output`](https://angular.io/docs/ts/latest/api/core/Output-var.html) we can modify it on a single place.
**Why?** If we ever need to rename the property or event name associated to [`@Input`](https://angular.io/docs/ts/latest/api/core/index/Input-var.html) or [`@Output`](https://angular.io/docs/ts/latest/api/core/index/Output-var.html) we can modify it on a single place.
**为何?**如果我们需要重命名[`@Input`](https://angular.io/docs/ts/latest/api/core/Input-var.html) 或 [`@Output`](https://angular.io/docs/ts/latest/api/core/Output-var.html)关的属性或者事件,我们可以在一个地方修改。

View File

@ -836,8 +836,8 @@ table
If we must read a target element property or call one of its methods,
we'll need a different technique.
See the API reference for
[viewChild](../api/core/ViewChild-var.html) and
[contentChild](../api/core/ContentChild-var.html).
[viewChild](../api/core/index/ViewChild-var.html) and
[contentChild](../api/core/index/ContentChild-var.html).
如果我们不得不读取目标元素上的属性或调用它的某个方法,我们得用另一种技术。
参见API参考手册中的[viewChild](../api/core/index/ViewChild-var.html)和
@ -1310,7 +1310,7 @@ block style-property-name-dart-diff
### Custom events with EventEmitter
### 使用EventEmitter实现自定义事件
Directives typically raise custom events with an Angular [EventEmitter](../api/core/EventEmitter-class.html).
Directives typically raise custom events with an Angular [EventEmitter](../api/core/index/EventEmitter-class.html).
A directive creates an `EventEmitter` and exposes it as a property.
The directive calls `EventEmitter.emit(payload)` to fire an event, passing in a message payload that can be anything.
Parent directives listen for the event by binding to this property and accessing the payload through the `$event` object.
@ -1456,7 +1456,7 @@ block style-property-name-dart-diff
The `ngModel` input property sets the element's value property and the `ngModelChange` output property
listens for changes to the element's value.
The details are specific to each kind of element and therefore the `NgModel` directive only works for elements,
such as the input text box, that are supported by a [ControlValueAccessor](../api/common/ControlValueAccessor-interface.html).
such as the input text box, that are supported by a [ControlValueAccessor](../api/common/index/ControlValueAccessor-interface.html).
We can't apply `[(ngModel)]` to our custom components until we write a suitable *value accessor*,
a technique that is beyond the scope of this chapter.
@ -1738,8 +1738,8 @@ block dart-no-truthy-falsey
这里有三个相互合作的指令:
1. `ngSwitch`: bound to an expression that returns the switch value
1. `ngSwitch`:绑定到一个返回开关值的表达式
1. `ngSwitchWhen`: bound to an expression returning a match value
1. `ngSwitchWhen`:绑定到一个返回匹配值的表达式
1. `ngSwitchCase`: bound to an expression returning a match value
1. `ngSwitchCase`:绑定到一个返回匹配值的表达式
1. `ngSwitchDefault`: a marker attribute on the default element
1. `ngSwitchDefault`一个用于标记出默认元素的Attribute
@ -1749,10 +1749,10 @@ block dart-no-truthy-falsey
**不要**在`ngSwitch`的前面放星号(`*`),而应该用属性绑定。
**Do** put the asterisk (`*`) in front of `ngSwitchWhen` and `ngSwitchDefault`.
**Do** put the asterisk (`*`) in front of `ngSwitchCase` and `ngSwitchDefault`.
For more information, see [\* and &lt;template>](#star-template).
**要**把星号(`*`)放在`ngSwitchWhen`和`ngSwitchDefault`的前面。
**要**把星号(`*`)放在`ngSwitchCase`和`ngSwitchDefault`的前面。
要了解更多信息,参见[\*与&lt;template>](#star-template)。
<a id="ngFor"></a>
@ -1852,7 +1852,7 @@ block dart-no-truthy-falsey
+makeExample('template-syntax/ts/app/app.component.html', 'NgFor-3')(format=".")
.l-sub-section
:marked
Learn about other special *index-like* values such as `last`, `even`, and `odd` in the [NgFor API reference](../api/common/NgFor-directive.html).
Learn about other special *index-like* values such as `last`, `even`, and `odd` in the [NgFor API reference](../api/common/index/NgFor-directive.html).
要学习更多的*类似index*的值,例如`last`、`even`和`odd`,请参阅[NgFor API 参考](../api/common/index/NgFor-directive.html)。
@ -1983,13 +1983,13 @@ block remember-the-brackets
### Expanding `*ngSwitch`
### 展开`*ngSwitch`
A similar transformation applies to `*ngSwitch`. We can de-sugar the syntax ourselves.
Here's an example, first with `*ngSwitchWhen` and `*ngSwitchDefault` and then again with `<template>` tags:
Here's an example, first with `*ngSwitchCase` and `*ngSwitchDefault` and then again with `<template>` tags:
类似的转换也作用于`*ngSwitch`上。我们可以自己解开这个语法糖。
这里是一个例子,首先是`*ngSwitchWhen`和`*ngSwitchDefault`,然后再解出`<template>`标签:
这里是一个例子,首先是`*ngSwitchCase`和`*ngSwitchDefault`,然后再解出`<template>`标签:
+makeExample('template-syntax/ts/app/app.component.html', 'NgSwitch-expanded')(format=".")
:marked
The `*ngSwitchWhen` and `*ngSwitchDefault` expand in exactly the same manner as `*ngIf`,
The `*ngSwitchCase` and `*ngSwitchDefault` expand in exactly the same manner as `*ngIf`,
wrapping their former elements in `<template>` tags.
`*ngSwitchWhen`和`*ngSwitchDefault`用和`*ngIf`完全相同的方式展开,把它们以前的元素包裹在`<template>`标签中。
@ -2000,13 +2000,14 @@ block remember-the-brackets
现在,我们应该明白为什么`ngSwitch`本身不能用星号(*)前缀的原因了吧?
它没有定义内容,它的工作是控制一组模板。
In this case, it governs two sets of `NgSwitchWhen` and `NgSwitchDefault` directives.
In this case, it governs two sets of `NgSwitchCase` and `NgSwitchDefault` directives.
We should expect it to display the values of the selected template twice,
once for the (*) prefixed version and once for the expanded template version.
That's exactly what we see in this example:
上面这种情况下,它管理两组`NgSwitchWhen`和`NgSwitchDefault`指令,一次是(*)前缀的版本,一次是展开模板后的版本。
上面这种情况下,它管理两组`NgSwitchCase`和`NgSwitchDefault`指令,一次是(*)前缀的版本,一次是展开模板后的版本。
我们也期待它显示所选模板的值两次。这正是我们在这个例子中看到的:
figure.image-display
img(src='/resources/images/devguide/template-syntax/ng-switch-anim.gif' alt="NgSwitch")
:marked

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