Merge remote-tracking branch 'origin/master'

# Conflicts:
#	public/docs/_examples/cb-component-communication/e2e-spec.ts
#	public/docs/_examples/cb-component-communication/ts/app/app.component.ts
#	public/docs/_examples/dependency-injection/ts/app/main.1.ts
#	public/docs/ts/latest/tutorial/toh-pt1.jade
#	public/docs/ts/latest/tutorial/toh-pt2.jade
#	public/docs/ts/latest/tutorial/toh-pt3.jade
#	public/docs/ts/latest/tutorial/toh-pt4.jade
#	public/docs/ts/latest/tutorial/toh-pt5.jade
This commit is contained in:
Zhicheng Wang 2016-06-08 09:58:16 +08:00
commit f2dbdb3163
255 changed files with 794 additions and 767 deletions

View File

@ -636,7 +636,15 @@ gulp.task('_zip-examples', function() {
// Linting // Linting
gulp.task('lint', function() { gulp.task('lint', function() {
return gulp.src(['./public/docs/_examples/style-guide/ts/**/*.ts', '!./public/docs/_examples/style-guide/ts/**/*.avoid.ts']) return gulp.src([
'./public/docs/_examples/**/*.ts',
'!./public/docs/_examples/**/ts-snippets/*.ts',
'!./public/docs/_examples/style-guide/ts/**/*.avoid.ts',
'!./public/docs/_examples/**/node_modules/**/*',
'!./public/docs/_examples/_protractor/**/*',
'!./public/docs/_examples/**/typings/**/*',
'!./public/docs/_examples/**/typings-ng1/**/*'
])
.pipe(tslint({ .pipe(tslint({
rulesDirectory: ['node_modules/codelyzer'], rulesDirectory: ['node_modules/codelyzer'],
configuration: require('./tslint.json') configuration: require('./tslint.json')

View File

@ -31,7 +31,7 @@
"browser-sync": "^2.9.3", "browser-sync": "^2.9.3",
"canonical-path": "0.0.2", "canonical-path": "0.0.2",
"cross-spawn": "^4.0.0", "cross-spawn": "^4.0.0",
"codelyzer": "0.0.20", "codelyzer": "0.0.22",
"del": "^2.2.0", "del": "^2.2.0",
"dgeni": "^0.4.0", "dgeni": "^0.4.0",
"dgeni-packages": "^0.13.0", "dgeni-packages": "^0.13.0",

View File

@ -13,7 +13,7 @@ const HEROES = [
export class BackendService { export class BackendService {
constructor(private logger: Logger) {} constructor(private logger: Logger) {}
getAll(type:Type) : PromiseLike<any[]>{ getAll(type: Type): PromiseLike<any[]> {
if (type === Hero) { if (type === Hero) {
// TODO get from the database // TODO get from the database
return Promise.resolve<Hero[]>(HEROES); return Promise.resolve<Hero[]>(HEROES);

View File

@ -1,4 +1,4 @@
import { Component, Input} from '@angular/core'; import { Component, Input } from '@angular/core';
import { Hero } from './hero'; import { Hero } from './hero';

View File

@ -35,7 +35,7 @@ export class SalesTaxComponent {
constructor(private salesTaxService: SalesTaxService) { } constructor(private salesTaxService: SalesTaxService) { }
// #enddocregion ctor // #enddocregion ctor
getTax(value:string | number){ getTax(value: string | number) {
return this.salesTaxService.getVAT(value); return this.salesTaxService.getVAT(value);
} }
} }

View File

@ -1,5 +1,5 @@
// #docregion // #docregion
import { Inject, Injectable } from '@angular/core'; import { Inject, Injectable } from '@angular/core';
import { TaxRateService } from './tax-rate.service'; import { TaxRateService } from './tax-rate.service';
@ -7,9 +7,9 @@ import { TaxRateService } from './tax-rate.service';
@Injectable() @Injectable()
export class SalesTaxService { export class SalesTaxService {
constructor(private rateService: TaxRateService) { } constructor(private rateService: TaxRateService) { }
getVAT(value:string | number){ getVAT(value: string | number) {
let amount:number; let amount: number;
if (typeof value === "string"){ if (typeof value === 'string') {
amount = parseFloat(value); amount = parseFloat(value);
} else { } else {
amount = value; amount = value;

View File

@ -4,6 +4,6 @@ import { Injectable } from '@angular/core';
// #docregion class // #docregion class
@Injectable() @Injectable()
export class TaxRateService { export class TaxRateService {
getRate(rateName:string){return 0.10;} // always 10% everywhere getRate(rateName: string) {return 0.10; } // always 10% everywhere
} }
// #enddocregion class // #enddocregion class

View File

@ -11,4 +11,4 @@ import { HighlightDirective } from './highlight.directive';
export class AppComponent { } export class AppComponent { }
// #enddocregion // #enddocregion

View File

@ -14,12 +14,12 @@ import { Directive, ElementRef, Input } from '@angular/core';
export class HighlightDirective { export class HighlightDirective {
// #docregion ctor // #docregion ctor
private el:HTMLElement; private el: HTMLElement;
constructor(el: ElementRef) { this.el = el.nativeElement; } constructor(el: ElementRef) { this.el = el.nativeElement; }
// #enddocregion ctor // #enddocregion ctor
// #docregion mouse-methods // #docregion mouse-methods
onMouseEnter() { this.highlight("yellow"); } onMouseEnter() { this.highlight('yellow'); }
onMouseLeave() { this.highlight(null); } onMouseLeave() { this.highlight(null); }
private highlight(color: string) { private highlight(color: string) {

View File

@ -13,12 +13,12 @@ import { Directive, ElementRef, Input } from '@angular/core';
export class HighlightDirective { export class HighlightDirective {
private _defaultColor = 'red'; private _defaultColor = 'red';
private el: HTMLElement; private el: HTMLElement;
constructor(el: ElementRef) { this.el = el.nativeElement; } constructor(el: ElementRef) { this.el = el.nativeElement; }
// #enddocregion class-1 // #enddocregion class-1
// #docregion defaultColor // #docregion defaultColor
@Input() set defaultColor(colorName:string){ @Input() set defaultColor(colorName: string){
this._defaultColor = colorName || this._defaultColor; this._defaultColor = colorName || this._defaultColor;
} }
// #enddocregion defaultColor // #enddocregion defaultColor
@ -33,7 +33,7 @@ export class HighlightDirective {
// #enddocregion mouse-enter // #enddocregion mouse-enter
onMouseLeave() { this.highlight(null); } onMouseLeave() { this.highlight(null); }
private highlight(color:string) { private highlight(color: string) {
this.el.style.backgroundColor = color; this.el.style.backgroundColor = color;
} }
} }

View File

@ -85,7 +85,7 @@ describe('Angular 1 to 2 Quick Reference Tests', function () {
posterButton.click().then(function () { posterButton.click().then(function () {
testImagesAreDisplayed(isDisplayed); testImagesAreDisplayed(isDisplayed);
}) });
} }
function getMovieRows() { function getMovieRows() {
@ -107,7 +107,7 @@ describe('Angular 1 to 2 Quick Reference Tests', function () {
} else { } else {
expect(favoriteHeroLabel.isDisplayed()).toBe(false); expect(favoriteHeroLabel.isDisplayed()).toBe(false);
} }
}) });
}) });
} }
}); });

View File

@ -11,7 +11,7 @@ import { StringSafeDatePipe } from './date.pipe';
// #docregion component // #docregion component
@Component({ @Component({
selector: 'movie-list', selector: 'movie-list',
templateUrl:'app/movie-list.component.html', templateUrl: 'app/movie-list.component.html',
// #enddocregion component // #enddocregion component
// #docregion style-url // #docregion style-url
styleUrls: ['app/movie-list.component.css'], styleUrls: ['app/movie-list.component.css'],

View File

@ -19,8 +19,8 @@ describe('Component Communication Cookbook Tests', function () {
for (let i = 0; i < _heroNames.length; i++) { for (let i = 0; i < _heroNames.length; i++) {
let childTitle = heroes.get(i).element(by.tagName('h3')).getText(); let childTitle = heroes.get(i).element(by.tagName('h3')).getText();
let childDetail = heroes.get(i).element(by.tagName('p')).getText(); let childDetail = heroes.get(i).element(by.tagName('p')).getText();
expect(childTitle).toEqual(_heroNames[i] + ' says:') expect(childTitle).toEqual(_heroNames[i] + ' says:');
expect(childDetail).toContain(_masterName) expect(childDetail).toContain(_masterName);
} }
}); });
// ... // ...
@ -37,7 +37,7 @@ describe('Component Communication Cookbook Tests', function () {
let hero = parent.all(by.tagName('name-child')).get(_nonEmptyNameIndex); let hero = parent.all(by.tagName('name-child')).get(_nonEmptyNameIndex);
let displayName = hero.element(by.tagName('h3')).getText(); let displayName = hero.element(by.tagName('h3')).getText();
expect(displayName).toEqual(_nonEmptyName) expect(displayName).toEqual(_nonEmptyName);
}); });
it('should replace empty name with default name', function () { it('should replace empty name with default name', function () {
@ -47,7 +47,7 @@ describe('Component Communication Cookbook Tests', function () {
let hero = parent.all(by.tagName('name-child')).get(_emptyNameIndex); let hero = parent.all(by.tagName('name-child')).get(_emptyNameIndex);
let displayName = hero.element(by.tagName('h3')).getText(); let displayName = hero.element(by.tagName('h3')).getText();
expect(displayName).toEqual(_defaultName) expect(displayName).toEqual(_defaultName);
}); });
// ... // ...
// #enddocregion parent-to-child-setter // #enddocregion parent-to-child-setter
@ -82,7 +82,7 @@ describe('Component Communication Cookbook Tests', function () {
expect(actual.label).toBe(labelAfter2Minor); expect(actual.label).toBe(labelAfter2Minor);
expect(actual.count).toBe(3); expect(actual.count).toBe(3);
expect(actual.logs.get(2).getText()).toBe(logAfter2Minor); expect(actual.logs.get(2).getText()).toBe(logAfter2Minor);
}) });
}); });
}); });
@ -150,13 +150,15 @@ describe('Component Communication Cookbook Tests', function () {
// ... // ...
// #enddocregion child-to-parent // #enddocregion child-to-parent
}); });
describe('Parent calls child via local var', function() { // Can't run timer tests in protractor because
countDownTimerTests('countdown-parent-lv') // interaction w/ zones causes all tests to freeze & timeout.
}); xdescribe('Parent calls child via local var', function() {
countDownTimerTests('countdown-parent-lv');
describe('Parent calls ViewChild', function() { });
countDownTimerTests('countdown-parent-vc')
xdescribe('Parent calls ViewChild', function() {
countDownTimerTests('countdown-parent-vc');
}); });
function countDownTimerTests(parentTag: string) { function countDownTimerTests(parentTag: string) {
@ -180,7 +182,7 @@ describe('Component Communication Cookbook Tests', function () {
}); });
}); });
// ... // ...
// #enddocregion countdown-timer-tests // #enddocregion countdown-timer-tests
} }

View File

@ -16,9 +16,20 @@ import { MissionControlComponent } from './missioncontrol.component';
NameParentComponent, NameParentComponent,
VersionParentComponent, VersionParentComponent,
VoteTakerComponent, VoteTakerComponent,
CountdownLocalVarParentComponent, MissionControlComponent,
CountdownViewChildParentComponent, ];
MissionControlComponent
] // Include Countdown examples
// unless in e2e tests which they break.
if (!/e2e/.test(location.search)) {
console.log('adding countdown timer examples');
directives.push(CountdownLocalVarParentComponent);
directives.push(CountdownViewChildParentComponent);
}
@Component({
selector: 'app',
templateUrl: 'app/app.component.html',
directives: directives
}) })
export class AppComponent { } export class AppComponent { }

