Merge remote-tracking branch 'origin/master'

# Conflicts:
#	public/docs/ts/latest/guide/_data.json
This commit is contained in:
Zhicheng Wang 2016-06-19 10:17:03 +08:00
commit 0aa207bbac
113 changed files with 2717 additions and 382 deletions

BIN
public/docs/ImageGuide.pdf Normal file

Binary file not shown.

View File

@ -1,6 +1,6 @@
{
"compilerOptions": {
"target": "es5",
"target": "es6",
"module": "commonjs",
"moduleResolution": "node",
"sourceMap": true,

View File

@ -1,9 +1,8 @@
{
"globalDependencies": {
"angular-protractor": "registry:dt/angular-protractor#1.5.0+20160425143459",
"core-js": "registry:dt/core-js#0.0.0+20160317120654",
"jasmine": "registry:dt/jasmine#2.2.0+20160505161446",
"node": "registry:dt/node#4.0.0+20160509154515",
"node": "registry:dt/node#6.0.0+20160613154055",
"selenium-webdriver": "registry:dt/selenium-webdriver#2.44.0+20160317120654"
}
}

View File

@ -1,4 +1,5 @@
/// <reference path='../_protractor/e2e.d.ts' />
'use strict';
/**
* The tests here basically just checking that the end styles
* of each animation are in effect.
@ -29,7 +30,7 @@ describe('Animation Tests', () => {
});
it('animates between active and inactive', () => {
addHero();
addInactiveHero();
let li = host.element(by.css('li'));
@ -58,7 +59,7 @@ describe('Animation Tests', () => {
});
it('are not kept after animation', () => {
addHero();
addInactiveHero();
let li = host.element(by.css('li'));
@ -79,7 +80,7 @@ describe('Animation Tests', () => {
});
it('animates between active and inactive', () => {
addHero();
addInactiveHero();
let li = host.element(by.css('li'));
@ -108,7 +109,7 @@ describe('Animation Tests', () => {
});
it('animates between active and inactive', () => {
addHero();
addInactiveHero();
let li = host.element(by.css('li'));
@ -137,7 +138,7 @@ describe('Animation Tests', () => {
});
it('adds and removes element', () => {
addHero();
addInactiveHero();
let li = host.element(by.css('li'));
expect(li.getCssValue('transform')).toMatch(NO_TRANSFORM_MATRIX_REGEX);
@ -157,7 +158,7 @@ describe('Animation Tests', () => {
});
it('adds and removes and animates between active and inactive', () => {
addHero();
addInactiveHero();
let li = host.element(by.css('li'));
@ -186,7 +187,7 @@ describe('Animation Tests', () => {
});
it('adds and removes element', () => {
addHero();
addInactiveHero();
let li = host.element(by.css('li'));
expect(li.getCssValue('height')).toBe('50px');
@ -206,7 +207,7 @@ describe('Animation Tests', () => {
});
it('adds and removes element', () => {
addHero();
addInactiveHero();
let li = host.element(by.css('li'));
expect(li.getCssValue('transform')).toMatch(NO_TRANSFORM_MATRIX_REGEX);
@ -227,7 +228,7 @@ describe('Animation Tests', () => {
});
it('adds and removes element', () => {
addHero();
addInactiveHero();
let li = host.element(by.css('li'));
expect(li.getCssValue('transform')).toMatch(NO_TRANSFORM_MATRIX_REGEX);
@ -248,7 +249,7 @@ describe('Animation Tests', () => {
});
it('adds and removes element', () => {
addHero();
addInactiveHero();
let li = host.element(by.css('li'));
expect(li.getCssValue('transform')).toMatch(NO_TRANSFORM_MATRIX_REGEX);
@ -260,8 +261,41 @@ describe('Animation Tests', () => {
});
function addHero() {
element(by.buttonText('Add hero')).click();
describe('adding active heroes', () => {
let host: protractor.ElementFinder;
beforeEach(() => {
host = element(by.css('hero-list-basic'));
});
it('animates between active and inactive', () => {
addActiveHero();
let li = host.element(by.css('li'));
expect(getScaleX(li)).toBe(1.1);
expect(li.getCssValue('backgroundColor')).toBe(ACTIVE_COLOR);
li.click();
browser.driver.sleep(300);
expect(getScaleX(li)).toBe(1.0);
expect(li.getCssValue('backgroundColor')).toBe(INACTIVE_COLOR);
li.click();
browser.driver.sleep(300);
expect(getScaleX(li)).toBe(1.1);
expect(li.getCssValue('backgroundColor')).toBe(ACTIVE_COLOR);
});
});
function addActiveHero() {
element(by.buttonText('Add active hero')).click();
browser.driver.sleep(500);
}
function addInactiveHero() {
element(by.buttonText('Add inactive hero')).click();
browser.driver.sleep(500);
}
@ -274,7 +308,9 @@ describe('Animation Tests', () => {
return protractor.promise.all([
getBoundingClientWidth(el),
getOffsetWidth(el)
]).then(function([clientWidth, offsetWidth]) {
]).then(function(promiseResolutions) {
let clientWidth = promiseResolutions[0];
let offsetWidth = promiseResolutions[1];
return clientWidth / offsetWidth;
});
}

View File

@ -16,7 +16,8 @@ import { HeroListTimingsComponent } from './hero-list-timings.component';
selector: 'hero-team-builder',
template: `
<div class="buttons">
<button [disabled]="!heroes.canAdd()" (click)="heroes.add()">Add hero</button>
<button [disabled]="!heroes.canAdd()" (click)="heroes.addInactive()">Add inactive hero</button>
<button [disabled]="!heroes.canAdd()" (click)="heroes.addActive()">Add active hero</button>
<button [disabled]="!heroes.canRemove()" (click)="heroes.remove()">Remove hero</button>
</div>
<div class="columns">

View File

@ -11,19 +11,17 @@ class Hero {
}
let ALL_HEROES = [
'Wolverine',
'Magneto',
'Emma Frost',
'Thing',
'Kitty Pryde',
'Nightcrawler',
'Juggernaut',
'Beast',
'Captain America',
'Spider-Man',
'Puck',
'Alex Wilder',
'Doctor Strange'
'Windstorm',
'RubberMan',
'Bombasto',
'Magneta',
'Dynama',
'Narco',
'Celeritas',
'Dr IQ',
'Magma',
'Tornado',
'Mr. Nice'
].map(name => new Hero(name));
@Injectable()
@ -43,8 +41,16 @@ export class Heroes implements Iterable<Hero> {
return this.currentHeroes.length > 0;
}
add() {
this.currentHeroes.push(ALL_HEROES[this.currentHeroes.length]);
addActive() {
let hero = ALL_HEROES[this.currentHeroes.length];
hero.state = 'active';
this.currentHeroes.push(hero);
}
addInactive() {
let hero = ALL_HEROES[this.currentHeroes.length];
hero.state = 'inactive';
this.currentHeroes.push(hero);
}
remove() {

View File

@ -1,4 +1,5 @@
/// <reference path='../_protractor/e2e.d.ts' />
'use strict';
describe('Architecture', function () {
let title = 'Hero List';

View File

@ -1,4 +1,5 @@
/// <reference path='../_protractor/e2e.d.ts' />
'use strict';
describe('Attribute directives', function () {
let _title = 'My First Attribute Directive';

View File

@ -1,4 +1,5 @@
/// <reference path='../_protractor/e2e.d.ts' />
'use strict';
describe('Angular 1 to 2 Quick Reference Tests', function () {
beforeAll(function () {

View File

@ -1,4 +1,5 @@
/// <reference path='../_protractor/e2e.d.ts' />
'use strict';
describe('Component Communication Cookbook Tests', function () {

View File

@ -1,4 +1,5 @@
/// <reference path="../_protractor/e2e.d.ts" />
/// <reference path='../_protractor/e2e.d.ts' />
'use strict';
describe('Cookbook: component-relative paths', function () {
interface Page {

View File

@ -1,4 +1,5 @@
/// <reference path="../_protractor/e2e.d.ts" />
/// <reference path='../_protractor/e2e.d.ts' />
'use strict';
describe('Dependency Injection Cookbook', function () {
beforeAll(function () {

View File

@ -1,4 +1,5 @@
/// <reference path="../_protractor/e2e.d.ts" />
/// <reference path='../_protractor/e2e.d.ts' />
'use strict';
/* tslint:disable:quotemark */
describe('Dynamic Form', function () {

View File

@ -1,4 +1,5 @@
/// <reference path="../_protractor/e2e.d.ts" />
/// <reference path='../_protractor/e2e.d.ts' />
'use strict';
// gulp run-e2e-tests --filter=cb-set-document-title
describe('Set Document Title', function () {

View File

@ -1,4 +1,5 @@
/// <reference path="../_protractor/e2e.d.ts" />
/// <reference path='../_protractor/e2e.d.ts' />
'use strict';
describe('TypeScript to Javascript tests', function () {
beforeAll(function () {

View File

@ -1,4 +1,5 @@
/// <reference path="../_protractor/e2e.d.ts" />
/// <reference path='../_protractor/e2e.d.ts' />
'use strict';
describe('cli-quickstart App', () => {
beforeEach(() => {
return browser.get('/');

View File

@ -1,4 +1,5 @@
/// <reference path="../_protractor/e2e.d.ts" />
/// <reference path='../_protractor/e2e.d.ts' />
'use strict';
describe('Component Style Tests', function () {
beforeAll(function () {

View File

@ -1,4 +1,5 @@
/// <reference path="../_protractor/e2e.d.ts" />
/// <reference path='../_protractor/e2e.d.ts' />
'use strict';
describe('Dependency Injection Tests', function () {

View File

@ -1,4 +1,5 @@
/// <reference path='../_protractor/e2e.d.ts' />
'use strict';
describe('Displaying Data Tests', function () {
let _title = 'Tour of Heroes';
let _defaultHero = 'Windstorm';

View File

@ -1,4 +1,5 @@
/// <reference path="../_protractor/e2e.d.ts" />
/// <reference path='../_protractor/e2e.d.ts' />
'use strict';
describeIf(browser.appIsTs || browser.appIsJs, 'Forms Tests', function () {
beforeEach(function () {

View File

@ -1,4 +1,5 @@
/// <reference path="../_protractor/e2e.d.ts" />
/// <reference path='../_protractor/e2e.d.ts' />
'use strict';
describe('Hierarchical dependency injection', function () {
beforeEach(function () {

View File

@ -1,4 +1,5 @@
/// <reference path="../_protractor/e2e.d.ts" />
/// <reference path='../_protractor/e2e.d.ts' />
'use strict';
describe('Homepage Hello World', function () {
beforeAll(function () {

View File

@ -1,4 +1,5 @@
/// <reference path="../_protractor/e2e.d.ts" />
/// <reference path='../_protractor/e2e.d.ts' />
'use strict';
describe('Homepage Tabs', function () {
beforeAll(function () {

View File

@ -1,4 +1,5 @@
/// <reference path="../_protractor/e2e.d.ts" />
/// <reference path='../_protractor/e2e.d.ts' />
'use strict';
describe('Homepage Todo', function () {
beforeAll(function () {

View File

@ -1,4 +1,5 @@
/// <reference path="../_protractor/e2e.d.ts" />
/// <reference path='../_protractor/e2e.d.ts' />
'use strict';
describe('Lifecycle hooks', function () {
beforeAll(function () {

View File

@ -45,7 +45,7 @@
"devDependencies": {
"angular-cli": "^1.0.0-beta.5",
"canonical-path": "0.0.2",
"concurrently": "^2.0.0",
"concurrently": "^2.1.0",
"css-loader": "^0.23.1",
"extract-text-webpack-plugin": "^1.0.1",
"file-loader": "^0.8.5",
@ -62,7 +62,7 @@
"karma-sourcemap-loader": "^0.3.7",
"karma-webpack": "^1.7.0",
"lite-server": "^2.2.0",
"lodash": "^4.11.1",
"lodash": "^4.13.1",
"null-loader": "^0.1.1",
"phantomjs-prebuilt": "^2.1.7",
"protractor": "^3.3.0",
@ -71,7 +71,7 @@
"style-loader": "^0.13.1",
"ts-loader": "^0.8.2",
"ts-node": "^0.7.3",
"typescript": "^1.8.10",
"typescript": "^1.9.0-dev.20160409",
"typings": "^1.0.4",
"webpack": "^1.13.0",
"webpack-dev-server": "^1.14.1",

View File

@ -1,4 +1,5 @@
/// <reference path="../_protractor/e2e.d.ts" />
/// <reference path='../_protractor/e2e.d.ts' />
'use strict';
describe('Pipes', function () {
beforeAll(function () {

View File

@ -1,4 +1,5 @@
/// <reference path="../_protractor/e2e.d.ts" />
/// <reference path='../_protractor/e2e.d.ts' />
'use strict';
describe('QuickStart E2E Tests', function () {
let expectedMsg = 'My First Angular 2 App';

View File

@ -2,6 +2,6 @@
"globalDependencies": {
"core-js": "registry:dt/core-js#0.0.0+20160317120654",
"jasmine": "registry:dt/jasmine#2.2.0+20160505161446",
"node": "registry:dt/node#4.0.0+20160509154515"
"node": "registry:dt/node#6.0.0+20160613154055"
}
}

View File

@ -1,4 +1,5 @@
/// <reference path="../_protractor/e2e.d.ts" />
/// <reference path='../_protractor/e2e.d.ts' />
'use strict';
describe('Router', function () {
beforeAll(function () {

View File

@ -1,4 +1,5 @@
/// <reference path="../_protractor/e2e.d.ts" />
/// <reference path='../_protractor/e2e.d.ts' />
'use strict';
describe('Router', function () {
beforeAll(function () {

View File

@ -1,16 +1,14 @@
/* First version */
// #docplaster
// #docregion
import { Component } from '@angular/core';
import { ROUTER_DIRECTIVES, Routes } from '@angular/router';
import { CrisisListComponent } from './crisis-list.component';
import { HeroListComponent } from './hero-list.component';
// #docregion import-router
import { ROUTER_DIRECTIVES } from '@angular/router';
// #enddocregion import-router
@Component({
selector: 'my-app',
// #docregion template
// #docregion template
template: `
<h1>Component Router</h1>
<nav>
@ -19,24 +17,10 @@ import { HeroListComponent } from './hero-list.component';
</nav>
<router-outlet></router-outlet>
`,
// #enddocregion template
// #enddocregion template
// #docregion directives
directives: [ROUTER_DIRECTIVES]
// #enddocregion directives
})
// #enddocregion
/*
// #docregion route-config
@Component({ ... })
// #enddocregion route-config
*/
// #docregion
// #docregion route-config
@Routes([
// #docregion route-defs
{path: '/crisis-center', component: CrisisListComponent},
{path: '/heroes', component: HeroListComponent},
{path: '*', component: CrisisListComponent}
// #enddocregion route-defs
])
export class AppComponent { }
// #enddocregion route-config
// #enddocregion

View File

@ -2,10 +2,9 @@
// #docplaster
// #docregion
import { Component, OnInit } from '@angular/core';
import { Router, ROUTER_DIRECTIVES, Routes } from '@angular/router';
import { Component } from '@angular/core';
import { Router, ROUTER_DIRECTIVES } from '@angular/router';
import { CrisisListComponent } from './crisis-list.component';
// #enddocregion
/*
// Apparent Milestone 2 imports
@ -18,8 +17,6 @@ import { CrisisListComponent } from './crisis-list.component';
// #enddocregion
*/
// Actual Milestone 2 imports
import { HeroDetailComponent } from './heroes/hero-detail.component.1';
import { HeroListComponent } from './heroes/hero-list.component.1';
import { HeroService } from './heroes/hero.service';
// #docregion
@ -37,28 +34,7 @@ import { HeroService } from './heroes/hero.service';
directives: [ROUTER_DIRECTIVES]
})
// #enddocregion
/*
// #docregion route-config
@Component({ ... })
// #enddocregion route-config
*/
// #docregion
// #docregion route-config
@Routes([
// #docregion route-defs
{path: '/crisis-center', component: CrisisListComponent},
{path: '/heroes', component: HeroListComponent},
// #docregion hero-detail-route
{path: '/hero/:id', component: HeroDetailComponent}
// #enddocregion hero-detail-route
// #enddocregion route-defs
])
export class AppComponent implements OnInit {
constructor(private router: Router) {}
ngOnInit() {
this.router.navigate(['/crisis-center']);
}
export class AppComponent {
}
// #enddocregion route-config
// #enddocregion

View File

@ -1,63 +1,49 @@
/* tslint:disable:no-unused-variable */
// #docplaster
import { Component, OnInit } from '@angular/core';
import { Router, ROUTER_DIRECTIVES, Routes } from '@angular/router';
import { Component } from '@angular/core';
import { Router, ROUTER_DIRECTIVES } from '@angular/router';
import { CrisisCenterComponent } from './crisis-center/crisis-center.component.1';
import { HeroDetailComponent } from './heroes/hero-detail.component.1';
import { HeroListComponent } from './heroes/hero-list.component.1';
import { DialogService } from './dialog.service';
import { HeroService } from './heroes/hero.service';
@Component({
selector: 'my-app',
// #enddocregion
/* Typical link
// #docregion h-anchor
<a [routerLink]="['/heroes']">Heroes</a>
// #enddocregion h-anchor
*/
// #docregion h-anchor
<a [routerLink]="['/heroes']">Heroes</a>
// #enddocregion h-anchor
*/
/* Incomplete Crisis Center link when CC lacks a default
// #docregion cc-anchor-fail
// The link now fails with a "non-terminal link" error
// #docregion cc-anchor-w-default
<a [routerLink]="['/crisis-center']">Crisis Center</a>
// #enddocregion cc-anchor-w-default
// #enddocregion cc-anchor-fail
*/
// #docregion cc-anchor-fail
// The link now fails with a "non-terminal link" error
// #docregion cc-anchor-w-default
<a [routerLink]="['/crisis-center']">Crisis Center</a>
// #enddocregion cc-anchor-w-default
// #enddocregion cc-anchor-fail
*/
/* Crisis Center link when CC lacks a default
// #docregion cc-anchor-no-default
<a [routerLink]="['/crisis-center/']">Crisis Center</a>
// #enddocregion cc-anchor-no-default
*/
// #docregion cc-anchor-no-default
<a [routerLink]="['/crisis-center/']">Crisis Center</a>
// #enddocregion cc-anchor-no-default
*/
/* Crisis Center Detail link
// #docregion Dragon-anchor
<a [routerLink]="['/crisis-center/1']">Dragon Crisis</a>
// #enddocregion Dragon-anchor
*/
// #docregion Dragon-anchor
<a [routerLink]="['/crisis-center/1']">Dragon Crisis</a>
// #enddocregion Dragon-anchor
*/
// #docregion template
template: `
<h1 class="title">Component Router</h1>
<nav>
<a [routerLink]="['/crisis-center']">Crisis Center</a>
<a [routerLink]="['/crisis-center', 1]">Dragon Crisis</a>
<a [routerLink]="['/crisis-center', 2]">Shark Crisis</a>
<a [routerLink]="['/crisis-center/1']">Dragon Crisis</a>
<a [routerLink]="['/crisis-center/2']">Shark Crisis</a>
</nav>
<router-outlet></router-outlet>
`,
// #enddocregion template
providers: [DialogService, HeroService],
providers: [HeroService],
directives: [ROUTER_DIRECTIVES]
})
@Routes([
{path: '/crisis-center', component: CrisisCenterComponent},
{path: '*', component: CrisisCenterComponent}
])
export class AppComponent implements OnInit {
constructor(private router: Router) {}
ngOnInit() {
this.router.navigate(['/crisis-center']);
}
export class AppComponent {
}

View File

@ -0,0 +1,28 @@
// #docregion
import { Component } from '@angular/core';
import { ROUTER_DIRECTIVES } from '@angular/router';
import { DialogService } from './dialog.service';
import { HeroService } from './heroes/hero.service';
@Component({
selector: 'my-app',
// #docregion template
template: `
<h1 class="title">Component Router</h1>
<nav>
<a [routerLink]="['/crisis-center']">Crisis Center</a>
<a [routerLink]="['/heroes']">Heroes</a>
<a [routerLink]="['/crisis-center/admin']">Crisis Admin</a>
</nav>
<router-outlet></router-outlet>
`,
// #enddocregion template
providers: [
HeroService,
DialogService
],
directives: [ROUTER_DIRECTIVES]
})
export class AppComponent {
}

View File

@ -0,0 +1,42 @@
// #docplaster
// #docregion
import { Component } from '@angular/core';
import { provideRouter, ROUTER_DIRECTIVES } from '@angular/router';
import { routes } from './app.routes';
// #docregion can-deactivate-guard
import { CanDeactivateGuard } from './interfaces';
// #enddocregion can-deactivate-guard
import { DialogService } from './dialog.service';
import { HeroService } from './heroes/hero.service';
// Add these symbols to override the `LocationStrategy`
import { LocationStrategy,
HashLocationStrategy } from '@angular/common';
@Component({
selector: 'my-app',
// #docregion template
template: `
<h1 class="title">Component Router</h1>
<nav>
<a [routerLink]="['/crisis-center']">Crisis Center</a>
<a [routerLink]="['/heroes']">Heroes</a>
</nav>
<router-outlet></router-outlet>
`,
// #enddocregion template
providers: [
HeroService,
DialogService,
provideRouter(routes),
CanDeactivateGuard,
{ provide: LocationStrategy,
useClass: HashLocationStrategy } // .../#/crisis-center/
],
directives: [ROUTER_DIRECTIVES]
})
export class AppComponent {
}

View File

@ -1,41 +1,30 @@
// #docplaster
// #docregion
import { Component, OnInit } from '@angular/core';
import { Routes, Router, ROUTER_DIRECTIVES } from '@angular/router';
import { Component } from '@angular/core';
import { ROUTER_DIRECTIVES } from '@angular/router';
import { CrisisCenterComponent } from './crisis-center/crisis-center.component';
import { HeroListComponent } from './heroes/hero-list.component';
import { HeroDetailComponent } from './heroes/hero-detail.component';
import { DialogService } from './dialog.service';
import { HeroService } from './heroes/hero.service';
import { DialogService } from './dialog.service';
import { HeroService } from './heroes/hero.service';
@Component({
selector: 'my-app',
// #docregion template
// #docregion template
template: `
<h1 class="title">Component Router</h1>
<nav>
<a [routerLink]="['/crisis-center']">Crisis Center</a>
<a [routerLink]="['/heroes']">Heroes</a>
<a [routerLink]="['/crisis-center/admin']">Crisis Admin</a>
<a [routerLink]="['/login']">Login</a>
</nav>
<router-outlet></router-outlet>
`,
// #enddocregion template
providers: [DialogService, HeroService],
// #enddocregion template
providers: [
HeroService,
DialogService
],
directives: [ROUTER_DIRECTIVES]
})
// #docregion routes
@Routes([
{path: '/crisis-center', component: CrisisCenterComponent},
{path: '/heroes', component: HeroListComponent},
{path: '/hero/:id', component: HeroDetailComponent},
])
// #enddocregion routes
export class AppComponent implements OnInit {
constructor(private router: Router) {}
ngOnInit() {
this.router.navigate(['/crisis-center']);
}
export class AppComponent {
}

View File

@ -0,0 +1,31 @@
// #docplaster
// #docregion
// #docregion route-config
import { provideRouter, RouterConfig } from '@angular/router';
// #enddocregion route-config
// #enddocregion
// #docregion base-routes
import { HeroListComponent } from './hero-list.component';
import { CrisisCenterComponent } from './crisis-center/crisis-center.component';
import { HeroDetailComponent } from './heroes/hero-detail.component';
// #enddocregion base-routes
// #docregion
// #docregion route-config
export const routes: RouterConfig = [
// #docregion route-defs
{ path: '/crisis-center', component: CrisisCenterComponent },
{ path: '/heroes', component: HeroListComponent },
// #enddocregion route-defs
// #docregion hero-detail-route
{ path: '/hero/:id', component: HeroDetailComponent }
// #enddocregion hero-detail-route
];
export const APP_ROUTER_PROVIDERS = [
provideRouter(routes)
];
// #enddocregion route-config
// #enddocregion

View File

@ -0,0 +1,19 @@
// #docplaster
// #docregion
// #docregion route-config
import { provideRouter, RouterConfig } from '@angular/router';
// #enddocregion route-config
import { CrisisListComponent } from './crisis-list.component';
import { HeroListComponent } from './hero-list.component';
// #docregion route-config
export const routes: RouterConfig = [
{ path: '/crisis-center', component: CrisisListComponent },
{ path: '/heroes', component: HeroListComponent }
];
export const APP_ROUTER_PROVIDERS = [
provideRouter(routes)
];
// #enddocregion route-config

View File

@ -0,0 +1,15 @@
// #docplaster
// #docregion
import { provideRouter } from '@angular/router';
import { CrisisListComponent } from './crisis-center/crisis-list.component';
import { HeroesRoutes } from './heroes/heroes.routes';
export const routes = [
...HeroesRoutes,
{ path: '/crisis-center', component: CrisisListComponent }
];
export const APP_ROUTER_PROVIDERS = [
provideRouter(routes)
];

View File

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

View File

@ -0,0 +1,19 @@
// #docregion
import { provideRouter, RouterConfig } from '@angular/router';
import { CrisisCenterRoutes } from './crisis-center/crisis-center.routes';
import { HeroesRoutes } from './heroes/heroes.routes';
import { LoginRoutes,
AUTH_PROVIDERS } from './login.routes';
export const routes: RouterConfig = [
...HeroesRoutes,
...LoginRoutes,
...CrisisCenterRoutes
];
export const APP_ROUTER_PROVIDERS = [
provideRouter(routes),
AUTH_PROVIDERS
];

View File

@ -0,0 +1,22 @@
// #docregion
import { provideRouter, RouterConfig } from '@angular/router';
import { CrisisCenterRoutes } from './crisis-center/crisis-center.routes';
import { HeroesRoutes } from './heroes/heroes.routes';
import { LoginRoutes,
AUTH_PROVIDERS } from './login.routes';
import { CanDeactivateGuard } from './interfaces';
export const routes: RouterConfig = [
...HeroesRoutes,
...LoginRoutes,
...CrisisCenterRoutes
];
export const APP_ROUTER_PROVIDERS = [
provideRouter(routes),
AUTH_PROVIDERS,
CanDeactivateGuard
];

View File

@ -0,0 +1,9 @@
// #docregion
import { CanActivate } from '@angular/router';
export class AuthGuard implements CanActivate {
canActivate() {
console.log('AuthGuard#canActivate called');
return true;
}
}

View File

@ -0,0 +1,22 @@
// #docregion
import { Injectable } from '@angular/core';
import { CanActivate,
Router,
ActivatedRouteSnapshot,
RouterStateSnapshot } from '@angular/router';
import { AuthService } from './auth.service';
@Injectable()
export class AuthGuard implements CanActivate {
constructor(private authService: AuthService, private router: Router) {}
canActivate(
// Not using but worth knowing about
next: ActivatedRouteSnapshot,
state: RouterStateSnapshot
) {
if (this.authService.isLoggedIn) { return true; }
this.router.navigate(['/login']);
return false;
}
}

View File

@ -0,0 +1,20 @@
// #docregion
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/observable/of';
import 'rxjs/add/operator/do';
import 'rxjs/add/operator/delay';
@Injectable()
export class AuthService {
isLoggedIn: boolean = false;
login() {
return Observable.of(true).delay(1000).do(val => this.isLoggedIn = true);
}
logout() {
this.isLoggedIn = false;
}
}

View File

@ -0,0 +1,13 @@
// #docregion
import { Component } from '@angular/core';
import { ROUTER_DIRECTIVES } from '@angular/router';
@Component({
template: `
<h3>CRISIS ADMINISTRATION</h3>
<p>Manage your crises here</p>
`,
directives: [ROUTER_DIRECTIVES]
})
export class CrisisAdminComponent { }

View File

@ -1,9 +1,7 @@
import { Component } from '@angular/core';
import { ROUTER_DIRECTIVES, Routes } from '@angular/router';
import { Component } from '@angular/core';
import { ROUTER_DIRECTIVES } from '@angular/router';
import { CrisisDetailComponent } from './crisis-detail.component.1';
import { CrisisListComponent } from './crisis-list.component.1';
import { CrisisService } from './crisis.service';
import { CrisisService } from './crisis.service';
// #docregion minus-imports
@Component({
@ -16,13 +14,5 @@ import { CrisisService } from './crisis.service';
providers: [CrisisService]
// #enddocregion providers
})
// #docregion route-config
@Routes([
// #docregion default-route
{path: '/', component: CrisisListComponent}, // , useAsDefault: true}, // coming soon
// #enddocregion default-route
{path: '/:id', component: CrisisDetailComponent}
])
// #enddocregion route-config
export class CrisisCenterComponent { }
// #enddocregion minus-imports

View File

@ -1,10 +1,8 @@
// #docregion
import { Component } from '@angular/core';
import { ROUTER_DIRECTIVES, Routes } from '@angular/router';
import { Component } from '@angular/core';
import { ROUTER_DIRECTIVES } from '@angular/router';
import { CrisisDetailComponent } from './crisis-detail.component';
import { CrisisListComponent } from './crisis-list.component';
import { CrisisService } from './crisis.service';
import { CrisisService } from './crisis.service';
@Component({
template: `
@ -14,9 +12,5 @@ import { CrisisService } from './crisis.service';
directives: [ROUTER_DIRECTIVES],
providers: [CrisisService]
})
@Routes([
{path: '', component: CrisisListComponent}, // , useAsDefault: true}, // coming soon
{path: '/:id', component: CrisisDetailComponent}
])
export class CrisisCenterComponent { }
// #enddocregion

View File

@ -0,0 +1,18 @@
// #docregion
import { RouterConfig } from '@angular/router';
import { CrisisDetailComponent } from './crisis-detail.component';
import { CrisisListComponent } from './crisis-list.component';
import { CrisisCenterComponent } from './crisis-center.component';
// #docregion routes
export const CrisisCenterRoutes: RouterConfig = [
{
path: '/crisis-center',
component: CrisisCenterComponent,
children: [
{ path: '/', component: CrisisListComponent },
{ path: '/:id', component: CrisisDetailComponent }
]
}
];
// #enddocregion routes

View File

@ -0,0 +1,22 @@
// #docregion
import { RouterConfig } from '@angular/router';
import { CrisisDetailComponent } from './crisis-detail.component';
import { CrisisListComponent } from './crisis-list.component';
import { CrisisCenterComponent } from './crisis-center.component';
// #docregion routes
export const CrisisCenterRoutes: RouterConfig = [
{
path: '/crisis-center',
component: CrisisCenterComponent,
index: true,
children: [
{ path: '/:id', component: CrisisDetailComponent },
{ path: '/', component: CrisisListComponent,
index: true
}
]
}
];
// #enddocregion routes

View File

@ -0,0 +1,48 @@
// #docplaster
// #docregion
import { RouterConfig } from '@angular/router';
import { CrisisDetailComponent } from './crisis-detail.component';
import { CrisisListComponent } from './crisis-list.component';
import { CrisisCenterComponent } from './crisis-center.component';
import { CrisisAdminComponent } from './crisis-admin.component';
import { CanDeactivateGuard } from '../interfaces';
export const CrisisCenterRoutes: RouterConfig = [
{
path: '/crisis-center',
component: CrisisCenterComponent,
index: true,
children: [
// #docregion admin-route-no-guard
{
path: '/admin',
component: CrisisAdminComponent
},
// #enddocregion admin-route-no-guard
{
path: '/:id',
component: CrisisDetailComponent,
canDeactivate: [CanDeactivateGuard]
},
{
path: '/',
component: CrisisListComponent,
index: true
}
]
}
];
// #enddocregion
/*
// #docregion auth-guard
import { AuthGuard } from '../auth.guard';
{
path: '/admin',
component: CrisisAdminComponent,
canActivate: [AuthGuard]
}
// #enddocregion auth-guard
*/

View File

@ -0,0 +1,50 @@
// #docplaster
// #docregion
import { RouterConfig } from '@angular/router';
import { CrisisDetailComponent } from './crisis-detail.component';
import { CrisisListComponent } from './crisis-list.component';
import { CrisisCenterComponent } from './crisis-center.component';
import { CrisisAdminComponent } from './crisis-admin.component';
import { CanDeactivateGuard } from '../interfaces';
import { AuthGuard } from '../auth.guard';
export const CrisisCenterRoutes: RouterConfig = [
{
path: '/crisis-center',
component: CrisisCenterComponent,
index: true,
children: [
{
path: '/admin',
component: CrisisAdminComponent,
canActivate: [AuthGuard]
},
{
path: '/:id',
component: CrisisDetailComponent,
canDeactivate: [CanDeactivateGuard]
},
// #docregion default-route
{
path: '/',
component: CrisisListComponent,
index: true
}
// #enddocregion default-route
]
}
];
// #enddocregion
/*
// #docregion auth-guard
import { AuthGuard } from '../auth.guard';
{
path: '/admin',
component: CrisisAdminComponent,
canActivate: [AuthGuard]
}
// #enddocregion auth-guard
*/

View File

@ -0,0 +1,35 @@
// #docregion
import { RouterConfig } from '@angular/router';
import { CrisisDetailComponent } from './crisis-detail.component';
import { CrisisListComponent } from './crisis-list.component';
import { CrisisCenterComponent } from './crisis-center.component';
import { CrisisAdminComponent } from './crisis-admin.component';
import { CanDeactivateGuard } from '../interfaces';
import { AuthGuard } from '../auth.guard';
export const CrisisCenterRoutes: RouterConfig = [
{
path: '/crisis-center',
component: CrisisCenterComponent,
index: true,
children: [
// #docregion admin-route
{
path: '/admin',
component: CrisisAdminComponent,
canActivate: [AuthGuard]
},
// #enddocregion admin-route
{
path: '/:id',
component: CrisisDetailComponent,
canDeactivate: [CanDeactivateGuard]
},
{ path: '/',
component: CrisisListComponent,
index: true
}
]
}
];

View File

@ -1,14 +1,15 @@
// #docplaster
// #docregion
import { Component } from '@angular/core';
import { OnActivate, Router, RouteSegment } from '@angular/router';
import { Component, OnInit, OnDestroy } from '@angular/core';
import { ActivatedRoute, Router } from '@angular/router';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/observable/fromPromise';
import { Crisis, CrisisService } from './crisis.service';
// #docregion routerCanDeactivate
// import { CanDeactivate } from '@angular/router';
import { DialogService } from '../dialog.service';
// #enddocregion routerCanDeactivate
@Component({
// #docregion template
template: `
@ -29,49 +30,52 @@ import { DialogService } from '../dialog.service';
// #enddocregion template
styles: ['input {width: 20em}']
})
// #docregion routerCanDeactivate, cancel-save
export class CrisisDetailComponent implements OnActivate {// , CanDeactivate {
// #docregion cancel-save
export class CrisisDetailComponent implements OnInit, OnDestroy {
crisis: Crisis;
editName: string;
// #enddocregion ngOnDestroy
private sub: any;
// #enddocregion ngOnDestroy
// #enddocregion routerCanDeactivate, cancel-save
// #enddocregion cancel-save
constructor(
private service: CrisisService,
private router: Router,
private dialog: DialogService
) { }
private route: ActivatedRoute,
private dialogService: DialogService
) { }
// #docregion ngOnActivate
routerOnActivate(curr: RouteSegment): void {
let id = +curr.getParam('id');
this.service.getCrisis(id).then(crisis => {
if (crisis) {
this.editName = crisis.name;
this.crisis = crisis;
} else { // id not found
this.gotoCrises();
}
});
// #docregion ngOnInit
ngOnInit() {
this.sub = this.route
.params
.subscribe(params => {
let id = +params['id'];
this.service.getCrisis(id)
.then(crisis => {
if (crisis) {
this.editName = crisis.name;
this.crisis = crisis;
} else { // id not found
this.gotoCrises();
}
});
});
}
// #enddocregion ngOnActivate
// #enddocregion ngOnInit
// #docregion routerCanDeactivate
// NOT IMPLEMENTED YET
routerCanDeactivate(): any {
// Allow synchronous navigation (`true`) if no crisis or the crisis is unchanged.
if (!this.crisis || this.crisis.name === this.editName) {
return true;
// #enddocregion ngOnDestroy
ngOnDestroy() {
if (this.sub) {
this.sub.unsubscribe();
}
// Otherwise ask the user with the dialog service and return its
// promise which resolves to true or false when the user decides
return this.dialog.confirm('Discard changes?');
}
// #enddocregion routerCanDeactivate
// #enddocregion ngOnDestroy
// #docregion cancel-save
cancel() {
this.editName = this.crisis.name;
this.gotoCrises();
}
@ -81,13 +85,30 @@ export class CrisisDetailComponent implements OnActivate {// , CanDeactivate {
}
// #enddocregion cancel-save
// #docregion cancel-save-only
canDeactivate(): Observable<boolean> | boolean {
// Allow synchronous navigation (`true`) if no crisis or the crisis is unchanged
if (!this.crisis || this.crisis.name === this.editName) {
return true;
}
// Otherwise ask the user with the dialog service and return its
// promise which resolves to true or false when the user decides
let p = this.dialogService.confirm('Discard changes?');
let o = Observable.fromPromise(p);
return o;
}
// #enddocregion cancel-save-only
// #docregion gotoCrises
gotoCrises() {
// Like <a [routerLink]="[/crisis-center/]">Crisis Center</a
this.router.navigateByUrl('/crisis-center/'); // absolute url
let crisisId = this.crisis ? this.crisis.id : null;
// Pass along the hero id if available
// so that the CrisisListComponent can select that hero.
// Add a totally useless `foo` parameter for kicks.
this.router.navigate(['/crisis-center', { id: crisisId, foo: 'foo' }], { relativeTo: this.route });
}
// #enddocregion gotoCrises
// #docregion routerCanDeactivate, cancel-save
// #docregion cancel-save
}
// #enddocregion routerCanDeactivate, cancel-save
// #enddocregion cancel-save
// #enddocregion

View File

@ -1,7 +1,9 @@
// #docplaster
// #docregion
import { Component } from '@angular/core';
import { CanDeactivate, OnActivate, Router, RouteSegment } from '@angular/router';
import { Component, OnInit, OnDestroy } from '@angular/core';
import { Router, ActivatedRoute } from '@angular/router';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/observable/fromPromise';
import { Crisis, CrisisService } from './crisis.service';
import { DialogService } from '../dialog.service';
@ -25,43 +27,42 @@ import { DialogService } from '../dialog.service';
styles: ['input {width: 20em}']
})
export class CrisisDetailComponent implements OnActivate, CanDeactivate {
export class CrisisDetailComponent implements OnInit, OnDestroy {
crisis: Crisis;
editName: string;
private curSegment: RouteSegment;
private sub: any;
constructor(
private service: CrisisService,
private route: ActivatedRoute,
private router: Router,
private dialog: DialogService
private dialogService: DialogService
) { }
routerOnActivate(curr: RouteSegment) {
this.curSegment = curr;
let id = +curr.getParam('id');
this.service.getCrisis(id).then(crisis => {
if (crisis) {
this.editName = crisis.name;
this.crisis = crisis;
} else { // id not found
this.gotoCrises();
}
});
ngOnInit() {
this.sub = this.route
.params
.subscribe(params => {
let id = +params['id'];
this.service.getCrisis(id)
.then(crisis => {
if (crisis) {
this.editName = crisis.name;
this.crisis = crisis;
} else { // id not found
this.gotoCrises();
}
});
});
}
routerCanDeactivate(): any {
// Allow synchronous navigation (`true`) if no crisis or the crisis is unchanged.
if (!this.crisis || this.crisis.name === this.editName) {
return true;
ngOnDestroy() {
if (this.sub) {
this.sub.unsubscribe();
}
// Otherwise ask the user with the dialog service and return its
// promise which resolves to true or false when the user decides
return this.dialog.confirm('Discard changes?');
}
cancel() {
this.editName = this.crisis.name;
this.gotoCrises();
}
@ -70,6 +71,18 @@ export class CrisisDetailComponent implements OnActivate, CanDeactivate {
this.gotoCrises();
}
canDeactivate(): Observable<boolean> | boolean {
// Allow synchronous navigation (`true`) if no crisis or the crisis is unchanged
if (!this.crisis || this.crisis.name === this.editName) {
return true;
}
// Otherwise ask the user with the dialog service and return its
// promise which resolves to true or false when the user decides
let p = this.dialogService.confirm('Discard changes?');
let o = Observable.fromPromise(p);
return o;
}
// #docregion gotoCrises
gotoCrises() {
let crisisId = this.crisis ? this.crisis.id : null;
@ -79,9 +92,6 @@ export class CrisisDetailComponent implements OnActivate, CanDeactivate {
// #docregion gotoCrises-navigate
// Absolute link
this.router.navigate(['/crisis-center', {id: crisisId, foo: 'foo'}]);
// Relative link
// this.router.navigate(['../', {id: crisisId, foo: 'foo'}], this.curSegment);
// #enddocregion gotoCrises-navigate
}
// #enddocregion gotoCrises

View File

@ -1,7 +1,7 @@
// #docplaster
// #docregion
import { Component } from '@angular/core';
import { OnActivate, Router, RouteSegment } from '@angular/router';
import { Component, OnInit, OnDestroy } from '@angular/core';
import { ActivatedRoute, Router } from '@angular/router';
import { Crisis, CrisisService } from './crisis.service';
@ -17,20 +17,34 @@ import { Crisis, CrisisService } from './crisis.service';
`,
// #enddocregion template
})
export class CrisisListComponent implements OnActivate {
export class CrisisListComponent implements OnInit, OnDestroy {
crises: Crisis[];
selectedId: number;
private sub: any;
constructor(
private service: CrisisService,
private route: ActivatedRoute,
private router: Router) {}
routerOnActivate(curr: RouteSegment): void {
this.service.getCrises().then(crises => this.crises = crises);
ngOnInit() {
this.sub = this.route
.params
.subscribe(params => {
this.selectedId = +params['id'];
this.service.getCrises()
.then(crises => this.crises = crises);
});
}
ngOnDestroy() {
this.sub.unsubscribe();
}
// #docregion select
onSelect(crisis: Crisis) {
this.router.navigateByUrl( `/crisis-list/${crisis.id}`);
// Absolute link
this.router.navigate(['/crisis-center', crisis.id]);
}
// #enddocregion select
}

View File

@ -1,7 +1,7 @@
// #docplaster
// #docregion
import { Component } from '@angular/core';
import { OnActivate, Router, RouteSegment, RouteTree } from '@angular/router';
import { Component, OnInit, OnDestroy } from '@angular/core';
import { Router, ActivatedRoute } from '@angular/router';
import { Crisis, CrisisService } from './crisis.service';
@ -16,28 +16,36 @@ import { Crisis, CrisisService } from './crisis.service';
</ul>
`,
})
export class CrisisListComponent implements OnActivate {
export class CrisisListComponent implements OnInit, OnDestroy {
crises: Crisis[];
private currSegment: RouteSegment;
private selectedId: number;
private sub: any;
constructor(
private service: CrisisService,
private route: ActivatedRoute,
private router: Router) { }
isSelected(crisis: Crisis) { return crisis.id === this.selectedId; }
routerOnActivate(curr: RouteSegment, prev: RouteSegment, currTree: RouteTree) {
this.currSegment = curr;
this.selectedId = +currTree.parent(curr).getParam('id');
this.service.getCrises().then(crises => this.crises = crises);
ngOnInit() {
this.sub = this.route
.params
.subscribe(params => {
this.selectedId = +params['id'];
this.service.getCrises()
.then(crises => this.crises = crises);
});
}
ngOnDestroy() {
if (this.sub) {
this.sub.unsubscribe();
}
}
onSelect(crisis: Crisis) {
// Absolute link
// this.router.navigate([`/crisis-center`, crisis.id]);
// Relative link
this.router.navigate([`./${crisis.id}`], this.currSegment);
// Navigate with Absolute link
this.router.navigate(['/crisis-center', crisis.id]);
}
}

View File

@ -1,5 +1,5 @@
// #docplaster
// #docregion
export class Crisis {
constructor(public id: number, public name: string) { }
}
@ -14,7 +14,7 @@ const CRISES = [
let crisesPromise = Promise.resolve(CRISES);
// #docregion
import { Injectable } from '@angular/core';
import {Injectable} from '@angular/core';
@Injectable()
export class CrisisService {

View File

@ -12,7 +12,8 @@ export class DialogService {
* Returns promise resolving to `true`=confirm or `false`=cancel
*/
confirm(message?: string) {
return new Promise<boolean>((resolve, reject) =>
resolve(window.confirm(message || 'Is it OK?')));
return new Promise<boolean>(resolve => {
return resolve(window.confirm(message || 'Is it OK?'));
});
};
}

View File

@ -1,6 +1,7 @@
// #docplaster
// #docregion
import { Component } from '@angular/core';
import { OnActivate, Router, RouteSegment } from '@angular/router';
import { Component, OnInit, OnDestroy } from '@angular/core';
import { Router, ActivatedRoute } from '@angular/router';
import { Hero, HeroService } from './hero.service';
@ -21,26 +22,35 @@ import { Hero, HeroService } from './hero.service';
</div>
`,
})
export class HeroDetailComponent implements OnActivate {
export class HeroDetailComponent implements OnInit, OnDestroy {
hero: Hero;
// #docregion ngOnInit
private sub: any;
// #enddocregion ngOnInit
// #docregion ctor
constructor(
private route: ActivatedRoute,
private router: Router,
private service: HeroService) {}
// #enddocregion ctor
// #docregion OnActivate
routerOnActivate(curr: RouteSegment): void {
let id = +curr.getParam('id');
this.service.getHero(id).then(hero => this.hero = hero);
// #docregion ngOnInit
ngOnInit() {
this.sub = this.route.params.subscribe(params => {
let id = +params['id']; // (+) converts string 'id' to a number
this.service.getHero(id).then(hero => this.hero = hero);
});
}
// #enddocregion OnActivate
// #enddocregion ngOnInit
// #docregion ngOnDestroy
ngOnDestroy() {
this.sub.unsubscribe();
}
// #enddocregion ngOnDestroy
// #docregion gotoHeroes
gotoHeroes() {
// Like <a [routerLink]="['/heroes']">Heroes</a>
this.router.navigate(['/heroes']);
}
gotoHeroes() { this.router.navigate(['/heroes']); }
// #enddocregion gotoHeroes
}

View File

@ -0,0 +1,42 @@
// Snapshot version
// #docregion
import { Component, OnInit } from '@angular/core';
import { ActivatedRoute, Router } from '@angular/router';
import { Hero, HeroService } from './hero.service';
@Component({
template: `
<h2>HEROES</h2>
<div *ngIf="hero">
<h3>"{{hero.name}}"</h3>
<div>
<label>Id: </label>{{hero.id}}</div>
<div>
<label>Name: </label>
<input [(ngModel)]="hero.name" placeholder="name"/>
</div>
<p>
<button (click)="gotoHeroes()">Back</button>
</p>
</div>
`,
})
export class HeroDetailComponent implements OnInit {
hero: Hero;
constructor(
private route: ActivatedRoute,
private router: Router,
private service: HeroService) {}
// #docregion snapshot
ngOnInit() {
// (+) converts string 'id' to a number
let id = +this.route.snapshot.params['id'];
this.service.getHero(id).then(hero => this.hero = hero);
}
// #enddocregion snapshot
gotoHeroes() { this.router.navigate(['/heroes']); }
}

View File

@ -1,6 +1,7 @@
// #docplaster
// #docregion
import { Component } from '@angular/core';
import { OnActivate, Router, RouteSegment } from '@angular/router';
import { Component, OnInit, OnDestroy } from '@angular/core';
import { Router, ActivatedRoute } from '@angular/router';
import { Hero, HeroService } from './hero.service';
@ -21,30 +22,41 @@ import { Hero, HeroService } from './hero.service';
</div>
`,
})
export class HeroDetailComponent implements OnActivate {
export class HeroDetailComponent implements OnInit, OnDestroy {
hero: Hero;
// #docregion ngOnInit
private sub: any;
// #enddocregion ngOnInit
// #docregion ctor
constructor(
private route: ActivatedRoute,
private router: Router,
private service: HeroService) {}
// #enddocregion ctor
// #docregion OnActivate
routerOnActivate(curr: RouteSegment): void {
let id = +curr.getParam('id');
this.service.getHero(id).then(hero => this.hero = hero);
// #docregion ngOnInit
ngOnInit() {
this.sub = this.route.params.subscribe(params => {
let id = +params['id']; // (+) converts string 'id' to a number
this.service.getHero(id).then(hero => this.hero = hero);
});
}
// #enddocregion OnActivate
// #enddocregion ngOnInit
// #docregion ngOnDestroy
ngOnDestroy() {
this.sub.unsubscribe();
}
// #enddocregion ngOnDestroy
// #docregion gotoHeroes-navigate
gotoHeroes() {
let heroId = this.hero ? this.hero.id : null;
// Pass along the hero id if available
// so that the HeroList component can select that hero.
// Add a totally useless `foo` parameter for kicks.
// #docregion gotoHeroes-navigate
this.router.navigate([`/heroes`, {id: heroId, foo: 'foo'}]);
// #enddocregion gotoHeroes-navigate
this.router.navigate(['/heroes'], { queryParams: { id: `${heroId}`, foo: 'foo' } });
}
// #enddocregion gotoHeroes-navigate
}

View File

@ -43,7 +43,7 @@ export class HeroListComponent implements OnInit {
// #enddocregion
/* A link parameters array
// #docregion link-parameters-array
['HeroDetail', { id: hero.id }] // {id: 15}
// #enddocregion link-parameters-array
*/
// #docregion link-parameters-array
['/hero', hero.id] // { 15 }
// #enddocregion link-parameters-array
*/

View File

@ -0,0 +1,64 @@
// #docplaster
// #docregion
// TODO SOMEDAY: Feature Componetized like CrisisCenter
import { Component, OnInit, OnDestroy } from '@angular/core';
// #docregion import-router
import { Router } from '@angular/router';
// #enddocregion import-router
import { Hero, HeroService } from './hero.service';
@Component({
// #docregion template
template: `
<h2>HEROES</h2>
<ul class="items">
<li *ngFor="let hero of heroes"
[class.selected]="isSelected(hero)"
(click)="onSelect(hero)">
<span class="badge">{{hero.id}}</span> {{hero.name}}
</li>
</ul>
`
// #enddocregion template
})
export class HeroListComponent implements OnInit, OnDestroy {
heroes: Hero[];
// #docregion ctor
private selectedId: number;
private sub: any;
constructor(
private service: HeroService,
private router: Router) {}
// #enddocregion ctor
ngOnInit() {
this.sub = this.router
.routerState
.queryParams
.subscribe(params => {
this.selectedId = +params['id'];
this.service.getHeroes()
.then(heroes => this.heroes = heroes);
});
}
ngOnDestroy() {
this.sub.unsubscribe();
}
// #enddocregion ctor
// #docregion isSelected
isSelected(hero: Hero) { return hero.id === this.selectedId; }
// #enddocregion isSelected
// #docregion select
onSelect(hero: Hero) {
this.router.navigate(['/hero', hero.id]);
}
// #enddocregion select
}
// #enddocregion

View File

@ -1,9 +1,9 @@
// #docplaster
// #docregion
// TODO SOMEDAY: Feature Componetized like CrisisCenter
import { Component } from '@angular/core';
import { Component, OnInit, OnDestroy } from '@angular/core';
// #docregion import-router
import { OnActivate, Router, RouteSegment, RouteTree } from '@angular/router';
import { Router } from '@angular/router';
// #enddocregion import-router
import { Hero, HeroService } from './hero.service';
@ -22,22 +22,34 @@ import { Hero, HeroService } from './hero.service';
`
// #enddocregion template
})
export class HeroListComponent implements OnActivate {
export class HeroListComponent implements OnInit, OnDestroy {
heroes: Hero[];
// #docregion ctor
private selectedId: number;
private sub: any;
constructor(
private service: HeroService,
private router: Router) { }
private router: Router) {}
// #enddocregion ctor
routerOnActivate(curr: RouteSegment, prev?: RouteSegment, currTree?: RouteTree, prevTree?: RouteTree): void {
this.selectedId = +curr.getParam('id');
this.service.getHeroes().then(heroes => this.heroes = heroes);
ngOnInit() {
this.sub = this.router
.routerState
.queryParams
.subscribe(params => {
this.selectedId = +params['id'];
this.service.getHeroes()
.then(heroes => this.heroes = heroes);
});
}
ngOnDestroy() {
this.sub.unsubscribe();
}
// #enddocregion ctor
// #docregion isSelected
isSelected(hero: Hero) { return hero.id === this.selectedId; }
// #enddocregion isSelected

View File

@ -0,0 +1,12 @@
// #docregion
import { RouterConfig } from '@angular/router';
import { HeroListComponent } from './hero-list.component';
import { HeroDetailComponent } from './hero-detail.component';
export const HeroesRoutes: RouterConfig = [
{ path: '/heroes', component: HeroListComponent },
// #docregion hero-detail-route
{ path: '/hero/:id', component: HeroDetailComponent }
// #enddocregion hero-detail-route
];
// #enddocregion

View File

@ -0,0 +1,13 @@
// #docregion
import { CanDeactivate } from '@angular/router';
import { Observable } from 'rxjs/Observable';
export interface CanComponentDeactivate {
canDeactivate: () => boolean | Observable<boolean>;
}
export class CanDeactivateGuard implements CanDeactivate<CanComponentDeactivate> {
canDeactivate(component: CanComponentDeactivate): Observable<boolean> | boolean {
return component.canDeactivate ? component.canDeactivate() : true;
}
}

View File

@ -0,0 +1,44 @@
// #docregion
import { Component } from '@angular/core';
import { Router } from '@angular/router';
import { AuthService } from './auth.service';
@Component({
selector: 'login',
template: `
<h2>LOGIN</h2>
<p>{{message}}</p>
<p>
<button (click)="login()" *ngIf="!authService.isLoggedIn">Login</button>
<button (click)="logout()" *ngIf="authService.isLoggedIn">Logout</button>
</p>`
})
export class LoginComponent {
message: string;
constructor(public authService: AuthService, public router: Router) {
this.setMessage();
}
setMessage() {
this.message = 'Logged ' + (this.authService.isLoggedIn ? 'in' : 'out');
}
login() {
this.message = "Trying to log in ...";
this.authService.login().subscribe(() => {
this.setMessage();
if (this.authService.isLoggedIn) {
// Todo: capture where the user was going and nav there.
// Meanwhile redirect the user to the crisis admin
this.router.navigate(['/crisis-center/admin']);
}
});
}
logout() {
this.authService.logout();
this.setMessage();
}
}

View File

@ -0,0 +1,10 @@
// #docregion
import { AuthGuard } from './auth.guard';
import { AuthService } from './auth.service';
import { LoginComponent } from './login.component';
export const LoginRoutes = [
{ path: '/login', component: LoginComponent }
];
export const AUTH_PROVIDERS = [AuthGuard, AuthService];

View File

@ -1,23 +1,25 @@
/* First version */
// #docplaster
// #docregion all
import { bootstrap } from '@angular/platform-browser-dynamic';
import { ROUTER_PROVIDERS } from '@angular/router';
// main entry point
import { bootstrap } from '@angular/platform-browser-dynamic';
import { AppComponent } from './app.component';
import { APP_ROUTER_PROVIDERS } from './app.routes';
import { AppComponent } from './app.component';
// #enddocregion all
// #enddocregion
/* Can't use AppComponent ... but display as if we can
// #docregion all
bootstrap(AppComponent, [
// #enddocregion all
*/
// Actually use the v.1 component
import { AppComponent as ac } from './app.component.1';
import { AppComponent as ac } from './app.component.ts'; // './app.component.1';
bootstrap(ac, [
// #docregion all
ROUTER_PROVIDERS
]);
APP_ROUTER_PROVIDERS
])
.catch(err => console.error(err));
// #enddocregion all

View File

@ -2,30 +2,32 @@
// For Milestone #2
// Also includes digression on HashPathStrategy (not used in the final app)
// #docplaster
// #docregion
// main entry point
import { bootstrap } from '@angular/platform-browser-dynamic';
import { ROUTER_PROVIDERS } from '@angular/router';
// Add these symbols to override the `LocationStrategy`
import { LocationStrategy,
HashLocationStrategy } from '@angular/common';
import { AppComponent } from './app.component';
import { APP_ROUTER_PROVIDERS } from './app.routes';
// #enddocregion
/* Can't use AppComponent ... but display as if we can
// #docregion
bootstrap(AppComponent, [
// #enddocregion
*/
// Actually use the v.2 component
import { AppComponent as ac } from './app.component.2';
import { AppComponent as ac } from './app.component.ts'; // './app.component.2';
bootstrap(ac, [
// #docregion
ROUTER_PROVIDERS,
APP_ROUTER_PROVIDERS,
{ provide: LocationStrategy, useClass: HashLocationStrategy } // .../#/crisis-center/
]);
])
.catch(err => console.error(err));
// #enddocregion

View File

@ -1,7 +1,11 @@
/* third version */
// #docregion
import { bootstrap } from '@angular/platform-browser-dynamic';
import { ROUTER_PROVIDERS } from '@angular/router';
// main entry point
import { bootstrap } from '@angular/platform-browser-dynamic';
import { AppComponent } from './app.component.3';
import { APP_ROUTER_PROVIDERS } from './app.routes';
import { AppComponent } from './app.component.3';
bootstrap(AppComponent, [ROUTER_PROVIDERS]);
bootstrap(AppComponent, [
APP_ROUTER_PROVIDERS
])
.catch(err => console.error(err));

View File

@ -1,7 +1,10 @@
// #docregion
import { bootstrap } from '@angular/platform-browser-dynamic';
import { ROUTER_PROVIDERS } from '@angular/router';
// main entry point
import { bootstrap } from '@angular/platform-browser-dynamic';
import { AppComponent } from './app.component';
import { APP_ROUTER_PROVIDERS } from './app.routes';
import { AppComponent } from './app.component';
bootstrap(AppComponent, [ROUTER_PROVIDERS]);
bootstrap(AppComponent, [
APP_ROUTER_PROVIDERS
])
.catch(err => console.error(err));

View File

@ -3,7 +3,7 @@
<html>
<head>
<!-- #docregion base-href -->
<base href="/">
<base href=".">
<!-- #enddocregion base-href -->
<title>Router Sample v.1</title>
<meta charset="UTF-8">
@ -20,7 +20,7 @@
<script src="systemjs.config.js"></script>
<script>
System.import('app/main.1') // <----- ONLY CHANGE
.then(null, console.error.bind(console));
.catch(function(err){ console.error(err); });
</script>
</head>

View File

@ -2,7 +2,7 @@
<!-- #docregion -->
<html>
<head>
<base href="/">
<base href=".">
<title>Router Sample v.2</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
@ -18,7 +18,7 @@
<script src="systemjs.config.js"></script>
<script>
System.import('app/main.2') // <----- ONLY CHANGE
.then(null, console.error.bind(console));
.catch(function(err){ console.error(err); });
</script>
</head>

View File

@ -2,7 +2,7 @@
<!-- #docregion -->
<html>
<head>
<base href="/">
<base href=".">
<title>Router Sample v.3</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
@ -18,7 +18,7 @@
<script src="systemjs.config.js"></script>
<script>
System.import('app/main.3') // <----- ONLY CHANGE
.then(null, console.error.bind(console));
.catch(function(err){ console.error(err); });
</script>
</head>

View File

@ -4,7 +4,7 @@
<html>
<head>
<!-- Set the base href -->
<base href="/">
<base href=".">
<title>Router Sample</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
@ -19,7 +19,8 @@
<script src="systemjs.config.js"></script>
<script>
System.import('app').catch(function(err){ console.error(err); });
System.import('app')
.catch(function(err){ console.error(err); });
</script>
</head>

View File

@ -3,7 +3,7 @@
"files":[
"!**/*.d.ts",
"!**/*.js",
"!**/*.[1,2,3].*",
"!**/*.[1,2,3,4,5].*",
"!app/crisis-list.component.ts",
"!app/hero-list.component.ts",
"!app/crisis-center/add-crisis.component.ts"

View File

@ -1,4 +1,5 @@
/// <reference path="../_protractor/e2e.d.ts" />
/// <reference path='../_protractor/e2e.d.ts' />
'use strict';
describe('Server Communication', function () {
beforeAll(function () {

View File

@ -1,4 +1,5 @@
/// <reference path="../_protractor/e2e.d.ts" />
/// <reference path='../_protractor/e2e.d.ts' />
'use strict';
describe('Structural Directives', function () {
// tests interact - so we need beforeEach instead of beforeAll

View File

@ -1,4 +1,5 @@
/// <reference path="../_protractor/e2e.d.ts" />
/// <reference path='../_protractor/e2e.d.ts' />
'use strict';
describe('Style Guide', function () {
it('01-01', function () {
browser.get('#/01-01');

View File

@ -1,4 +1,5 @@
/// <reference path="../_protractor/e2e.d.ts" />
/// <reference path='../_protractor/e2e.d.ts' />
'use strict';
describe('Documentation StyleGuide E2E Tests', function() {
let expectedMsg = 'My First Angular 2 App';

View File

@ -48,6 +48,9 @@
// Add package entries for angular packages
ngPackageNames.forEach(setPackageConfig);
// No umd for router yet
packages['@angular/router'] = { main: 'index.js', defaultExtension: 'js' };
var config = {
map: map,
packages: packages

View File

@ -6,16 +6,18 @@
(function(global) {
var ngVer = '@2.0.0-rc.2'; // lock in the angular package version; do not let it float to current!
var routerVer = '@3.0.0-alpha.3'; // lock router version
//map tells the System loader where to look for things
var map = {
'app': 'app',
'@angular': 'https://npmcdn.com/@angular', // sufficient if we didn't pin the version
'@angular/router': 'https://npmcdn.com/@angular/router' + routerVer,
'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',
'typescript': 'https://npmcdn.com/typescript@1.8.10/lib/typescript.js',
'typescript': 'https://npmcdn.com/typescript@1.9.0-dev.20160409/lib/typescript.js',
};
//packages tells the System loader how to load when no filename and/or no extension
@ -32,7 +34,6 @@
'http',
'platform-browser',
'platform-browser-dynamic',
'router',
'router-deprecated',
'upgrade',
];
@ -53,6 +54,9 @@
//packages['@angular/'+pkgName] = { main: 'index.js', defaultExtension: 'js' };
});
// No umd for router yet
packages['@angular/router'] = { main: 'index.js', defaultExtension: 'js' };
var config = {
// DEMO ONLY! REAL CODE SHOULD NOT TRANSPILE IN THE BROWSER
transpiler: 'ts',

View File

@ -1,4 +1,5 @@
/// <reference path="../_protractor/e2e.d.ts" />
/// <reference path='../_protractor/e2e.d.ts' />
'use strict';
// Not yet complete
describe('Template Syntax', function () {

View File

@ -1,7 +1,7 @@
/* tslint:disable:no-unused-variable */
import { AppComponent } from './app.component';
import { By } from '@angular/platform-browser';
import { By } from '@angular/platform-browser';
import { DebugElement } from '@angular/core';
import {

View File

@ -1,4 +1,5 @@
/// <reference path="../_protractor/e2e.d.ts" />
/// <reference path='../_protractor/e2e.d.ts' />
'use strict';
describe('Tutorial part 1', () => {
let expectedH1 = 'Tour of Heroes';

View File

@ -1,4 +1,5 @@
/// <reference path="../_protractor/e2e.d.ts" />
/// <reference path='../_protractor/e2e.d.ts' />
'use strict';
describe('Tutorial', function () {
beforeAll(function () {

View File

@ -1,4 +1,5 @@
/// <reference path='../_protractor/e2e.d.ts' />
'use strict';
describe('TOH Http Chapter', function () {
beforeEach(function () {

View File

@ -2,6 +2,6 @@
"globalDependencies": {
"core-js": "registry:dt/core-js#0.0.0+20160317120654",
"jasmine": "registry:dt/jasmine#2.2.0+20160505161446",
"node": "registry:dt/node#4.0.0+20160509154515"
"node": "registry:dt/node#6.0.0+20160613154055"
}
}

View File

@ -1,4 +1,5 @@
/// <reference path="../_protractor/e2e.d.ts" />
/// <reference path='../_protractor/e2e.d.ts' />
'use strict';
describe('Upgrade Tests', function () {
// Protractor doesn't support the UpgradeAdapter's asynchronous

View File

@ -1,4 +1,4 @@
/// <reference path="../_protractor/e2e.d.ts" />
/// <reference path='../_protractor/e2e.d.ts' />
'use strict';
// Angular E2E Testing Guide:

View File

@ -1,4 +1,4 @@
/// <reference path="../_protractor/e2e.d.ts" />
/// <reference path='../_protractor/e2e.d.ts' />
'use strict';
// Angular E2E Testing Guide:

View File

@ -1,4 +1,4 @@
/// <reference path="../_protractor/e2e.d.ts" />
/// <reference path='../_protractor/e2e.d.ts' />
'use strict';
// Angular E2E Testing Guide:

View File

@ -1,4 +1,5 @@
/// <reference path="../_protractor/e2e.d.ts" />
/// <reference path='../_protractor/e2e.d.ts' />
'use strict';
describe('User Input Tests', function () {
beforeAll(function () {

View File

@ -1,4 +1,5 @@
/// <reference path="../_protractor/e2e.d.ts" />
/// <reference path='../_protractor/e2e.d.ts' />
'use strict';
describe('QuickStart E2E Tests', function () {
let expectedMsg = 'Hello from Angular 2 App with Webpack';

View File

@ -2,6 +2,6 @@
"globalDependencies": {
"core-js": "registry:dt/core-js#0.0.0+20160317120654",
"jasmine": "registry:dt/jasmine#2.2.0+20160505161446",
"node": "registry:dt/node#4.0.0+20160509154515"
"node": "registry:dt/node#6.0.0+20160613154055"
}
}

View File

@ -0,0 +1,10 @@
#sg-images.showcase.shadow-1
header.showcase-header
h2 Images
p.
To maintain visual consistency across documentation chapters, please follow the best
practices for authors outlined in the <a href="/docs/ImageGuide.pdf" target="_blank">Image
Guide</a>.
p.
The browser background template used for outlining screenshots is <a
href="/resources/images/backgrounds/browser-background-template.png" target="_blank">here</a>.

View File

@ -6,5 +6,6 @@
!= partial("_callouts")
!= partial("_tables")
!= partial("_aside")
!= partial("_images")
//!= partial("_jump-nav")

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