View File

@ -17,12 +17,12 @@ import { Subscription } from 'rxjs/Subscription';
</p> </p>
` `
}) })
export class AstronautComponent implements OnDestroy{ export class AstronautComponent implements OnDestroy {
@Input() astronaut: string; @Input() astronaut: string;
mission = "<no mission announced>"; mission = '<no mission announced>';
confirmed = false; confirmed = false;
announced = false; announced = false;
subscription:Subscription; subscription: Subscription;
constructor(private missionService: MissionService) { constructor(private missionService: MissionService) {
this.subscription = missionService.missionAnnounced$.subscribe( this.subscription = missionService.missionAnnounced$.subscribe(
@ -30,7 +30,7 @@ export class AstronautComponent implements OnDestroy{
this.mission = mission; this.mission = mission;
this.announced = true; this.announced = true;
this.confirmed = false; this.confirmed = false;
}) });
} }
confirm() { confirm() {
@ -38,9 +38,9 @@ export class AstronautComponent implements OnDestroy{
this.missionService.confirmMission(this.astronaut); this.missionService.confirmMission(this.astronaut);
} }
ngOnDestroy(){ ngOnDestroy() {
// prevent memory leak when component destroyed // prevent memory leak when component destroyed
this.subscription.unsubscribe(); this.subscription.unsubscribe();
} }
} }
// #enddocregion // #enddocregion

View File

@ -11,7 +11,7 @@ import { CountdownTimerComponent } from './countdown-timer.component';
//// Local variable, #timer, version //// Local variable, #timer, version
// #docregion lv // #docregion lv
@Component({ @Component({
selector:'countdown-parent-lv', selector: 'countdown-parent-lv',
template: ` template: `
<h3>Countdown to Liftoff (via local variable)</h3> <h3>Countdown to Liftoff (via local variable)</h3>
<button (click)="timer.start()">Start</button> <button (click)="timer.start()">Start</button>
@ -28,7 +28,7 @@ export class CountdownLocalVarParentComponent { }
//// View Child version //// View Child version
// #docregion vc // #docregion vc
@Component({ @Component({
selector:'countdown-parent-vc', selector: 'countdown-parent-vc',
template: ` template: `
<h3>Countdown to Liftoff (via ViewChild)</h3> <h3>Countdown to Liftoff (via ViewChild)</h3>
<button (click)="start()">Start</button> <button (click)="start()">Start</button>
@ -42,7 +42,7 @@ export class CountdownLocalVarParentComponent { }
export class CountdownViewChildParentComponent implements AfterViewInit { export class CountdownViewChildParentComponent implements AfterViewInit {
@ViewChild(CountdownTimerComponent) @ViewChild(CountdownTimerComponent)
private timerComponent:CountdownTimerComponent; private timerComponent: CountdownTimerComponent;
seconds() { return 0; } seconds() { return 0; }
@ -50,10 +50,10 @@ export class CountdownViewChildParentComponent implements AfterViewInit {
// Redefine `seconds()` to get from the `CountdownTimerComponent.seconds` ... // Redefine `seconds()` to get from the `CountdownTimerComponent.seconds` ...
// but wait a tick first to avoid one-time devMode // but wait a tick first to avoid one-time devMode
// unidirectional-data-flow-violation error // unidirectional-data-flow-violation error
setTimeout(() => this.seconds = () => this.timerComponent.seconds, 0) setTimeout(() => this.seconds = () => this.timerComponent.seconds, 0);
} }
start(){ this.timerComponent.start(); } start() { this.timerComponent.start(); }
stop() { this.timerComponent.stop(); } stop() { this.timerComponent.stop(); }
} }
// #enddocregion vc // #enddocregion vc

View File

@ -11,7 +11,7 @@ export class CountdownTimerComponent implements OnInit, OnDestroy {
message = ''; message = '';
seconds = 11; seconds = 11;
clearTimer() {clearInterval(this.intervalId);} clearTimer() { clearInterval(this.intervalId); }
ngOnInit() { this.start(); } ngOnInit() { this.start(); }
ngOnDestroy() { this.clearTimer(); } ngOnDestroy() { this.clearTimer(); }

View File

@ -6,4 +6,4 @@ export const HEROES = [
{name: 'Mr. IQ'}, {name: 'Mr. IQ'},
{name: 'Magneta'}, {name: 'Magneta'},
{name: 'Bombasto'} {name: 'Bombasto'}
]; ];

View File

@ -2,4 +2,4 @@ import { bootstrap } from '@angular/platform-browser-dynamic';
import { AppComponent } from './app.component'; import { AppComponent } from './app.component';
bootstrap(AppComponent); bootstrap(AppComponent);

View File

@ -1,5 +1,5 @@
// #docregion // #docregion
import { Injectable } from '@angular/core' import { Injectable } from '@angular/core';
import { Subject } from 'rxjs/Subject'; import { Subject } from 'rxjs/Subject';
@Injectable() @Injectable()
@ -15,7 +15,7 @@ export class MissionService {
// Service message commands // Service message commands
announceMission(mission: string) { announceMission(mission: string) {
this.missionAnnouncedSource.next(mission) this.missionAnnouncedSource.next(mission);
} }
confirmMission(astronaut: string) { confirmMission(astronaut: string) {

View File

@ -21,7 +21,7 @@ import { MissionService } from './mission.service';
providers: [MissionService] providers: [MissionService]
}) })
export class MissionControlComponent { export class MissionControlComponent {
astronauts = ['Lovell', 'Swigert', 'Haise'] astronauts = ['Lovell', 'Swigert', 'Haise'];
history: string[] = []; history: string[] = [];
missions = ['Fly to the moon!', missions = ['Fly to the moon!',
'Fly to mars!', 'Fly to mars!',
@ -32,7 +32,7 @@ export class MissionControlComponent {
missionService.missionConfirmed$.subscribe( missionService.missionConfirmed$.subscribe(
astronaut => { astronaut => {
this.history.push(`${astronaut} confirmed the mission`); this.history.push(`${astronaut} confirmed the mission`);
}) });
} }
announce() { announce() {

View File

@ -17,7 +17,7 @@ export class VersionChildComponent implements OnChanges {
@Input() minor: number; @Input() minor: number;
changeLog: string[] = []; changeLog: string[] = [];
ngOnChanges(changes: {[propKey:string]: SimpleChange}){ ngOnChanges(changes: {[propKey: string]: SimpleChange}) {
let log: string[] = []; let log: string[] = [];
for (let propName in changes) { for (let propName in changes) {
let changedProp = changes[propName]; let changedProp = changes[propName];

View File

@ -14,9 +14,9 @@ export class VoterComponent {
@Output() onVoted = new EventEmitter<boolean>(); @Output() onVoted = new EventEmitter<boolean>();
voted = false; voted = false;
vote(agreed:boolean){ vote(agreed: boolean) {
this.onVoted.emit(agreed); this.onVoted.emit(agreed);
this.voted = true; this.voted = true;
} }
} }
// #enddocregion // #enddocregion

View File

@ -18,7 +18,7 @@ import { VoterComponent } from './voter.component';
export class VoteTakerComponent { export class VoteTakerComponent {
agreed = 0; agreed = 0;
disagreed = 0; disagreed = 0;
voters = ['Mr. IQ', 'Ms. Universe', 'Bombasto'] voters = ['Mr. IQ', 'Ms. Universe', 'Bombasto'];
onVoted(agreed: boolean) { onVoted(agreed: boolean) {
agreed ? this.agreed++ : this.disagreed++; agreed ? this.agreed++ : this.disagreed++;

View File

@ -12,7 +12,7 @@ describe('Cookbook: component-relative paths', function () {
title: element( by.tagName( 'h1' )), title: element( by.tagName( 'h1' )),
absComp: element( by.css( 'absolute-path div' ) ), absComp: element( by.css( 'absolute-path div' ) ),
relComp: element( by.css( 'relative-path div' ) ) relComp: element( by.css( 'relative-path div' ) )
} };
} }
let page: Page; let page: Page;

View File

@ -1,7 +1,7 @@
// #docregion // #docregion
import { Component } from '@angular/core'; import { Component } from '@angular/core';
import { SomeAbsoluteComponent, SomeRelativeComponent} from './some.component'; import { SomeAbsoluteComponent, SomeRelativeComponent } from './some.component';
@Component({ @Component({
selector: 'my-app', selector: 'my-app',

View File

@ -66,7 +66,7 @@ describe('Dependency Injection Cookbook', function () {
}); });
it('should highlight Hero Bios and Contacts container when mouseover', function () { it('should highlight Hero Bios and Contacts container when mouseover', function () {
let target = element(by.css('div[myHighlight="yellow"]')) let target = element(by.css('div[myHighlight="yellow"]'));
let yellow = 'rgba(255, 255, 0, 1)'; let yellow = 'rgba(255, 255, 0, 1)';
expect(target.getCssValue('background-color')).not.toEqual(yellow); expect(target.getCssValue('background-color')).not.toEqual(yellow);

View File

@ -2,7 +2,7 @@
import { Component } from '@angular/core'; import { Component } from '@angular/core';
import { HeroBiosComponent, import { HeroBiosComponent,
HeroBiosAndContactsComponent} from './hero-bios.component'; HeroBiosAndContactsComponent } from './hero-bios.component';
import { HeroOfTheMonthComponent } from './hero-of-the-month.component'; import { HeroOfTheMonthComponent } from './hero-of-the-month.component';
import { HeroesBaseComponent, import { HeroesBaseComponent,
SortedHeroesComponent } from './sorted-heroes.component'; SortedHeroesComponent } from './sorted-heroes.component';

View File

@ -6,9 +6,9 @@ import { HeroCacheService } from './hero-cache.service';
// #docregion component // #docregion component
@Component({ @Component({
selector:'hero-bio', selector: 'hero-bio',
// #docregion template // #docregion template
template:` template: `
<h4>{{hero.name}}</h4> <h4>{{hero.name}}</h4>
<ng-content></ng-content> <ng-content></ng-content>
<textarea cols="25" [(ngModel)]="hero.description"></textarea>`, <textarea cols="25" [(ngModel)]="hero.description"></textarea>`,
@ -18,9 +18,9 @@ import { HeroCacheService } from './hero-cache.service';
export class HeroBioComponent implements OnInit { export class HeroBioComponent implements OnInit {
@Input() heroId:number; @Input() heroId: number;
constructor(private heroCache:HeroCacheService) { } constructor(private heroCache: HeroCacheService) { }
ngOnInit() { this.heroCache.fetchCachedHero(this.heroId); } ngOnInit() { this.heroCache.fetchCachedHero(this.heroId); }

View File

@ -10,15 +10,15 @@ import { LoggerService } from './logger.service';
//////// HeroBiosComponent //// //////// HeroBiosComponent ////
// #docregion simple // #docregion simple
@Component({ @Component({
selector:'hero-bios', selector: 'hero-bios',
template:` template: `
<hero-bio [heroId]="1"></hero-bio> <hero-bio [heroId]="1"></hero-bio>
<hero-bio [heroId]="2"></hero-bio> <hero-bio [heroId]="2"></hero-bio>
<hero-bio [heroId]="3"></hero-bio>`, <hero-bio [heroId]="3"></hero-bio>`,
directives:[HeroBioComponent], directives: [HeroBioComponent],
providers: [HeroService] providers: [HeroService]
}) })
export class HeroBiosComponent{ export class HeroBiosComponent {
// #enddocregion simple // #enddocregion simple
// #docregion ctor // #docregion ctor
constructor(logger: LoggerService) { constructor(logger: LoggerService) {
@ -32,21 +32,21 @@ export class HeroBiosComponent{
//////// HeroBiosAndContactsComponent //// //////// HeroBiosAndContactsComponent ////
// #docregion hero-bios-and-contacts // #docregion hero-bios-and-contacts
@Component({ @Component({
selector:'hero-bios-and-contacts', selector: 'hero-bios-and-contacts',
// #docregion template // #docregion template
template:` template: `
<hero-bio [heroId]="1"> <hero-contact></hero-contact> </hero-bio> <hero-bio [heroId]="1"> <hero-contact></hero-contact> </hero-bio>
<hero-bio [heroId]="2"> <hero-contact></hero-contact> </hero-bio> <hero-bio [heroId]="2"> <hero-contact></hero-contact> </hero-bio>
<hero-bio [heroId]="3"> <hero-contact></hero-contact> </hero-bio>`, <hero-bio [heroId]="3"> <hero-contact></hero-contact> </hero-bio>`,
// #enddocregion template // #enddocregion template
directives:[HeroBioComponent, HeroContactComponent], directives: [HeroBioComponent, HeroContactComponent],
// #docregion class-provider // #docregion class-provider
providers: [HeroService] providers: [HeroService]
// #enddocregion class-provider // #enddocregion class-provider
}) })
export class HeroBiosAndContactsComponent{ export class HeroBiosAndContactsComponent {
constructor(logger: LoggerService) { constructor(logger: LoggerService) {
logger.logInfo('Creating HeroBiosAndContactsComponent'); logger.logInfo('Creating HeroBiosAndContactsComponent');
} }
} }
// #enddocregion hero-bios-and-contacts // #enddocregion hero-bios-and-contacts

View File

@ -7,14 +7,14 @@ import { HeroService } from './hero.service';
// #docregion service // #docregion service
@Injectable() @Injectable()
export class HeroCacheService { export class HeroCacheService {
hero:Hero; hero: Hero;
constructor(private heroService:HeroService){} constructor(private heroService: HeroService) {}
fetchCachedHero(id:number){ fetchCachedHero(id: number) {
if (!this.hero) { if (!this.hero) {
this.hero = this.heroService.getHeroById(id); this.hero = this.heroService.getHeroById(id);
} }
return this.hero return this.hero;
} }
} }
// #enddocregion service // #enddocregion service

View File

@ -1,14 +1,14 @@
// #docplaster // #docplaster
// #docregion // #docregion
import { Component, ElementRef, Host, Inject, Optional } from '@angular/core'; import { Component, ElementRef, Host, Inject, Optional } from '@angular/core';
import { HeroCacheService } from './hero-cache.service'; import { HeroCacheService } from './hero-cache.service';
import { LoggerService } from './logger.service'; import { LoggerService } from './logger.service';
// #docregion component // #docregion component
@Component({ @Component({
selector:'hero-contact', selector: 'hero-contact',
template:` template: `
<div>Phone #: {{phoneNumber}} <div>Phone #: {{phoneNumber}}
<span *ngIf="hasLogger">!!!</span></div>` <span *ngIf="hasLogger">!!!</span></div>`
}) })

View File

@ -4,10 +4,10 @@ import { Hero } from './hero';
export class HeroData { export class HeroData {
createDb() { createDb() {
let heroes = [ let heroes = [
new Hero(1,"Windstorm"), new Hero(1, 'Windstorm'),
new Hero(2,"Bombasto"), new Hero(2, 'Bombasto'),
new Hero(3,"Magneta"), new Hero(3, 'Magneta'),
new Hero(4,"Tornado") new Hero(4, 'Tornado')
]; ];
return {heroes}; return {heroes};
} }

View File

@ -5,18 +5,18 @@ import { Hero } from './hero';
@Injectable() @Injectable()
export class HeroService { export class HeroService {
//TODO move to database // TODO move to database
private heroes:Array<Hero> = [ private heroes: Array<Hero> = [
new Hero(1, 'RubberMan','Hero of many talents', '123-456-7899'), new Hero(1, 'RubberMan', 'Hero of many talents', '123-456-7899'),
new Hero(2, 'Magma','Hero of all trades', '555-555-5555'), new Hero(2, 'Magma', 'Hero of all trades', '555-555-5555'),
new Hero(3, 'Mr. Nice','The name says it all','111-222-3333') new Hero(3, 'Mr. Nice', 'The name says it all', '111-222-3333')
]; ];
getHeroById(id:number):Hero{ getHeroById(id: number): Hero {
return this.heroes.filter(hero => hero.id === id)[0]; return this.heroes.filter(hero => hero.id === id)[0];
} }
getAllHeroes():Array<Hero>{ getAllHeroes(): Array<Hero> {
return this.heroes; return this.heroes;
} }
} }

View File

@ -1,9 +1,9 @@
// #docregion // #docregion
export class Hero{ export class Hero {
constructor( constructor(
public id: number, public id: number,
public name:string, public name: string,
public description?:string, public description?: string,
public phone?:string) { public phone?: string) {
} }
} }

View File

@ -23,7 +23,7 @@ const provideParent =
// #enddocregion provide-parent, provide-the-parent // #enddocregion provide-parent, provide-the-parent
// #docregion provide-parent // #docregion provide-parent
(component: any, parentType?: any) => { (component: any, parentType?: any) => {
return { provide: parentType || Parent, useExisting: forwardRef(() => component) } return { provide: parentType || Parent, useExisting: forwardRef(() => component) };
}; };
// #enddocregion provide-parent // #enddocregion provide-parent
@ -31,7 +31,7 @@ const provideParent =
const provideTheParent = const provideTheParent =
// #docregion provide-the-parent // #docregion provide-the-parent
(component: any) => { (component: any) => {
return { provide: Parent, useExisting: forwardRef(() => component) } return { provide: Parent, useExisting: forwardRef(() => component) };
}; };
// #enddocregion provide-the-parent // #enddocregion provide-the-parent

View File

@ -9,19 +9,19 @@ import { UserService } from './user.service';
@Injectable() @Injectable()
export class UserContextService { export class UserContextService {
// #enddocregion injectables, injectable // #enddocregion injectables, injectable
name:string; name: string;
role:string; role: string;
loggedInSince:Date; loggedInSince: Date;
// #docregion ctor, injectables // #docregion ctor, injectables
constructor(private userService:UserService, private loggerService:LoggerService){ constructor(private userService: UserService, private loggerService: LoggerService) {
// #enddocregion ctor, injectables // #enddocregion ctor, injectables
this.loggedInSince = new Date(); this.loggedInSince = new Date();
// #docregion ctor, injectables // #docregion ctor, injectables
} }
// #enddocregion ctor, injectables // #enddocregion ctor, injectables
loadUser(userId:number){ loadUser(userId: number) {
let user = this.userService.getUserById(userId); let user = this.userService.getUserById(userId);
this.name = user.name; this.name = user.name;
this.role = user.role; this.role = user.role;

View File

@ -4,7 +4,7 @@ import { Injectable } from '@angular/core';
@Injectable() @Injectable()
export class UserService { export class UserService {
getUserById(userId:number):any{ getUserById(userId: number): any {
return {name:'Bombasto',role:'Admin'}; return {name: 'Bombasto', role: 'Admin'};
} }
} }

View File

@ -15,7 +15,7 @@ describe('Dynamic Form', function () {
emailElement.sendKeys(email); emailElement.sendKeys(email);
expect(emailElement.getAttribute('value')).toEqual(email); expect(emailElement.getAttribute('value')).toEqual(email);
element(by.css('select option[value="solid"]')).click() element(by.css('select option[value="solid"]')).click();
let saveButton = element.all(by.css('button')).get(0); let saveButton = element.all(by.css('button')).get(0);
saveButton.click().then(function(){ saveButton.click().then(function(){

View File

@ -1,5 +1,5 @@
// #docregion // #docregion
import { Component } from '@angular/core' import { Component } from '@angular/core';
import { DynamicForm } from './dynamic-form.component'; import { DynamicForm } from './dynamic-form.component';
import { QuestionService } from './question.service'; import { QuestionService } from './question.service';
@ -16,7 +16,7 @@ import { QuestionService } from './question.service';
providers: [QuestionService] providers: [QuestionService]
}) })
export class AppComponent { export class AppComponent {
questions:any[] questions: any[];
constructor(service: QuestionService) { constructor(service: QuestionService) {
this.questions = service.getQuestions(); this.questions = service.getQuestions();

View File

@ -5,11 +5,11 @@ import { ControlGroup } from '@angular/common';
import { QuestionBase } from './question-base'; import { QuestionBase } from './question-base';
@Component({ @Component({
selector:'df-question', selector: 'df-question',
templateUrl:'app/dynamic-form-question.component.html' templateUrl: 'app/dynamic-form-question.component.html'
}) })
export class DynamicFormQuestionComponent { export class DynamicFormQuestionComponent {
@Input() question:QuestionBase<any>; @Input() question: QuestionBase<any>;
@Input() form:ControlGroup; @Input() form: ControlGroup;
get isValid() { return this.form.controls[this.question.key].valid; } get isValid() { return this.form.controls[this.question.key].valid; }
} }

View File

@ -7,8 +7,8 @@ import { QuestionControlService } from './question-control.service';
import { DynamicFormQuestionComponent } from './dynamic-form-question.component'; import { DynamicFormQuestionComponent } from './dynamic-form-question.component';
@Component({ @Component({
selector:'dynamic-form', selector: 'dynamic-form',
templateUrl:'app/dynamic-form.component.html', templateUrl: 'app/dynamic-form.component.html',
directives: [DynamicFormQuestionComponent], directives: [DynamicFormQuestionComponent],
providers: [QuestionControlService] providers: [QuestionControlService]
}) })
@ -20,7 +20,7 @@ export class DynamicForm {
constructor(private qcs: QuestionControlService) { } constructor(private qcs: QuestionControlService) { }
ngOnInit(){ ngOnInit() {
this.form = this.qcs.toControlGroup(this.questions); this.form = this.qcs.toControlGroup(this.questions);
} }

View File

@ -3,4 +3,4 @@ import { bootstrap } from '@angular/platform-browser-dynamic';
import { AppComponent } from './app.component'; import { AppComponent } from './app.component';
bootstrap(AppComponent, []) bootstrap(AppComponent, [])
.catch((err:any) => console.error(err)); .catch((err: any) => console.error(err));

View File

@ -1,20 +1,20 @@
// #docregion // #docregion
export class QuestionBase<T>{ export class QuestionBase<T>{
value:T; value: T;
key:string; key: string;
label:string; label: string;
required:boolean; required: boolean;
order:number; order: number;
controlType:string; controlType: string;
constructor(options:{ constructor(options: {
value?:T, value?: T,
key?:string, key?: string,
label?:string, label?: string,
required?:boolean, required?: boolean,
order?:number, order?: number,
controlType?:string controlType?: string
} = {}){ } = {}) {
this.value = options.value; this.value = options.value;
this.key = options.key || ''; this.key = options.key || '';
this.label = options.label || ''; this.label = options.label || '';

View File

@ -5,9 +5,9 @@ import { QuestionBase } from './question-base';
@Injectable() @Injectable()
export class QuestionControlService { export class QuestionControlService {
constructor(private fb:FormBuilder){ } constructor(private fb: FormBuilder) { }
toControlGroup(questions:QuestionBase<any>[] ) { toControlGroup(questions: QuestionBase<any>[] ) {
let group = {}; let group = {};
questions.forEach(question => { questions.forEach(question => {

View File

@ -1,11 +1,11 @@
// #docregion // #docregion
import { QuestionBase } from './question-base'; import { QuestionBase } from './question-base';
export class DropdownQuestion extends QuestionBase<string>{ export class DropdownQuestion extends QuestionBase<string> {
controlType = 'dropdown'; controlType = 'dropdown';
options:{key:string, value:string}[] = []; options: {key: string, value: string}[] = [];
constructor(options:{} = {}){ constructor(options: {} = {}) {
super(options); super(options);
this.options = options['options'] || []; this.options = options['options'] || [];
} }

View File

@ -1,11 +1,11 @@
// #docregion // #docregion
import { QuestionBase } from './question-base'; import { QuestionBase } from './question-base';
export class TextboxQuestion extends QuestionBase<string>{ export class TextboxQuestion extends QuestionBase<string> {
controlType = 'textbox'; controlType = 'textbox';
type:string; type: string;
constructor(options:{} = {}){ constructor(options: {} = {}) {
super(options); super(options);
this.type = options['type'] || ''; this.type = options['type'] || '';
} }

View File

@ -13,36 +13,36 @@ export class QuestionService {
// Todo: make asynchronous // Todo: make asynchronous
getQuestions() { getQuestions() {
let questions:QuestionBase<any>[] = [ let questions: QuestionBase<any>[] = [
new DropdownQuestion({ new DropdownQuestion({
key:'brave', key: 'brave',
label: 'Bravery Rating', label: 'Bravery Rating',
options: [ options: [
{key:'solid', value:'Solid'}, {key: 'solid', value: 'Solid'},
{key:'great', value:'Great'}, {key: 'great', value: 'Great'},
{key:'good', value:'Good'}, {key: 'good', value: 'Good'},
{key:'unproven',value:'Unproven'} {key: 'unproven', value: 'Unproven'}
], ],
order: 3 order: 3
}), }),
new TextboxQuestion({ new TextboxQuestion({
key:'firstName', key: 'firstName',
label:'First name', label: 'First name',
value:'Bombasto', value: 'Bombasto',
required: true, required: true,
order: 1 order: 1
}), }),
new TextboxQuestion({ new TextboxQuestion({
key:'emailAddress', key: 'emailAddress',
label:'Email', label: 'Email',
type: 'email', type: 'email',
order: 2 order: 2
}) })
]; ];
return questions.sort((a,b) => a.order - b.order); return questions.sort((a, b) => a.order - b.order);
} }
} }

View File

@ -1,3 +1,4 @@
/* tslint:disable */
// #docregion // #docregion
import { bootstrap } from '@angular/platform-browser-dynamic'; import { bootstrap } from '@angular/platform-browser-dynamic';

View File

@ -21,11 +21,11 @@ export class TitleComponent {
constructor( constructor(
@Inject('titlePrefix') @Inject('titlePrefix')
@Optional() @Optional()
private titlePrefix:string, private titlePrefix: string,
@Attribute('title') @Attribute('title')
private title:string, private title: string,
@Query('okMsg') @Query('okMsg')
private msg:QueryList<ElementRef>) { private msg: QueryList<ElementRef>) {
} }
ok() { ok() {

View File

@ -8,7 +8,7 @@ import { Component, Inject } from '@angular/core';
export class HeroComponent { export class HeroComponent {
constructor( constructor(
@Inject('heroName') @Inject('heroName')
private name:string) { private name: string) {
} }
} }
// #enddocregion // #enddocregion

View File

@ -8,8 +8,8 @@ import { DataService } from './data.service';
template: `<h1>Hero: {{name}}</h1>` template: `<h1>Hero: {{name}}</h1>`
}) })
export class HeroComponent { export class HeroComponent {
name:string; name: string;
constructor(dataService:DataService) { constructor(dataService: DataService) {
this.name = dataService.getHeroName(); this.name = dataService.getHeroName();
} }
} }

View File

@ -13,8 +13,8 @@ import { Component, EventEmitter, Input, Output } from '@angular/core';
` `
}) })
export class ConfirmComponent { export class ConfirmComponent {
@Input() okMsg:string; @Input() okMsg: string;
@Input('cancelMsg') notOkMsg:string; @Input('cancelMsg') notOkMsg: string;
@Output() ok = @Output() ok =
new EventEmitter(); new EventEmitter();
@Output('cancel') notOk = @Output('cancel') notOk =
@ -44,8 +44,8 @@ export class ConfirmComponent {
directives: [ConfirmComponent] directives: [ConfirmComponent]
}) })
export class AppComponent { export class AppComponent {
okClicked:boolean; okClicked: boolean;
cancelClicked:boolean; cancelClicked: boolean;
onOk() { onOk() {
this.okClicked = true; this.okClicked = true;

View File

@ -11,7 +11,7 @@ import { Component, OnInit }
// #docregion // #docregion
export class HeroComponent export class HeroComponent
implements OnInit { implements OnInit {
name:string; name: string;
ngOnInit() { ngOnInit() {
this.name = 'Windstorm'; this.name = 'Windstorm';
} }

View File

@ -4,14 +4,14 @@ import { Component } from '@angular/core';
@Component({ @Component({
selector: 'hero-view', selector: 'hero-view',
template: template:
'<h1>Hero: {{getName()}}</h1>' '<h1>Hero: {{getName()}}</h1>'
}) })
// #docregion appexport // #docregion appexport
// #docregion class // #docregion class
export class HeroComponent { export class HeroComponent {
title = 'Hero Detail'; title = 'Hero Detail';
getName() {return 'Windstorm';} getName() {return 'Windstorm'; }
} }
// #enddocregion class // #enddocregion class
// #enddocregion appexport // #enddocregion appexport

View File

@ -10,8 +10,8 @@ import { Component, HostBinding, HostListener } from '@angular/core';
export class HeroesComponent { export class HeroesComponent {
@HostBinding() title = 'Tooltip content'; @HostBinding() title = 'Tooltip content';
@HostBinding('class.heading') @HostBinding('class.heading')
hClass = true hClass = true;
active:boolean; active: boolean;
constructor() {} constructor() {}
@ -21,7 +21,7 @@ export class HeroesComponent {
} }
@HostListener('dblclick', ['$event']) @HostListener('dblclick', ['$event'])
doubleClicked(evt:Event) { doubleClicked(evt: Event) {
this.active = true; this.active = true;
} }
} }

View File

@ -14,7 +14,7 @@ import {
</span>` </span>`
}) })
class ActiveLabelComponent { class ActiveLabelComponent {
active:boolean; active: boolean;
activate() { activate() {
this.active = true; this.active = true;
@ -30,11 +30,11 @@ class ActiveLabelComponent {
</h2>` </h2>`
}) })
class HeroComponent { class HeroComponent {
@Input() hero:any; @Input() hero: any;
active:boolean; active: boolean;
@ContentChild(ActiveLabelComponent) @ContentChild(ActiveLabelComponent)
label:ActiveLabelComponent label: ActiveLabelComponent;
activate() { activate() {
this.active = true; this.active = true;
@ -68,7 +68,7 @@ export class HeroesQueriesComponent {
]; ];
@ViewChildren(HeroComponent) @ViewChildren(HeroComponent)
heroCmps:QueryList<HeroComponent>; heroCmps: QueryList<HeroComponent>;
activate() { activate() {
this.heroCmps.forEach( this.heroCmps.forEach(

View File

@ -1,8 +1,6 @@
// #docregion ng2import // #docregion ng2import
import { bootstrap } import { bootstrap }
from '@angular/platform-browser-dynamic'; from '@angular/platform-browser-dynamic';
import {
} from '@angular/router';
import { import {
LocationStrategy, LocationStrategy,
HashLocationStrategy HashLocationStrategy

View File

@ -16,7 +16,7 @@ export class HeroAppComponent {
hero = new Hero( hero = new Hero(
'Human Torch', 'Human Torch',
['Mister Fantastic', 'Invisible Woman', 'Thing'] ['Mister Fantastic', 'Invisible Woman', 'Thing']
) );
@HostBinding('class') get themeClass() { @HostBinding('class') get themeClass() {
return 'theme-light'; return 'theme-light';

View File

@ -1,7 +1,7 @@
export class Hero { export class Hero {
active:boolean; active: boolean;
constructor(public name:string, constructor(public name: string,
public team:string[]) { public team: string[]) {
} }
} }

View File

@ -123,7 +123,7 @@ describe('Dependency Injection Tests', function () {
it('P10 (optional dependency) displays as expected', function () { it('P10 (optional dependency) displays as expected', function () {
expectedMsg = 'Optional logger was not available'; expectedMsg = 'Optional logger was not available';
expect(element(by.css('#p10')).getText()).toEqual(expectedMsg); expect(element(by.css('#p10')).getText()).toEqual(expectedMsg);
}) });
}); });
describe('User/Heroes:', function() { describe('User/Heroes:', function() {
@ -163,8 +163,8 @@ describe('Dependency Injection Tests', function () {
describe('after button click', function() { describe('after button click', function() {
beforeAll(function (done) { beforeAll(function (done) {
let buttonEle = element.all(by.cssContainingText('button','Next User')).get(0); let buttonEle = element.all(by.cssContainingText('button', 'Next User')).get(0);
buttonEle.click().then(done,done); buttonEle.click().then(done, done);
}); });
it('User is Alice - authorized', function () { it('User is Alice - authorized', function () {

View File

@ -13,7 +13,7 @@ import { HeroesComponent } from './heroes/heroes.component.1';
<my-car></my-car> <my-car></my-car>
<my-heroes></my-heroes> <my-heroes></my-heroes>
`, `,
directives:[CarComponent, HeroesComponent] directives: [CarComponent, HeroesComponent]
}) })
export class AppComponent { export class AppComponent {

View File

@ -17,7 +17,7 @@ import { Logger } from './logger.service';
<my-car></my-car> <my-car></my-car>
<my-heroes></my-heroes> <my-heroes></my-heroes>
`, `,
directives:[CarComponent, HeroesComponent], directives: [CarComponent, HeroesComponent],
providers: [ providers: [
Logger, Logger,
// #docregion providers // #docregion providers
@ -26,10 +26,10 @@ import { Logger } from './logger.service';
] ]
}) })
export class AppComponent { export class AppComponent {
title:string; title: string;
// #docregion ctor // #docregion ctor
constructor(@Inject(APP_CONFIG) config:AppConfig) { constructor(@Inject(APP_CONFIG) config: AppConfig) {
this.title = config.title; this.title = config.title;
} }
// #enddocregion ctor // #enddocregion ctor

View File

@ -31,7 +31,7 @@ import { ProvidersComponent } from './providers.component';
<my-heroes id="authorized" *ngIf="isAuthorized"></my-heroes> <my-heroes id="authorized" *ngIf="isAuthorized"></my-heroes>
<my-heroes id="unauthorized" *ngIf="!isAuthorized"></my-heroes> <my-heroes id="unauthorized" *ngIf="!isAuthorized"></my-heroes>
`, `,
directives:[CarComponent, HeroesComponent, directives: [CarComponent, HeroesComponent,
InjectorComponent, TestComponent, ProvidersComponent], InjectorComponent, TestComponent, ProvidersComponent],
// #docregion providers // #docregion providers
providers: [ providers: [
@ -42,22 +42,22 @@ import { ProvidersComponent } from './providers.component';
// #enddocregion providers // #enddocregion providers
}) })
export class AppComponent { export class AppComponent {
title:string; title: string;
// #docregion ctor // #docregion ctor
constructor( constructor(
@Inject(APP_CONFIG) config:AppConfig, @Inject(APP_CONFIG) config: AppConfig,
private userService: UserService) { private userService: UserService) {
this.title = config.title; this.title = config.title;
} }
// #enddocregion ctor // #enddocregion ctor
get isAuthorized() { return this.user.isAuthorized;} get isAuthorized() { return this.user.isAuthorized; }
nextUser() { this.userService.getNewUser(); } nextUser() { this.userService.getNewUser(); }
get user() { return this.userService.user; } get user() { return this.userService.user; }
get userInfo() { get userInfo() {
return `Current user, ${this.user.name}, is `+ return `Current user, ${this.user.name}, is ` +
`${this.isAuthorized ? '' : 'not'} authorized. `; `${this.isAuthorized ? '' : 'not'} authorized. `;
} }
} }

View File

@ -4,10 +4,10 @@ import { OpaqueToken } from '@angular/core';
export let APP_CONFIG = new OpaqueToken('app.config'); export let APP_CONFIG = new OpaqueToken('app.config');
// #enddocregion token // #enddocregion token
//#docregion config // #docregion config
export interface AppConfig { export interface AppConfig {
apiEndpoint: string, apiEndpoint: string;
title: string title: string;
} }
export const HERO_DI_CONFIG: AppConfig = { export const HERO_DI_CONFIG: AppConfig = {

View File

@ -5,42 +5,42 @@ import { Car, Engine, Tires } from './car';
///////// example 1 //////////// ///////// example 1 ////////////
export function simpleCar() { export function simpleCar() {
//#docregion car-ctor-instantiation // #docregion car-ctor-instantiation
// Simple car with 4 cylinders and Flintstone tires. // Simple car with 4 cylinders and Flintstone tires.
var car = new Car(new Engine(), new Tires()); let car = new Car(new Engine(), new Tires());
//#enddocregion car-ctor-instantiation // #enddocregion car-ctor-instantiation
car.description = 'Simple'; car.description = 'Simple';
return car; return car;
} }
///////// example 2 //////////// ///////// example 2 ////////////
//#docregion car-ctor-instantiation-with-param // #docregion car-ctor-instantiation-with-param
class Engine2 { class Engine2 {
constructor(public cylinders: number) { } constructor(public cylinders: number) { }
} }
//#enddocregion car-ctor-instantiation-with-param // #enddocregion car-ctor-instantiation-with-param
export function superCar() { export function superCar() {
//#docregion car-ctor-instantiation-with-param // #docregion car-ctor-instantiation-with-param
// Super car with 12 cylinders and Flintstone tires. // Super car with 12 cylinders and Flintstone tires.
var bigCylinders = 12; let bigCylinders = 12;
var car = new Car(new Engine2(bigCylinders), new Tires()); let car = new Car(new Engine2(bigCylinders), new Tires());
//#enddocregion car-ctor-instantiation-with-param // #enddocregion car-ctor-instantiation-with-param
car.description = 'Super'; car.description = 'Super';
return car; return car;
} }
/////////// example 3 ////////// /////////// example 3 //////////
//#docregion car-ctor-instantiation-with-mocks // #docregion car-ctor-instantiation-with-mocks
class MockEngine extends Engine { cylinders = 8; } class MockEngine extends Engine { cylinders = 8; }
class MockTires extends Tires { make = "YokoGoodStone"; } class MockTires extends Tires { make = 'YokoGoodStone'; }
//#enddocregion car-ctor-instantiation-with-mocks // #enddocregion car-ctor-instantiation-with-mocks
export function testCar() { export function testCar() {
//#docregion car-ctor-instantiation-with-mocks // #docregion car-ctor-instantiation-with-mocks
// Test car with 8 cylinders and YokoGoodStone tires. // Test car with 8 cylinders and YokoGoodStone tires.
var car = new Car(new MockEngine(), new MockTires()); let car = new Car(new MockEngine(), new MockTires());
//#enddocregion car-ctor-instantiation-with-mocks // #enddocregion car-ctor-instantiation-with-mocks
car.description = 'Test'; car.description = 'Test';
return car; return car;
} }

View File

@ -5,23 +5,23 @@ import { Logger } from '../logger.service';
// #docregion injector // #docregion injector
export function useInjector() { export function useInjector() {
var injector: ReflectiveInjector; let injector: ReflectiveInjector;
// #enddocregion injector // #enddocregion injector
/* /*
// #docregion injector-no-new // #docregion injector-no-new
// Cannot instantiate an ReflectiveInjector like this! // Cannot instantiate an ReflectiveInjector like this!
var injector = new ReflectiveInjector([Car, Engine, Tires]); let injector = new ReflectiveInjector([Car, Engine, Tires]);
// #enddocregion injector-no-new // #enddocregion injector-no-new
*/ */
// #docregion injector, injector-create-and-call // #docregion injector, injector-create-and-call
injector = ReflectiveInjector.resolveAndCreate([Car, Engine, Tires]); injector = ReflectiveInjector.resolveAndCreate([Car, Engine, Tires]);
// #docregion injector-call // #docregion injector-call
var car = injector.get(Car); let car = injector.get(Car);
// #enddocregion injector-call, injector-create-and-call // #enddocregion injector-call, injector-create-and-call
car.description = 'Injector'; car.description = 'Injector';
injector = ReflectiveInjector.resolveAndCreate([Logger]); injector = ReflectiveInjector.resolveAndCreate([Logger]);
var logger = injector.get(Logger); let logger = injector.get(Logger);
logger.log('Injector car.drive() said: '+car.drive()); logger.log('Injector car.drive() said: ' + car.drive());
return car; return car;
} }

View File

@ -1,10 +1,10 @@
// Car without DI // Car without DI
import { Engine, Tires } from './car'; import { Engine, Tires } from './car';
//#docregion car // #docregion car
export class Car { export class Car {
//#docregion car-ctor // #docregion car-ctor
public engine: Engine; public engine: Engine;
public tires: Tires; public tires: Tires;
public description = 'No DI'; public description = 'No DI';
@ -13,12 +13,12 @@ export class Car {
this.engine = new Engine(); this.engine = new Engine();
this.tires = new Tires(); this.tires = new Tires();
} }
//#enddocregion car-ctor // #enddocregion car-ctor
// Method using the engine and tires // Method using the engine and tires
drive() { drive() {
return `${this.description} car with ` + return `${this.description} car with ` +
`${this.engine.cylinders} cylinders and ${this.tires.make} tires.` `${this.engine.cylinders} cylinders and ${this.tires.make} tires.`;
} }
} }
//#enddocregion car // #enddocregion car

View File

@ -11,7 +11,7 @@ export class Tires {
@Injectable() @Injectable()
export class Car { export class Car {
//#docregion car-ctor // #docregion car-ctor
public description = 'DI'; public description = 'DI';
constructor(public engine: Engine, public tires: Tires) { } constructor(public engine: Engine, public tires: Tires) { }
@ -20,6 +20,6 @@ export class Car {
// Method using the engine and tires // Method using the engine and tires
drive() { drive() {
return `${this.description} car with ` + return `${this.description} car with ` +
`${this.engine.cylinders} cylinders and ${this.tires.make} tires.` `${this.engine.cylinders} cylinders and ${this.tires.make} tires.`;
} }
} }

View File

@ -1,3 +1,4 @@
/* tslint:disable:one-line */
// #docregion // #docregion
import { Component } from '@angular/core'; import { Component } from '@angular/core';

View File

@ -8,12 +8,12 @@ import { Logger } from '../logger.service';
@Injectable() @Injectable()
export class HeroService { export class HeroService {
//#docregion ctor // #docregion ctor
constructor(private logger: Logger) { } constructor(private logger: Logger) { }
//#enddocregion ctor // #enddocregion ctor
getHeroes() { getHeroes() {
this.logger.log('Getting heroes ...') this.logger.log('Getting heroes ...');
return HEROES; return HEROES;
} }
} }

View File

@ -1,3 +1,4 @@
/* tslint:disable:one-line */
// #docregion // #docregion
import { HeroService } from './hero.service'; import { HeroService } from './hero.service';
import { Logger } from '../logger.service'; import { Logger } from '../logger.service';
@ -6,7 +7,7 @@ import { UserService } from '../user.service';
// #docregion factory // #docregion factory
let heroServiceFactory = (logger: Logger, userService: UserService) => { let heroServiceFactory = (logger: Logger, userService: UserService) => {
return new HeroService(logger, userService.user.isAuthorized); return new HeroService(logger, userService.user.isAuthorized);
} };
// #enddocregion factory // #enddocregion factory
// #docregion provider // #docregion provider

View File

@ -7,7 +7,7 @@ import { Logger } from '../logger.service';
@Injectable() @Injectable()
export class HeroService { export class HeroService {
private _user:string; private _user: string;
// #docregion internals // #docregion internals
constructor( constructor(
@ -15,7 +15,7 @@ export class HeroService {
private isAuthorized: boolean) { } private isAuthorized: boolean) { }
getHeroes() { getHeroes() {
let auth = this.isAuthorized ? 'authorized ': 'unauthorized'; let auth = this.isAuthorized ? 'authorized ' : 'unauthorized';
this.logger.log(`Getting heroes for ${auth} user.`); this.logger.log(`Getting heroes for ${auth} user.`);
return HEROES.filter(hero => this.isAuthorized || !hero.isSecret); return HEROES.filter(hero => this.isAuthorized || !hero.isSecret);
} }

View File

@ -21,8 +21,8 @@ import { HeroService } from './hero.service';
<hero-list></hero-list> <hero-list></hero-list>
`, `,
// #enddocregion v1 // #enddocregion v1
providers:[HeroService], providers: [HeroService],
// #docregion v1 // #docregion v1
directives:[HeroListComponent] directives: [HeroListComponent]
}) })
export class HeroesComponent { } export class HeroesComponent { }

View File

@ -2,7 +2,7 @@
import { Component } from '@angular/core'; import { Component } from '@angular/core';
import { HeroListComponent } from './hero-list.component'; import { HeroListComponent } from './hero-list.component';
import { heroServiceProvider} from './hero.service.provider'; import { heroServiceProvider } from './hero.service.provider';
@Component({ @Component({
selector: 'my-heroes', selector: 'my-heroes',
@ -10,7 +10,7 @@ import { heroServiceProvider} from './hero.service.provider';
<h2>Heroes</h2> <h2>Heroes</h2>
<hero-list></hero-list> <hero-list></hero-list>
`, `,
providers:[heroServiceProvider], providers: [heroServiceProvider],
directives:[HeroListComponent] directives: [HeroListComponent]
}) })
export class HeroesComponent { } export class HeroesComponent { }

View File

@ -2,14 +2,14 @@
import { Hero } from './hero'; import { Hero } from './hero';
export var HEROES: Hero[] = [ export var HEROES: Hero[] = [
{ id: 11, isSecret: false, name: "Mr. Nice" }, { id: 11, isSecret: false, name: 'Mr. Nice' },
{ id: 12, isSecret: false, name: "Narco" }, { id: 12, isSecret: false, name: 'Narco' },
{ id: 13, isSecret: false, name: "Bombasto" }, { id: 13, isSecret: false, name: 'Bombasto' },
{ id: 14, isSecret: false, name: "Celeritas" }, { id: 14, isSecret: false, name: 'Celeritas' },
{ id: 15, isSecret: false, name: "Magneta" }, { id: 15, isSecret: false, name: 'Magneta' },
{ id: 16, isSecret: false, name: "RubberMan" }, { id: 16, isSecret: false, name: 'RubberMan' },
{ id: 17, isSecret: false, name: "Dynama" }, { id: 17, isSecret: false, name: 'Dynama' },
{ id: 18, isSecret: true, name: "Dr IQ" }, { id: 18, isSecret: true, name: 'Dr IQ' },
{ id: 19, isSecret: true, name: "Magma" }, { id: 19, isSecret: true, name: 'Magma' },
{ id: 20, isSecret: true, name: "Tornado" } { id: 20, isSecret: true, name: 'Tornado' }
]; ];

View File

@ -20,8 +20,6 @@ import { Logger } from './logger.service';
providers: [Car, Engine, Tires, heroServiceProvider, Logger] providers: [Car, Engine, Tires, heroServiceProvider, Logger]
}) })
export class InjectorComponent { export class InjectorComponent {
constructor(private injector: Injector) { }
car: Car = this.injector.get(Car); car: Car = this.injector.get(Car);
// #docregion get-hero-service // #docregion get-hero-service
@ -29,8 +27,10 @@ export class InjectorComponent {
// #enddocregion get-hero-service // #enddocregion get-hero-service
hero: Hero = this.heroService.getHeroes()[0]; hero: Hero = this.heroService.getHeroes()[0];
constructor(private injector: Injector) { }
get rodent() { get rodent() {
let rousDontExist = "R.O.U.S.'s? I don't think they exist!"; let rousDontExist = `R.O.U.S.'s? I don't think they exist!`;
return this.injector.get(ROUS, rousDontExist); return this.injector.get(ROUS, rousDontExist);
} }
} }

View File

@ -3,7 +3,7 @@ import { Injectable } from '@angular/core';
@Injectable() @Injectable()
export class Logger { export class Logger {
logs:string[] = []; // capture logs for testing logs: string[] = []; // capture logs for testing
log(message: string) { log(message: string) {
this.logs.push(message); this.logs.push(message);

View File

@ -1,3 +1,4 @@
/* tslint:disable:no-unused-variable */
import { bootstrap } from '@angular/platform-browser-dynamic'; import { bootstrap } from '@angular/platform-browser-dynamic';
import { AppComponent } from './app.component.1'; import { AppComponent } from './app.component.1';
import { HeroService } from './heroes/hero.service.1'; import { HeroService } from './heroes/hero.service.1';
@ -5,9 +6,8 @@ import { HeroService } from './heroes/hero.service.1';
bootstrap(AppComponent); bootstrap(AppComponent);
function discouraged() { function discouraged() {
//#docregion bootstrap // #docregion bootstrap-discouraged
bootstrap(AppComponent, bootstrap(AppComponent,
[HeroService]); // DISCOURAGED (but works)不推荐(但可用) [HeroService]); // DISCOURAGED (but works)
//#enddocregion bootstrap // #enddocregion bootstrap-discouraged
} }

View File

@ -2,7 +2,7 @@ import { bootstrap } from '@angular/platform-browser-dynamic';
import { AppComponent } from './app.component'; import { AppComponent } from './app.component';
import { ProvidersComponent } from './providers.component'; import { ProvidersComponent } from './providers.component';
//#docregion bootstrap // #docregion bootstrap
bootstrap(AppComponent); bootstrap(AppComponent);
//#enddocregion bootstrap // #enddocregion bootstrap
bootstrap(ProvidersComponent); bootstrap(ProvidersComponent);

View File

@ -235,8 +235,9 @@ export class ProviderComponent10 {
log: string; log: string;
// #docregion provider-10-ctor // #docregion provider-10-ctor
constructor(@Optional() private logger: Logger) { constructor(@Optional() private logger: Logger) {
if (this.logger) if (this.logger) {
this.logger.log(some_message); this.logger.log(some_message);
}
} }
// #enddocregion provider-10-ctor // #enddocregion provider-10-ctor

View File

@ -1,3 +1,4 @@
/* tslint:disable */
// Simulate a simple test // Simulate a simple test
// Reader should look to the testing chapter for the real thing // Reader should look to the testing chapter for the real thing
@ -20,15 +21,15 @@ export class TestComponent {
///////////////////////////////////// /////////////////////////////////////
function runTests() { function runTests() {
//#docregion spec // #docregion spec
let expectedHeroes = [{name: 'A'}, {name: 'B'}] let expectedHeroes = [{name: 'A'}, {name: 'B'}]
let mockService = <HeroService> {getHeroes: () => expectedHeroes } let mockService = <HeroService> {getHeroes: () => expectedHeroes }
it("should have heroes when HeroListComponent created", () => { it('should have heroes when HeroListComponent created', () => {
let hlc = new HeroListComponent(mockService); let hlc = new HeroListComponent(mockService);
expect(hlc.heroes.length).toEqual(expectedHeroes.length); expect(hlc.heroes.length).toEqual(expectedHeroes.length);
}) });
//#enddocregion spec // #enddocregion spec
return testResults; return testResults;
} }
@ -36,19 +37,19 @@ function runTests() {
////////////////////////////////// //////////////////////////////////
// Fake Jasmine infrastructure // Fake Jasmine infrastructure
var testName: string; var testName: string;
var testResults: {pass:string; message:string}; var testResults: {pass: string; message: string};
function expect(actual:any) { function expect(actual: any) {
return { return {
toEqual: function(expected:any){ toEqual: function(expected: any){
testResults = actual === expected? testResults = actual === expected ?
{pass:'passed', message: testName} : {pass: 'passed', message: testName} :
{pass:'failed', message: `${testName}; expected ${actual} to equal ${expected}.`}; {pass: 'failed', message: `${testName}; expected ${actual} to equal ${expected}.`};
} }
} };
} }
function it(label:string, test: () => void) { function it(label: string, test: () => void) {
testName = label; testName = label;
test(); test();
} }

View File

@ -1,10 +1,10 @@
// #docregion // #docregion
import {Injectable} from '@angular/core'; import { Injectable } from '@angular/core';
export class User { export class User {
constructor( constructor(
public name:string, public name: string,
public isAuthorized:boolean = false) { } public isAuthorized = false) { }
} }
// Todo: get the user; don't 'new' it. // Todo: get the user; don't 'new' it.

View File

@ -17,4 +17,4 @@ export class AppCtorComponent {
this.myHero = 'Windstorm'; this.myHero = 'Windstorm';
} }
} }
// #enddocregion app-ctor // #enddocregion app-ctor

View File

@ -1,7 +1,7 @@
// #docregion // #docregion
import { Component} from '@angular/core'; import { Component } from '@angular/core';
// #docregion import-hero // #docregion import-hero
import { Hero} from './hero'; import { Hero } from './hero';
// #enddocregion import-hero // #enddocregion import-hero
@Component({ @Component({

View File

@ -2,8 +2,8 @@
export class Hero { export class Hero {
constructor( constructor(
// #docregion id-parameter // #docregion id-parameter
public id:number, public id: number,
// #enddocregion id-parameter // #enddocregion id-parameter
public name:string) { } public name: string) { }
} }
// #enddocregion // #enddocregion

View File

@ -1,3 +1,4 @@
/* tslint:disable */
import { bootstrap } from '@angular/platform-browser-dynamic'; import { bootstrap } from '@angular/platform-browser-dynamic';
import { AppCtorComponent } from './app-ctor.component'; import { AppCtorComponent } from './app-ctor.component';
@ -8,9 +9,9 @@ import { AppComponent as v3 } from './app.component.3';
import { AppComponent as final } from './app.component'; import { AppComponent as final } from './app.component';
// pick one // pick one
//bootstrap(v1); // bootstrap(v1);
//bootstrap(v2); // bootstrap(v2);
//bootstrap(v3); // bootstrap(v3);
bootstrap(final); bootstrap(final);
// for doc testing // for doc testing

View File

@ -1,6 +1,6 @@
// #docregion // #docregion
import { Component } from '@angular/core'; import { Component } from '@angular/core';
import { HeroFormComponent } from './hero-form.component' import { HeroFormComponent } from './hero-form.component';
@Component({ @Component({
selector: 'my-app', selector: 'my-app',

View File

@ -41,7 +41,7 @@ export class HeroFormComponent {
this.model = new Hero(42, '', ''); this.model = new Hero(42, '', '');
// #enddocregion new-hero-v1 // #enddocregion new-hero-v1
this.active = false; this.active = false;
setTimeout(()=> this.active=true, 0); setTimeout(() => this.active = true, 0);
// #docregion new-hero-v1 // #docregion new-hero-v1
} }
// #enddocregion new-hero-v1 // #enddocregion new-hero-v1
@ -51,7 +51,7 @@ export class HeroFormComponent {
// Reveal in html: // Reveal in html:
// Name via form.controls = {{showFormControls(heroForm)}} // Name via form.controls = {{showFormControls(heroForm)}}
showFormControls(form:NgForm){ showFormControls(form: NgForm) {
return form && form.controls['name'] && return form && form.controls['name'] &&
// #docregion form-controls // #docregion form-controls

View File

@ -6,8 +6,8 @@ describe('Hierarchical dependency injection', function () {
}); });
it('should open with a card view', function () { it('should open with a card view', function () {
expect(element.all(by.cssContainingText('button','edit')).get(0).isDisplayed()).toBe(true, expect(element.all(by.cssContainingText('button', 'edit')).get(0).isDisplayed()).toBe(true,
"edit button should be displayed"); 'edit button should be displayed');
}); });
it('should have multiple heroes listed', function () { it('should have multiple heroes listed', function () {
@ -15,10 +15,10 @@ describe('Hierarchical dependency injection', function () {
}); });
it('should change to editor view after selection', function () { it('should change to editor view after selection', function () {
let editButtonEle = element.all(by.cssContainingText('button','edit')).get(0); let editButtonEle = element.all(by.cssContainingText('button', 'edit')).get(0);
editButtonEle.click().then(function() { editButtonEle.click().then(function() {
expect(editButtonEle.isDisplayed()).toBe(false, "edit button should be hidden after selection"); expect(editButtonEle.isDisplayed()).toBe(false, 'edit button should be hidden after selection');
}) });
}); });
it('should be able to save editor change', function () { it('should be able to save editor change', function () {
@ -34,11 +34,11 @@ describe('Hierarchical dependency injection', function () {
let heroEle = element.all(by.css('heroes-list li')).get(1); let heroEle = element.all(by.css('heroes-list li')).get(1);
// get the 2nd span which is the name of the hero // get the 2nd span which is the name of the hero
let heroNameEle = heroEle.all(by.css('hero-card span')).get(1); let heroNameEle = heroEle.all(by.css('hero-card span')).get(1);
let editButtonEle = heroEle.element(by.cssContainingText('button','edit')); let editButtonEle = heroEle.element(by.cssContainingText('button', 'edit'));
editButtonEle.click().then(function() { editButtonEle.click().then(function() {
let inputEle = heroEle.element(by.css('hero-editor input')); let inputEle = heroEle.element(by.css('hero-editor input'));
// return inputEle.sendKeys("foo"); // return inputEle.sendKeys("foo");
return sendKeys(inputEle, "foo"); return sendKeys(inputEle, 'foo');
}).then(function() { }).then(function() {
let buttonName = shouldSave ? 'save' : 'cancel'; let buttonName = shouldSave ? 'save' : 'cancel';
let buttonEle = heroEle.element(by.cssContainingText('button', buttonName)); let buttonEle = heroEle.element(by.cssContainingText('button', buttonName));
@ -49,7 +49,7 @@ describe('Hierarchical dependency injection', function () {
} else { } else {
expect(heroNameEle.getText()).not.toContain('foo'); expect(heroNameEle.getText()).not.toContain('foo');
} }
}) });
} }

View File

@ -1,6 +1,6 @@
// #docregion // #docregion
export class EditItem<T> { export class EditItem<T> {
editing: boolean editing: boolean;
constructor (public item: T) {} constructor (public item: T) {}
} }
// #docregion // #docregion

View File

@ -2,8 +2,8 @@ import { Hero } from './hero';
export class HeroesService { export class HeroesService {
heroes: Array<Hero> = [ heroes: Array<Hero> = [
{ name: "RubberMan", power: 'flexibility'}, { name: 'RubberMan', power: 'flexibility'},
{ name: "Tornado", power: 'Weather changer'} { name: 'Tornado', power: 'Weather changer'}
]; ];
getHeroes () { getHeroes () {

View File

@ -4,7 +4,7 @@ import { bootstrap } from '@angular/platform-browser-dynamic';
import { HeroesListComponent } from './heroes-list.component'; import { HeroesListComponent } from './heroes-list.component';
import { HeroesService } from './heroes.service'; import { HeroesService } from './heroes.service';
bootstrap(HeroesListComponent, [HeroesService]) bootstrap(HeroesListComponent, [HeroesService]);
/* Documentation artifact below /* Documentation artifact below
// #docregion bad-alternative // #docregion bad-alternative

View File

@ -8,16 +8,16 @@ export class RestoreService<T> {
this.currentItem = this.clone(item); this.currentItem = this.clone(item);
} }
getItem () :T { getItem (): T {
return this.currentItem; return this.currentItem;
} }
restoreItem () :T { restoreItem (): T {
this.currentItem = this.originalItem; this.currentItem = this.originalItem;
return this.getItem(); return this.getItem();
} }
clone (item: T) :T { clone (item: T): T {
// super poor clone implementation // super poor clone implementation
return JSON.parse(JSON.stringify(item)); return JSON.parse(JSON.stringify(item));
} }

View File

@ -10,7 +10,7 @@ describe('Homepage Hello World', function () {
it(`should display the label: ${expectedLabel}`, function () { it(`should display the label: ${expectedLabel}`, function () {
expect(element(by.css('label')).getText()).toEqual(expectedLabel); expect(element(by.css('label')).getText()).toEqual(expectedLabel);
}); });
it('should display entered name', function () { it('should display entered name', function () {
let testName = 'Bobby Joe'; let testName = 'Bobby Joe';
let nameEle = element.all(by.css('input')).get(0); let nameEle = element.all(by.css('input')).get(0);

View File

@ -1,6 +1,6 @@
// #docregion // #docregion
// Declare an interaface for type safety // Declare an interaface for type safety
export interface Todo { export interface Todo {
text: string, text: string;
done: boolean done: boolean;
} }

View File

@ -14,7 +14,7 @@ import { TodoForm } from './todo_form';
<todo-list [todos]="todos"></todo-list> <todo-list [todos]="todos"></todo-list>
<todo-form (newTask)="addTask($event)"></todo-form>`, <todo-form (newTask)="addTask($event)"></todo-form>`,
styles:['a { cursor: pointer; cursor: hand; }'], styles: ['a { cursor: pointer; cursor: hand; }'],
directives: [TodoList, TodoForm] directives: [TodoList, TodoForm]
}) })
export class TodoApp { export class TodoApp {

View File

@ -17,7 +17,7 @@ export class TodoForm {
addTodo() { addTodo() {
if (this.task) { if (this.task) {
this.newTask.next({text:this.task, done:false}); this.newTask.next({text: this.task, done: false});
} }
this.task = ''; this.task = '';
} }

View File

@ -1,5 +1,6 @@
// #docregion // #docregion
import { Component, Input } from '@angular/core'; import { Component, Input } from '@angular/core';
import { Todo } from './todo'; import { Todo } from './todo';
@Component({ @Component({

View File

@ -11,22 +11,22 @@ describe('Lifecycle hooks', function () {
it('should support peek-a-boo', function () { it('should support peek-a-boo', function () {
let pabComp = element(by.css('peek-a-boo-parent peek-a-boo')); let pabComp = element(by.css('peek-a-boo-parent peek-a-boo'));
expect(pabComp.isPresent()).toBe(false, "should not be able to find the 'peek-a-boo' component"); expect(pabComp.isPresent()).toBe(false, 'should not be able to find the "peek-a-boo" component');
let pabButton = element.all(by.css('peek-a-boo-parent button')).get(0); let pabButton = element.all(by.css('peek-a-boo-parent button')).get(0);
let updateHeroButton = element.all(by.css('peek-a-boo-parent button')).get(1); let updateHeroButton = element.all(by.css('peek-a-boo-parent button')).get(1);
expect(pabButton.getText()).toContain('Create Peek'); expect(pabButton.getText()).toContain('Create Peek');
pabButton.click().then(function () { pabButton.click().then(function () {
expect(pabButton.getText()).toContain('Destroy Peek'); expect(pabButton.getText()).toContain('Destroy Peek');
expect(pabComp.isDisplayed()).toBe(true, "should be able to see the 'peek-a-boo' component"); expect(pabComp.isDisplayed()).toBe(true, 'should be able to see the "peek-a-boo" component');
expect(pabComp.getText()).toContain('Windstorm'); expect(pabComp.getText()).toContain('Windstorm');
expect(pabComp.getText()).not.toContain('Windstorm!'); expect(pabComp.getText()).not.toContain('Windstorm!');
expect(updateHeroButton.isPresent()).toBe(true, "should be able to see the update hero button"); expect(updateHeroButton.isPresent()).toBe(true, 'should be able to see the update hero button');
return updateHeroButton.click(); return updateHeroButton.click();
}).then(function () { }).then(function () {
expect(pabComp.getText()).toContain('Windstorm!'); expect(pabComp.getText()).toContain('Windstorm!');
return pabButton.click(); return pabButton.click();
}).then(function () { }).then(function () {
expect(pabComp.isPresent()).toBe(false, "should no longer be able to find the 'peek-a-boo' component"); expect(pabComp.isPresent()).toBe(false, 'should no longer be able to find the "peek-a-boo" component');
}); });
}); });
@ -39,18 +39,18 @@ describe('Lifecycle hooks', function () {
let changeLogEles = onChangesViewEle.all(by.css('div')); let changeLogEles = onChangesViewEle.all(by.css('div'));
expect(titleEle.getText()).toContain('Windstorm can sing'); expect(titleEle.getText()).toContain('Windstorm can sing');
expect(changeLogEles.count()).toEqual(2, "should start with 2 messages"); expect(changeLogEles.count()).toEqual(2, 'should start with 2 messages');
// heroNameInputEle.sendKeys('-foo-').then(function () { // heroNameInputEle.sendKeys('-foo-').then(function () {
sendKeys(heroNameInputEle, '-foo-').then(function () { sendKeys(heroNameInputEle, '-foo-').then(function () {
expect(titleEle.getText()).toContain('Windstorm-foo- can sing'); expect(titleEle.getText()).toContain('Windstorm-foo- can sing');
expect(changeLogEles.count()).toEqual(2, "should still have 2 messages"); expect(changeLogEles.count()).toEqual(2, 'should still have 2 messages');
// protractor bug with sendKeys means that line below does not work. // protractor bug with sendKeys means that line below does not work.
// return powerInputEle.sendKeys('-bar-'); // return powerInputEle.sendKeys('-bar-');
return sendKeys(powerInputEle, '-bar-'); return sendKeys(powerInputEle, '-bar-');
}).then(function () { }).then(function () {
expect(titleEle.getText()).toContain('Windstorm-foo- can sing-bar-'); expect(titleEle.getText()).toContain('Windstorm-foo- can sing-bar-');
// 7 == 2 previously + length of '-bar-' // 7 == 2 previously + length of '-bar-'
expect(changeLogEles.count()).toEqual(7, "should have 7 messages now"); expect(changeLogEles.count()).toEqual(7, 'should have 7 messages now');
}); });
}); });
@ -66,16 +66,16 @@ describe('Lifecycle hooks', function () {
expect(titleEle.getText()).toContain('Windstorm can sing'); expect(titleEle.getText()).toContain('Windstorm can sing');
changeLogEles.count().then(function(count) { changeLogEles.count().then(function(count) {
// Empirically 5 messages to start // Empirically 5 messages to start
expect(count).toBeGreaterThan(4, "should start with some messages"); expect(count).toBeGreaterThan(4, 'should start with some messages');
logCount = count; logCount = count;
// heroNameInputEle.sendKeys('-foo-').then(function () { // heroNameInputEle.sendKeys('-foo-').then(function () {
return sendKeys(heroNameInputEle, '-foo-') return sendKeys(heroNameInputEle, '-foo-');
}).then(function () { }).then(function () {
expect(titleEle.getText()).toContain('Windstorm-foo- can sing'); expect(titleEle.getText()).toContain('Windstorm-foo- can sing');
return changeLogEles.count() return changeLogEles.count();
}).then(function (count) { }).then(function (count) {
// two more for each keystroke except the 1st // two more for each keystroke except the 1st
expect(count).toEqual(logCount + 9, 'should add 9 more messages') expect(count).toEqual(logCount + 9, 'should add 9 more messages');
logCount = count; logCount = count;
// return powerInputEle.sendKeys('-bar-'); // return powerInputEle.sendKeys('-bar-');
return sendKeys(powerInputEle, '-bar-'); return sendKeys(powerInputEle, '-bar-');
@ -99,18 +99,18 @@ describe('Lifecycle hooks', function () {
logEles.count().then(function(count) { logEles.count().then(function(count) {
logCount = count; logCount = count;
return sendKeys(childViewInputEle, "-test-"); return sendKeys(childViewInputEle, '-test-');
}).then(function() { }).then(function() {
expect(childViewInputEle.getAttribute('value')).toContain('-test-'); expect(childViewInputEle.getAttribute('value')).toContain('-test-');
expect(commentEle.isPresent()).toBe(true,'should have comment because >10 chars'); expect(commentEle.isPresent()).toBe(true, 'should have comment because >10 chars');
expect(commentEle.getText()).toContain('long name'); expect(commentEle.getText()).toContain('long name');
return logEles.count(); return logEles.count();
}).then(function(count) { }).then(function(count) {
expect(logCount + 10).toEqual(count, "10 additional log messages should have been added"); expect(logCount + 10).toEqual(count, '10 additional log messages should have been added');
logCount = count; logCount = count;
return buttonEle.click(); return buttonEle.click();
}).then(function() { }).then(function() {
expect(logEles.count()).toBeLessThan(logCount, "log should shrink after reset"); expect(logEles.count()).toBeLessThan(logCount, 'log should shrink after reset');
}); });
}); });
@ -128,30 +128,30 @@ describe('Lifecycle hooks', function () {
logEles.count().then(function(count) { logEles.count().then(function(count) {
logCount = count; logCount = count;
return sendKeys(childViewInputEle, "-test-"); return sendKeys(childViewInputEle, '-test-');
}).then(function() { }).then(function() {
expect(childViewInputEle.getAttribute('value')).toContain('-test-'); expect(childViewInputEle.getAttribute('value')).toContain('-test-');
expect(commentEle.isPresent()).toBe(true,'should have comment because >10 chars'); expect(commentEle.isPresent()).toBe(true, 'should have comment because >10 chars');
expect(commentEle.getText()).toContain('long name'); expect(commentEle.getText()).toContain('long name');
return logEles.count(); return logEles.count();
}).then(function(count) { }).then(function(count) {
expect(logCount + 10).toEqual(count, "10 additional log messages should have been added"); expect(logCount + 10).toEqual(count, '10 additional log messages should have been added');
logCount = count; logCount = count;
return buttonEle.click(); return buttonEle.click();
}).then(function() { }).then(function() {
expect(logEles.count()).toBeLessThan(logCount, "log should shrink after reset"); expect(logEles.count()).toBeLessThan(logCount, 'log should shrink after reset');
}); });
}); });
it('should support spy\'s OnInit & OnDestroy hooks', function () { it('should support spy\'s OnInit & OnDestroy hooks', function () {
let inputEle = element(by.css('spy-parent input')); let inputEle = element(by.css('spy-parent input'));
let addHeroButtonEle = element(by.cssContainingText('spy-parent button','Add Hero')); let addHeroButtonEle = element(by.cssContainingText('spy-parent button', 'Add Hero'));
let resetHeroesButtonEle = element(by.cssContainingText('spy-parent button','Reset Heroes')); let resetHeroesButtonEle = element(by.cssContainingText('spy-parent button', 'Reset Heroes'));
let heroEles = element.all(by.css('spy-parent div[mySpy')); let heroEles = element.all(by.css('spy-parent div[mySpy'));
let logEles = element.all(by.css('spy-parent h4 ~ div')); let logEles = element.all(by.css('spy-parent h4 ~ div'));
expect(heroEles.count()).toBe(2, 'should have two heroes displayed'); expect(heroEles.count()).toBe(2, 'should have two heroes displayed');
expect(logEles.count()).toBe(2, 'should have two log entries'); expect(logEles.count()).toBe(2, 'should have two log entries');
sendKeys(inputEle, "-test-").then(function() { sendKeys(inputEle, '-test-').then(function() {
return addHeroButtonEle.click(); return addHeroButtonEle.click();
}).then(function() { }).then(function() {
expect(heroEles.count()).toBe(3, 'should have added one hero'); expect(heroEles.count()).toBe(3, 'should have added one hero');
@ -161,12 +161,12 @@ describe('Lifecycle hooks', function () {
}).then(function() { }).then(function() {
expect(heroEles.count()).toBe(0, 'should no longer have any heroes'); expect(heroEles.count()).toBe(0, 'should no longer have any heroes');
expect(logEles.count()).toBe(7, 'should now have 7 log entries - 3 orig + 1 reset + 3 removeall'); expect(logEles.count()).toBe(7, 'should now have 7 log entries - 3 orig + 1 reset + 3 removeall');
}) });
}); });
it('should support "spy counter"', function () { it('should support "spy counter"', function () {
let updateCounterButtonEle = element(by.cssContainingText('counter-parent button','Update')); let updateCounterButtonEle = element(by.cssContainingText('counter-parent button', 'Update'));
let resetCounterButtonEle = element(by.cssContainingText('counter-parent button','Reset')); let resetCounterButtonEle = element(by.cssContainingText('counter-parent button', 'Reset'));
let textEle = element(by.css('counter-parent my-counter > div')); let textEle = element(by.css('counter-parent my-counter > div'));
let logEles = element.all(by.css('counter-parent h4 ~ div')); let logEles = element.all(by.css('counter-parent h4 ~ div'));
expect(textEle.getText()).toContain('Counter = 0'); expect(textEle.getText()).toContain('Counter = 0');
@ -178,8 +178,6 @@ describe('Lifecycle hooks', function () {
}).then(function() { }).then(function() {
expect(textEle.getText()).toContain('Counter = 0'); expect(textEle.getText()).toContain('Counter = 0');
expect(logEles.count()).toBe(7, 'should now have 7 log entries - 3 prev + 1 reset + 2 destroy + 1 init'); expect(logEles.count()).toBe(7, 'should now have 7 log entries - 3 prev + 1 reset + 2 destroy + 1 init');
}) });
}); });
}); });

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