docs(router): samples and doc for new router (phase 1)
This commit is contained in:
parent
f513ee83c7
commit
2ccdd867d2
|
@ -25,6 +25,7 @@
|
||||||
"@angular/http": "2.0.0-rc.0",
|
"@angular/http": "2.0.0-rc.0",
|
||||||
"@angular/platform-browser": "2.0.0-rc.0",
|
"@angular/platform-browser": "2.0.0-rc.0",
|
||||||
"@angular/platform-browser-dynamic": "2.0.0-rc.0",
|
"@angular/platform-browser-dynamic": "2.0.0-rc.0",
|
||||||
|
"@angular/router": "2.0.0-rc.0",
|
||||||
"@angular/router-deprecated": "2.0.0-rc.0",
|
"@angular/router-deprecated": "2.0.0-rc.0",
|
||||||
"@angular/upgrade": "2.0.0-rc.0",
|
"@angular/upgrade": "2.0.0-rc.0",
|
||||||
|
|
||||||
|
|
|
@ -7,14 +7,22 @@
|
||||||
},
|
},
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@angular/common": "2.0.0-rc.0",
|
"@angular/common": "2.0.0-rc.0",
|
||||||
"@angular/compiler": "2.0.0-rc.0",
|
"@angular/compiler": "2.0.0-rc.0",
|
||||||
"@angular/core": "2.0.0-rc.0",
|
"@angular/core": "2.0.0-rc.0",
|
||||||
"@angular/platform-browser": "2.0.0-rc.0",
|
"@angular/http": "2.0.0-rc.0",
|
||||||
"@angular/platform-browser-dynamic": "2.0.0-rc.0",
|
"@angular/platform-browser": "2.0.0-rc.0",
|
||||||
|
"@angular/platform-browser-dynamic": "2.0.0-rc.0",
|
||||||
|
"@angular/router": "2.0.0-rc.0",
|
||||||
|
"@angular/router-deprecated": "2.0.0-rc.0",
|
||||||
|
"@angular/upgrade": "2.0.0-rc.0",
|
||||||
|
|
||||||
"reflect-metadata": "0.1.3",
|
"reflect-metadata": "0.1.3",
|
||||||
"rxjs": "5.0.0-beta.6",
|
"rxjs": "5.0.0-beta.6",
|
||||||
"zone.js": "0.6.12"
|
"zone.js": "0.6.12",
|
||||||
|
|
||||||
|
"angular2-in-memory-web-api": "0.0.6",
|
||||||
|
"bootstrap": "^3.3.6"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"concurrently": "^2.0.0",
|
"concurrently": "^2.0.0",
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
"@angular/http": "2.0.0-rc.0",
|
"@angular/http": "2.0.0-rc.0",
|
||||||
"@angular/platform-browser": "2.0.0-rc.0",
|
"@angular/platform-browser": "2.0.0-rc.0",
|
||||||
"@angular/platform-browser-dynamic": "2.0.0-rc.0",
|
"@angular/platform-browser-dynamic": "2.0.0-rc.0",
|
||||||
|
"@angular/router": "2.0.0-rc.0",
|
||||||
"@angular/router-deprecated": "2.0.0-rc.0",
|
"@angular/router-deprecated": "2.0.0-rc.0",
|
||||||
"@angular/upgrade": "2.0.0-rc.0",
|
"@angular/upgrade": "2.0.0-rc.0",
|
||||||
|
|
||||||
|
@ -26,7 +27,7 @@
|
||||||
"rxjs": "5.0.0-beta.6",
|
"rxjs": "5.0.0-beta.6",
|
||||||
"zone.js": "^0.6.12",
|
"zone.js": "^0.6.12",
|
||||||
|
|
||||||
"angular2-in-memory-web-api": "0.0.5",
|
"angular2-in-memory-web-api": "0.0.6",
|
||||||
"bootstrap": "^3.3.6"
|
"bootstrap": "^3.3.6"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
|
|
@ -0,0 +1,122 @@
|
||||||
|
describe('Router', function () {
|
||||||
|
|
||||||
|
beforeAll(function () {
|
||||||
|
browser.get('');
|
||||||
|
});
|
||||||
|
|
||||||
|
function getPageStruct() {
|
||||||
|
hrefEles = element.all(by.css('my-app a'));
|
||||||
|
|
||||||
|
return {
|
||||||
|
hrefs: hrefEles,
|
||||||
|
routerParent: element(by.css('my-app > undefined')),
|
||||||
|
routerTitle: element(by.css('my-app > undefined > h2')),
|
||||||
|
|
||||||
|
crisisHref: hrefEles.get(0),
|
||||||
|
crisisList: element.all(by.css('my-app > undefined > undefined li')),
|
||||||
|
crisisDetail: element(by.css('my-app > undefined > undefined > div')),
|
||||||
|
crisisDetailTitle: element(by.css('my-app > undefined > undefined > div > h3')),
|
||||||
|
|
||||||
|
heroesHref: hrefEles.get(1),
|
||||||
|
heroesList: element.all(by.css('my-app > undefined li')),
|
||||||
|
heroDetail: element(by.css('my-app > undefined > div')),
|
||||||
|
heroDetailTitle: element(by.css('my-app > undefined > div > h3')),
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
it('should be able to see the start screen', function () {
|
||||||
|
var page = getPageStruct();
|
||||||
|
expect(page.hrefs.count()).toEqual(2, 'should be two dashboard choices');
|
||||||
|
expect(page.crisisHref.getText()).toEqual("Crisis Center");
|
||||||
|
expect(page.heroesHref.getText()).toEqual("Heroes");
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should be able to see crises center items', function () {
|
||||||
|
var page = getPageStruct();
|
||||||
|
expect(page.crisisList.count()).toBe(4, "should be 4 crisis center entries at start");
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should be able to see hero items', function () {
|
||||||
|
var page = getPageStruct();
|
||||||
|
page.heroesHref.click().then(function() {
|
||||||
|
expect(page.routerTitle.getText()).toContain('HEROES');
|
||||||
|
expect(page.heroesList.count()).toBe(6, "should be 6 heroes");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should be able to toggle the views', function () {
|
||||||
|
var page = getPageStruct();
|
||||||
|
page.crisisHref.click().then(function() {
|
||||||
|
expect(page.crisisList.count()).toBe(4, "should be 4 crisis center entries");
|
||||||
|
return page.heroesHref.click();
|
||||||
|
}).then(function() {
|
||||||
|
expect(page.heroesList.count()).toBe(6, "should be 6 heroes");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should be able to edit and save details from the crisis center view', function () {
|
||||||
|
crisisCenterEdit(2, true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should be able to edit and cancel details from the crisis center view', function () {
|
||||||
|
crisisCenterEdit(3, false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should be able to edit and save details from the heroes view', function () {
|
||||||
|
var page = getPageStruct();
|
||||||
|
var heroEle, heroText;
|
||||||
|
page.heroesHref.click().then(function() {
|
||||||
|
heroEle = page.heroesList.get(4);
|
||||||
|
return heroEle.getText();
|
||||||
|
}).then(function(text) {
|
||||||
|
expect(text.length).toBeGreaterThan(0, 'should have some text');
|
||||||
|
// remove leading id from text
|
||||||
|
heroText = text.substr(text.indexOf(' ')).trim();
|
||||||
|
return heroEle.click();
|
||||||
|
}).then(function() {
|
||||||
|
expect(page.heroesList.count()).toBe(0, "should no longer see crisis center entries");
|
||||||
|
expect(page.heroDetail.isPresent()).toBe(true, 'should be able to see crisis detail');
|
||||||
|
expect(page.heroDetailTitle.getText()).toContain(heroText);
|
||||||
|
var inputEle = page.heroDetail.element(by.css('input'));
|
||||||
|
return sendKeys(inputEle, '-foo');
|
||||||
|
}).then(function() {
|
||||||
|
expect(page.heroDetailTitle.getText()).toContain(heroText + '-foo');
|
||||||
|
var buttonEle = page.heroDetail.element(by.css('button'));
|
||||||
|
return buttonEle.click();
|
||||||
|
}).then(function() {
|
||||||
|
expect(heroEle.getText()).toContain(heroText + '-foo');
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
|
function crisisCenterEdit(index, shouldSave) {
|
||||||
|
var page = getPageStruct();
|
||||||
|
var crisisEle, crisisText;
|
||||||
|
page.crisisHref.click().then(function () {
|
||||||
|
crisisEle = page.crisisList.get(index);
|
||||||
|
return crisisEle.getText();
|
||||||
|
}).then(function (text) {
|
||||||
|
expect(text.length).toBeGreaterThan(0, 'should have some text');
|
||||||
|
// remove leading id from text
|
||||||
|
crisisText = text.substr(text.indexOf(' ')).trim();
|
||||||
|
return crisisEle.click();
|
||||||
|
}).then(function () {
|
||||||
|
expect(page.crisisList.count()).toBe(0, "should no longer see crisis center entries");
|
||||||
|
expect(page.crisisDetail.isPresent()).toBe(true, 'should be able to see crisis detail');
|
||||||
|
expect(page.crisisDetailTitle.getText()).toContain(crisisText);
|
||||||
|
var inputEle = page.crisisDetail.element(by.css('input'));
|
||||||
|
return sendKeys(inputEle, '-foo');
|
||||||
|
}).then(function () {
|
||||||
|
expect(page.crisisDetailTitle.getText()).toContain(crisisText + '-foo');
|
||||||
|
var buttonEle = page.crisisDetail.element(by.cssContainingText('button', shouldSave ? 'Save' : 'Cancel'));
|
||||||
|
return buttonEle.click();
|
||||||
|
}).then(function () {
|
||||||
|
if (shouldSave) {
|
||||||
|
expect(crisisEle.getText()).toContain(crisisText + '-foo');
|
||||||
|
} else {
|
||||||
|
expect(crisisEle.getText()).not.toContain(crisisText + '-foo');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
|
@ -0,0 +1,43 @@
|
||||||
|
/* First version */
|
||||||
|
// #docplaster
|
||||||
|
|
||||||
|
// #docregion
|
||||||
|
import { Component } from '@angular/core';
|
||||||
|
// #docregion import-router
|
||||||
|
import { RouteConfig, ROUTER_DIRECTIVES } from '@angular/router-deprecated';
|
||||||
|
// #enddocregion import-router
|
||||||
|
|
||||||
|
import { CrisisListComponent } from './crisis-list.component';
|
||||||
|
import { HeroListComponent } from './hero-list.component';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'my-app',
|
||||||
|
// #docregion template
|
||||||
|
template: `
|
||||||
|
<h1>Component Router</h1>
|
||||||
|
<nav>
|
||||||
|
<a [routerLink]="['CrisisCenter']">Crisis Center</a>
|
||||||
|
<a [routerLink]="['Heroes']">Heroes</a>
|
||||||
|
</nav>
|
||||||
|
<router-outlet></router-outlet>
|
||||||
|
`,
|
||||||
|
// #enddocregion template
|
||||||
|
directives: [ROUTER_DIRECTIVES]
|
||||||
|
})
|
||||||
|
// #enddocregion
|
||||||
|
/*
|
||||||
|
// #docregion route-config
|
||||||
|
@Component({ ... })
|
||||||
|
// #enddocregion route-config
|
||||||
|
*/
|
||||||
|
// #docregion
|
||||||
|
// #docregion route-config
|
||||||
|
@RouteConfig([
|
||||||
|
// #docregion route-defs
|
||||||
|
{path: '/crisis-center', name: 'CrisisCenter', component: CrisisListComponent},
|
||||||
|
{path: '/heroes', name: 'Heroes', component: HeroListComponent}
|
||||||
|
// #enddocregion route-defs
|
||||||
|
])
|
||||||
|
export class AppComponent { }
|
||||||
|
// #enddocregion route-config
|
||||||
|
// #enddocregion
|
|
@ -0,0 +1,58 @@
|
||||||
|
/* Second Heroes version */
|
||||||
|
// #docplaster
|
||||||
|
|
||||||
|
// #docregion
|
||||||
|
import {Component} from '@angular/core';
|
||||||
|
import {RouteConfig, ROUTER_DIRECTIVES} from '@angular/router-deprecated';
|
||||||
|
|
||||||
|
import {CrisisListComponent} from './crisis-list.component';
|
||||||
|
// #enddocregion
|
||||||
|
/*
|
||||||
|
// Apparent Milestone 2 imports
|
||||||
|
// #docregion
|
||||||
|
// #docregion hero-import
|
||||||
|
import {HeroListComponent} from './heroes/hero-list.component';
|
||||||
|
import {HeroDetailComponent} from './heroes/hero-detail.component';
|
||||||
|
import {HeroService} from './heroes/hero.service';
|
||||||
|
// #enddocregion hero-import
|
||||||
|
// #enddocregion
|
||||||
|
*/
|
||||||
|
// Actual Milestone 2 imports
|
||||||
|
import {HeroListComponent} from './heroes/hero-list.component.1';
|
||||||
|
import {HeroDetailComponent} from './heroes/hero-detail.component.1';
|
||||||
|
import {HeroService} from './heroes/hero.service';
|
||||||
|
// #docregion
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'my-app',
|
||||||
|
template: `
|
||||||
|
<h1>Component Router</h1>
|
||||||
|
<nav>
|
||||||
|
<a [routerLink]="['CrisisCenter']">Crisis Center</a>
|
||||||
|
<a [routerLink]="['Heroes']">Heroes</a>
|
||||||
|
</nav>
|
||||||
|
<router-outlet></router-outlet>
|
||||||
|
`,
|
||||||
|
providers: [HeroService],
|
||||||
|
directives: [ROUTER_DIRECTIVES]
|
||||||
|
})
|
||||||
|
// #enddocregion
|
||||||
|
/*
|
||||||
|
// #docregion route-config
|
||||||
|
@Component({ ... })
|
||||||
|
// #enddocregion route-config
|
||||||
|
*/
|
||||||
|
// #docregion
|
||||||
|
// #docregion route-config
|
||||||
|
@RouteConfig([
|
||||||
|
// #docregion route-defs
|
||||||
|
{path: '/crisis-center', name: 'CrisisCenter', component: CrisisListComponent},
|
||||||
|
{path: '/heroes', name: 'Heroes', component: HeroListComponent},
|
||||||
|
// #docregion hero-detail-route
|
||||||
|
{path: '/hero/:id', name: 'HeroDetail', component: HeroDetailComponent}
|
||||||
|
// #enddocregion hero-detail-route
|
||||||
|
// #enddocregion route-defs
|
||||||
|
])
|
||||||
|
export class AppComponent { }
|
||||||
|
// #enddocregion route-config
|
||||||
|
// #enddocregion
|
|
@ -0,0 +1,53 @@
|
||||||
|
// #docplaster
|
||||||
|
import {Component} from '@angular/core';
|
||||||
|
import {RouteConfig, ROUTER_DIRECTIVES} from '@angular/router-deprecated';
|
||||||
|
|
||||||
|
import {CrisisCenterComponent} from './crisis-center/crisis-center.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
|
||||||
|
*/
|
||||||
|
/* 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]="['CrisisCenter']">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]="['CrisisCenter', 'CrisisList']">Crisis Center</a>
|
||||||
|
// #enddocregion cc-anchor-no-default
|
||||||
|
*/
|
||||||
|
/* Crisis Center Detail link
|
||||||
|
// #docregion Dragon-anchor
|
||||||
|
<a [routerLink]="['CrisisCenter', 'CrisisDetail', {id:1}]">Dragon Crisis</a>
|
||||||
|
// #enddocregion Dragon-anchor
|
||||||
|
*/
|
||||||
|
// #docregion template
|
||||||
|
template: `
|
||||||
|
<h1 class="title">Component Router</h1>
|
||||||
|
<nav>
|
||||||
|
<a [routerLink]="['CrisisCenter', 'CrisisList']">Crisis Center</a>
|
||||||
|
<a [routerLink]="['CrisisCenter', 'CrisisDetail', {id:1}]">Dragon Crisis</a>
|
||||||
|
<a [routerLink]="['CrisisCenter', 'CrisisDetail', {id:2}]">Shark Crisis</a>
|
||||||
|
</nav>
|
||||||
|
<router-outlet></router-outlet>
|
||||||
|
`,
|
||||||
|
// #enddocregion template
|
||||||
|
providers: [DialogService, HeroService],
|
||||||
|
directives: [ROUTER_DIRECTIVES]
|
||||||
|
})
|
||||||
|
@RouteConfig([
|
||||||
|
{path: '/crisis-center/...', name: 'CrisisCenter', component: CrisisCenterComponent},
|
||||||
|
])
|
||||||
|
export class AppComponent { }
|
|
@ -0,0 +1,44 @@
|
||||||
|
// #docplaster
|
||||||
|
// #docregion
|
||||||
|
import {Component} from '@angular/core';
|
||||||
|
import {RouteConfig, ROUTER_DIRECTIVES} from '@angular/router-deprecated';
|
||||||
|
|
||||||
|
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';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'my-app',
|
||||||
|
// #docregion template
|
||||||
|
template: `
|
||||||
|
<h1 class="title">Component Router</h1>
|
||||||
|
<nav>
|
||||||
|
<a [routerLink]="['CrisisCenter']">Crisis Center</a>
|
||||||
|
<a [routerLink]="['Heroes']">Heroes</a>
|
||||||
|
</nav>
|
||||||
|
<router-outlet></router-outlet>
|
||||||
|
`,
|
||||||
|
// #enddocregion template
|
||||||
|
providers: [DialogService, HeroService],
|
||||||
|
directives: [ROUTER_DIRECTIVES]
|
||||||
|
})
|
||||||
|
// #docregion route-config
|
||||||
|
@RouteConfig([
|
||||||
|
|
||||||
|
// #docregion route-config-cc
|
||||||
|
{ // Crisis Center child route
|
||||||
|
path: '/crisis-center/...',
|
||||||
|
name: 'CrisisCenter',
|
||||||
|
component: CrisisCenterComponent,
|
||||||
|
useAsDefault: true
|
||||||
|
},
|
||||||
|
// #enddocregion route-config-cc
|
||||||
|
|
||||||
|
{path: '/heroes', name: 'Heroes', component: HeroListComponent},
|
||||||
|
{path: '/hero/:id', name: 'HeroDetail', component: HeroDetailComponent},
|
||||||
|
])
|
||||||
|
// #enddocregion route-config
|
||||||
|
export class AppComponent { }
|
|
@ -0,0 +1,28 @@
|
||||||
|
import {Component} from '@angular/core';
|
||||||
|
import {RouteConfig, RouterOutlet} from '@angular/router-deprecated';
|
||||||
|
|
||||||
|
import {CrisisListComponent} from './crisis-list.component.1';
|
||||||
|
import {CrisisDetailComponent} from './crisis-detail.component.1';
|
||||||
|
import {CrisisService} from './crisis.service';
|
||||||
|
|
||||||
|
// #docregion minus-imports
|
||||||
|
@Component({
|
||||||
|
template: `
|
||||||
|
<h2>CRISIS CENTER</h2>
|
||||||
|
<router-outlet></router-outlet>
|
||||||
|
`,
|
||||||
|
directives: [RouterOutlet],
|
||||||
|
// #docregion providers
|
||||||
|
providers: [CrisisService]
|
||||||
|
// #enddocregion providers
|
||||||
|
})
|
||||||
|
// #docregion route-config
|
||||||
|
@RouteConfig([
|
||||||
|
// #docregion default-route
|
||||||
|
{path:'/', name: 'CrisisList', component: CrisisListComponent, useAsDefault: true},
|
||||||
|
// #enddocregion default-route
|
||||||
|
{path:'/:id', name: 'CrisisDetail', component: CrisisDetailComponent}
|
||||||
|
])
|
||||||
|
// #enddocregion route-config
|
||||||
|
export class CrisisCenterComponent { }
|
||||||
|
// #enddocregion minus-imports
|
|
@ -0,0 +1,22 @@
|
||||||
|
// #docregion
|
||||||
|
import {Component} from '@angular/core';
|
||||||
|
import {RouteConfig, RouterOutlet} from '@angular/router-deprecated';
|
||||||
|
|
||||||
|
import {CrisisListComponent} from './crisis-list.component';
|
||||||
|
import {CrisisDetailComponent} from './crisis-detail.component';
|
||||||
|
import {CrisisService} from './crisis.service';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
template: `
|
||||||
|
<h2>CRISIS CENTER</h2>
|
||||||
|
<router-outlet></router-outlet>
|
||||||
|
`,
|
||||||
|
directives: [RouterOutlet],
|
||||||
|
providers: [CrisisService]
|
||||||
|
})
|
||||||
|
@RouteConfig([
|
||||||
|
{path:'/', name: 'CrisisList', component: CrisisListComponent, useAsDefault: true},
|
||||||
|
{path:'/:id', name: 'CrisisDetail', component: CrisisDetailComponent}
|
||||||
|
])
|
||||||
|
export class CrisisCenterComponent { }
|
||||||
|
// #enddocregion
|
|
@ -0,0 +1,94 @@
|
||||||
|
// #docplaster
|
||||||
|
|
||||||
|
// #docregion
|
||||||
|
import {Component, OnInit} from '@angular/core';
|
||||||
|
import {Crisis, CrisisService} from './crisis.service';
|
||||||
|
import {RouteParams, Router} from '@angular/router-deprecated';
|
||||||
|
// #docregion routerCanDeactivate
|
||||||
|
import {CanDeactivate, ComponentInstruction} from '@angular/router-deprecated';
|
||||||
|
import {DialogService} from '../dialog.service';
|
||||||
|
|
||||||
|
// #enddocregion routerCanDeactivate
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
// #docregion template
|
||||||
|
template: `
|
||||||
|
<div *ngIf="crisis">
|
||||||
|
<h3>"{{editName}}"</h3>
|
||||||
|
<div>
|
||||||
|
<label>Id: </label>{{crisis.id}}</div>
|
||||||
|
<div>
|
||||||
|
<label>Name: </label>
|
||||||
|
<input [(ngModel)]="editName" placeholder="name"/>
|
||||||
|
</div>
|
||||||
|
<p>
|
||||||
|
<button (click)="save()">Save</button>
|
||||||
|
<button (click)="cancel()">Cancel</button>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
`,
|
||||||
|
// #enddocregion template
|
||||||
|
styles: ['input {width: 20em}']
|
||||||
|
})
|
||||||
|
// #docregion routerCanDeactivate, cancel-save
|
||||||
|
export class CrisisDetailComponent implements OnInit, CanDeactivate {
|
||||||
|
|
||||||
|
crisis: Crisis;
|
||||||
|
editName: string;
|
||||||
|
|
||||||
|
// #enddocregion routerCanDeactivate, cancel-save
|
||||||
|
constructor(
|
||||||
|
private _service: CrisisService,
|
||||||
|
private _router: Router,
|
||||||
|
private _routeParams: RouteParams,
|
||||||
|
private _dialog: DialogService
|
||||||
|
) { }
|
||||||
|
|
||||||
|
// #docregion ngOnInit
|
||||||
|
ngOnInit() {
|
||||||
|
let id = +this._routeParams.get('id');
|
||||||
|
this._service.getCrisis(id).then(crisis => {
|
||||||
|
if (crisis) {
|
||||||
|
this.editName = crisis.name;
|
||||||
|
this.crisis = crisis;
|
||||||
|
} else { // id not found
|
||||||
|
this.gotoCrises();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
// #enddocregion ngOnInit
|
||||||
|
|
||||||
|
// #docregion routerCanDeactivate
|
||||||
|
routerCanDeactivate(next: ComponentInstruction, prev: ComponentInstruction) : any {
|
||||||
|
// 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
|
||||||
|
return this._dialog.confirm('Discard changes?');
|
||||||
|
}
|
||||||
|
// #enddocregion routerCanDeactivate
|
||||||
|
|
||||||
|
// #docregion cancel-save
|
||||||
|
cancel() {
|
||||||
|
this.editName = this.crisis.name;
|
||||||
|
this.gotoCrises();
|
||||||
|
}
|
||||||
|
|
||||||
|
save() {
|
||||||
|
this.crisis.name = this.editName;
|
||||||
|
this.gotoCrises();
|
||||||
|
}
|
||||||
|
// #enddocregion cancel-save
|
||||||
|
|
||||||
|
// #docregion gotoCrises
|
||||||
|
gotoCrises() {
|
||||||
|
// Like <a [routerLink]="['CrisisList']">Crisis Center</a
|
||||||
|
this._router.navigate(['CrisisList']);
|
||||||
|
}
|
||||||
|
// #enddocregion gotoCrises
|
||||||
|
// #docregion routerCanDeactivate, cancel-save
|
||||||
|
}
|
||||||
|
// #enddocregion routerCanDeactivate, cancel-save
|
||||||
|
// #enddocregion
|
|
@ -0,0 +1,84 @@
|
||||||
|
// #docplaster
|
||||||
|
|
||||||
|
// #docregion
|
||||||
|
import {Component, OnInit} from '@angular/core';
|
||||||
|
import {Crisis, CrisisService} from './crisis.service';
|
||||||
|
import {RouteParams, Router} from '@angular/router-deprecated';
|
||||||
|
import {CanDeactivate, ComponentInstruction} from '@angular/router-deprecated';
|
||||||
|
import {DialogService} from '../dialog.service';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
template: `
|
||||||
|
<div *ngIf="crisis">
|
||||||
|
<h3>"{{editName}}"</h3>
|
||||||
|
<div>
|
||||||
|
<label>Id: </label>{{crisis.id}}</div>
|
||||||
|
<div>
|
||||||
|
<label>Name: </label>
|
||||||
|
<input [(ngModel)]="editName" placeholder="name"/>
|
||||||
|
</div>
|
||||||
|
<p>
|
||||||
|
<button (click)="save()">Save</button>
|
||||||
|
<button (click)="cancel()">Cancel</button>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
`,
|
||||||
|
styles: ['input {width: 20em}']
|
||||||
|
})
|
||||||
|
|
||||||
|
export class CrisisDetailComponent implements OnInit, CanDeactivate {
|
||||||
|
|
||||||
|
crisis: Crisis;
|
||||||
|
editName: string;
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
private _service: CrisisService,
|
||||||
|
private _router: Router,
|
||||||
|
private _routeParams: RouteParams,
|
||||||
|
private _dialog: DialogService
|
||||||
|
) { }
|
||||||
|
|
||||||
|
ngOnInit() {
|
||||||
|
let id = +this._routeParams.get('id');
|
||||||
|
this._service.getCrisis(id).then(crisis => {
|
||||||
|
if (crisis) {
|
||||||
|
this.editName = crisis.name;
|
||||||
|
this.crisis = crisis;
|
||||||
|
} else { // id not found
|
||||||
|
this.gotoCrises();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
routerCanDeactivate(next: ComponentInstruction, prev: ComponentInstruction) : any {
|
||||||
|
// 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
|
||||||
|
return this._dialog.confirm('Discard changes?');
|
||||||
|
}
|
||||||
|
|
||||||
|
cancel() {
|
||||||
|
this.editName = this.crisis.name;
|
||||||
|
this.gotoCrises();
|
||||||
|
}
|
||||||
|
|
||||||
|
save() {
|
||||||
|
this.crisis.name = this.editName;
|
||||||
|
this.gotoCrises();
|
||||||
|
}
|
||||||
|
|
||||||
|
// #docregion gotoCrises
|
||||||
|
gotoCrises() {
|
||||||
|
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.
|
||||||
|
// #docregion gotoCrises-navigate
|
||||||
|
this._router.navigate(['CrisisList', {id: crisisId, foo: 'foo'} ]);
|
||||||
|
// #enddocregion gotoCrises-navigate
|
||||||
|
}
|
||||||
|
// #enddocregion gotoCrises
|
||||||
|
}
|
|
@ -0,0 +1,36 @@
|
||||||
|
// #docplaster
|
||||||
|
|
||||||
|
// #docregion
|
||||||
|
import {Component, OnInit} from '@angular/core';
|
||||||
|
import {Crisis, CrisisService} from './crisis.service';
|
||||||
|
import {Router} from '@angular/router-deprecated';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
// #docregion template
|
||||||
|
template: `
|
||||||
|
<ul class="items">
|
||||||
|
<li *ngFor="let crisis of crises"
|
||||||
|
(click)="onSelect(crisis)">
|
||||||
|
<span class="badge">{{crisis.id}}</span> {{crisis.name}}
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
`,
|
||||||
|
// #enddocregion template
|
||||||
|
})
|
||||||
|
export class CrisisListComponent implements OnInit {
|
||||||
|
crises: Crisis[];
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
private _service: CrisisService,
|
||||||
|
private _router: Router) {}
|
||||||
|
|
||||||
|
ngOnInit() {
|
||||||
|
this._service.getCrises().then(crises => this.crises = crises);
|
||||||
|
}
|
||||||
|
|
||||||
|
// #docregion select
|
||||||
|
onSelect(crisis: Crisis) {
|
||||||
|
this._router.navigate(['CrisisDetail', { id: crisis.id }] );
|
||||||
|
}
|
||||||
|
// #enddocregion select
|
||||||
|
}
|
|
@ -0,0 +1,40 @@
|
||||||
|
// #docplaster
|
||||||
|
|
||||||
|
// #docregion
|
||||||
|
import {Component, OnInit} from '@angular/core';
|
||||||
|
import {Crisis, CrisisService} from './crisis.service';
|
||||||
|
import {Router, RouteParams} from '@angular/router-deprecated';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
template: `
|
||||||
|
<ul class="items">
|
||||||
|
<li *ngFor="let crisis of crises"
|
||||||
|
[class.selected]="isSelected(crisis)"
|
||||||
|
(click)="onSelect(crisis)">
|
||||||
|
<span class="badge">{{crisis.id}}</span> {{crisis.name}}
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
`,
|
||||||
|
})
|
||||||
|
export class CrisisListComponent implements OnInit {
|
||||||
|
crises: Crisis[];
|
||||||
|
|
||||||
|
private _selectedId: number;
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
private _service: CrisisService,
|
||||||
|
private _router: Router,
|
||||||
|
routeParams: RouteParams) {
|
||||||
|
this._selectedId = +routeParams.get('id');
|
||||||
|
}
|
||||||
|
|
||||||
|
isSelected(crisis: Crisis) { return crisis.id === this._selectedId; }
|
||||||
|
|
||||||
|
ngOnInit() {
|
||||||
|
this._service.getCrises().then(crises => this.crises = crises);
|
||||||
|
}
|
||||||
|
|
||||||
|
onSelect(crisis: Crisis) {
|
||||||
|
this._router.navigate( ['CrisisDetail', { id: crisis.id }] );
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,41 @@
|
||||||
|
// #docplaster
|
||||||
|
|
||||||
|
// #docregion
|
||||||
|
import {Injectable} from '@angular/core';
|
||||||
|
|
||||||
|
export class Crisis {
|
||||||
|
constructor(public id: number, public name: string) { }
|
||||||
|
}
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class CrisisService {
|
||||||
|
getCrises() { return crisesPromise; }
|
||||||
|
|
||||||
|
getCrisis(id: number | string) {
|
||||||
|
return crisesPromise
|
||||||
|
.then(crises => crises.filter(c => c.id === +id)[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// #enddocregion
|
||||||
|
|
||||||
|
static nextCrisisId = 100;
|
||||||
|
|
||||||
|
addCrisis(name:string) {
|
||||||
|
name = name.trim();
|
||||||
|
if (name){
|
||||||
|
let crisis = new Crisis(CrisisService.nextCrisisId++, name);
|
||||||
|
crisesPromise.then(crises => crises.push(crisis));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// #docregion
|
||||||
|
}
|
||||||
|
|
||||||
|
var crises = [
|
||||||
|
new Crisis(1, 'Dragon Burning Cities'),
|
||||||
|
new Crisis(2, 'Sky Rains Great White Sharks'),
|
||||||
|
new Crisis(3, 'Giant Asteroid Heading For Earth'),
|
||||||
|
new Crisis(4, 'Procrastinators Meeting Delayed Again'),
|
||||||
|
];
|
||||||
|
|
||||||
|
var crisesPromise = Promise.resolve(crises);
|
||||||
|
// #enddocregion
|
|
@ -0,0 +1,10 @@
|
||||||
|
// Initial empty version
|
||||||
|
// #docregion
|
||||||
|
import {Component} from '@angular/core';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
template: `
|
||||||
|
<h2>CRISIS CENTER</h2>
|
||||||
|
<p>Get your crisis here</p>`
|
||||||
|
})
|
||||||
|
export class CrisisListComponent { }
|
|
@ -0,0 +1,18 @@
|
||||||
|
// #docregion
|
||||||
|
import {Injectable} from '@angular/core';
|
||||||
|
/**
|
||||||
|
* Async modal dialog service
|
||||||
|
* DialogService makes this app easier to test by faking this service.
|
||||||
|
* TODO: better modal implemenation that doesn't use window.confirm
|
||||||
|
*/
|
||||||
|
@Injectable()
|
||||||
|
export class DialogService {
|
||||||
|
/**
|
||||||
|
* Ask user to confirm an action. `message` explains the action and choices.
|
||||||
|
* 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?')));
|
||||||
|
};
|
||||||
|
}
|
|
@ -0,0 +1,10 @@
|
||||||
|
/// Initial empty version
|
||||||
|
// #docregion
|
||||||
|
import {Component} from '@angular/core';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
template: `
|
||||||
|
<h2>HEROES</h2>
|
||||||
|
<p>Get your heroes here</p>`
|
||||||
|
})
|
||||||
|
export class HeroListComponent { }
|
|
@ -0,0 +1,46 @@
|
||||||
|
// #docregion
|
||||||
|
import {Component, OnInit} from '@angular/core';
|
||||||
|
import {Hero, HeroService} from './hero.service';
|
||||||
|
import {RouteParams, Router} from '@angular/router-deprecated';
|
||||||
|
|
||||||
|
@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;
|
||||||
|
|
||||||
|
// #docregion ctor
|
||||||
|
constructor(
|
||||||
|
private _router:Router,
|
||||||
|
private _routeParams:RouteParams,
|
||||||
|
private _service:HeroService){}
|
||||||
|
// #enddocregion ctor
|
||||||
|
|
||||||
|
// #docregion ngOnInit
|
||||||
|
ngOnInit() {
|
||||||
|
let id = this._routeParams.get('id');
|
||||||
|
this._service.getHero(id).then(hero => this.hero = hero);
|
||||||
|
}
|
||||||
|
// #enddocregion ngOnInit
|
||||||
|
|
||||||
|
// #docregion gotoHeroes
|
||||||
|
gotoHeroes() {
|
||||||
|
// Like <a [routerLink]="['Heroes']">Heroes</a>
|
||||||
|
this._router.navigate(['Heroes']);
|
||||||
|
}
|
||||||
|
// #enddocregion gotoHeroes
|
||||||
|
}
|
|
@ -0,0 +1,51 @@
|
||||||
|
// #docregion
|
||||||
|
import {Component, OnInit} from '@angular/core';
|
||||||
|
import {Hero, HeroService} from './hero.service';
|
||||||
|
import {RouteParams, Router} from '@angular/router-deprecated';
|
||||||
|
|
||||||
|
@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;
|
||||||
|
|
||||||
|
// #docregion ctor
|
||||||
|
constructor(
|
||||||
|
private _router:Router,
|
||||||
|
private _routeParams:RouteParams,
|
||||||
|
private _service:HeroService){}
|
||||||
|
// #enddocregion ctor
|
||||||
|
|
||||||
|
// #docregion ngOnInit
|
||||||
|
ngOnInit() {
|
||||||
|
let id = this._routeParams.get('id');
|
||||||
|
this._service.getHero(id).then(hero => this.hero = hero);
|
||||||
|
}
|
||||||
|
// #enddocregion ngOnInit
|
||||||
|
|
||||||
|
// #docregion gotoHeroes
|
||||||
|
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
|
||||||
|
}
|
||||||
|
// #enddocregion gotoHeroes
|
||||||
|
}
|
|
@ -0,0 +1,49 @@
|
||||||
|
// #docplaster
|
||||||
|
|
||||||
|
// #docregion
|
||||||
|
// TODO SOMEDAY: Feature Componetized like HeroCenter
|
||||||
|
import {Component, OnInit} from '@angular/core';
|
||||||
|
import {Hero, HeroService} from './hero.service';
|
||||||
|
import {Router} from '@angular/router-deprecated';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
// #docregion template
|
||||||
|
template: `
|
||||||
|
<h2>HEROES</h2>
|
||||||
|
<ul class="items">
|
||||||
|
<li *ngFor="let hero of heroes"
|
||||||
|
(click)="onSelect(hero)">
|
||||||
|
<span class="badge">{{hero.id}}</span> {{hero.name}}
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
`
|
||||||
|
// #enddocregion template
|
||||||
|
})
|
||||||
|
export class HeroListComponent implements OnInit {
|
||||||
|
heroes: Hero[];
|
||||||
|
|
||||||
|
// #docregion ctor
|
||||||
|
constructor(
|
||||||
|
private _router: Router,
|
||||||
|
private _service: HeroService) { }
|
||||||
|
// #enddocregion ctor
|
||||||
|
|
||||||
|
ngOnInit() {
|
||||||
|
this._service.getHeroes().then(heroes => this.heroes = heroes)
|
||||||
|
}
|
||||||
|
|
||||||
|
// #docregion select
|
||||||
|
onSelect(hero: Hero) {
|
||||||
|
// #docregion nav-to-detail
|
||||||
|
this._router.navigate( ['HeroDetail', { id: hero.id }] );
|
||||||
|
// #enddocregion nav-to-detail
|
||||||
|
}
|
||||||
|
// #enddocregion select
|
||||||
|
}
|
||||||
|
// #enddocregion
|
||||||
|
|
||||||
|
/* A link parameters array
|
||||||
|
// #docregion link-parameters-array
|
||||||
|
['HeroDetail', { id: hero.id }] // {id: 15}
|
||||||
|
// #enddocregion link-parameters-array
|
||||||
|
*/
|
|
@ -0,0 +1,53 @@
|
||||||
|
// #docplaster
|
||||||
|
|
||||||
|
// TODO SOMEDAY: Feature Componetized like CrisisCenter
|
||||||
|
// #docregion
|
||||||
|
import {Component, OnInit} from '@angular/core';
|
||||||
|
import {Hero, HeroService} from './hero.service';
|
||||||
|
// #docregion import-route-params
|
||||||
|
import {Router, RouteParams} from '@angular/router-deprecated';
|
||||||
|
// #enddocregion import-route-params
|
||||||
|
|
||||||
|
@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 {
|
||||||
|
heroes: Hero[];
|
||||||
|
|
||||||
|
// #docregion ctor
|
||||||
|
private _selectedId: number;
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
private _service: HeroService,
|
||||||
|
private _router: Router,
|
||||||
|
routeParams: RouteParams) {
|
||||||
|
this._selectedId = +routeParams.get('id');
|
||||||
|
}
|
||||||
|
// #enddocregion ctor
|
||||||
|
|
||||||
|
// #docregion isSelected
|
||||||
|
isSelected(hero: Hero) { return hero.id === this._selectedId; }
|
||||||
|
// #enddocregion isSelected
|
||||||
|
|
||||||
|
// #docregion select
|
||||||
|
onSelect(hero: Hero) {
|
||||||
|
this._router.navigate( ['HeroDetail', { id: hero.id }] );
|
||||||
|
}
|
||||||
|
// #enddocregion select
|
||||||
|
|
||||||
|
ngOnInit() {
|
||||||
|
this._service.getHeroes().then(heroes => this.heroes = heroes)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// #enddocregion
|
|
@ -0,0 +1,27 @@
|
||||||
|
// #docregion
|
||||||
|
import {Injectable} from '@angular/core';
|
||||||
|
|
||||||
|
export class Hero {
|
||||||
|
constructor(public id: number, public name: string) { }
|
||||||
|
}
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class HeroService {
|
||||||
|
getHeroes() { return heroesPromise; }
|
||||||
|
|
||||||
|
getHero(id: number | string) {
|
||||||
|
return heroesPromise
|
||||||
|
.then(heroes => heroes.filter(h => h.id === +id)[0]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var HEROES = [
|
||||||
|
new Hero(11, 'Mr. Nice'),
|
||||||
|
new Hero(12, 'Narco'),
|
||||||
|
new Hero(13, 'Bombasto'),
|
||||||
|
new Hero(14, 'Celeritas'),
|
||||||
|
new Hero(15, 'Magneta'),
|
||||||
|
new Hero(16, 'RubberMan')
|
||||||
|
];
|
||||||
|
|
||||||
|
var heroesPromise = Promise.resolve(HEROES);
|
|
@ -0,0 +1,23 @@
|
||||||
|
/* First version */
|
||||||
|
// #docplaster
|
||||||
|
|
||||||
|
// #docregion all
|
||||||
|
import {AppComponent} from './app.component';
|
||||||
|
import {bootstrap} from '@angular/platform-browser-dynamic';
|
||||||
|
import {ROUTER_PROVIDERS} from '@angular/router-deprecated';
|
||||||
|
|
||||||
|
// #enddocregion all
|
||||||
|
|
||||||
|
/* 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';
|
||||||
|
bootstrap(ac, [
|
||||||
|
// #docregion all
|
||||||
|
ROUTER_PROVIDERS
|
||||||
|
]);
|
||||||
|
// #enddocregion all
|
|
@ -0,0 +1,32 @@
|
||||||
|
/* Second version */
|
||||||
|
// For Milestone #2
|
||||||
|
// Also includes digression on HashPathStrategy (not used in the final app)
|
||||||
|
// #docplaster
|
||||||
|
|
||||||
|
// #docregion
|
||||||
|
import {bootstrap} from '@angular/platform-browser-dynamic';
|
||||||
|
import {ROUTER_PROVIDERS} from '@angular/router-deprecated';
|
||||||
|
import {AppComponent} from './app.component';
|
||||||
|
|
||||||
|
// Add these symbols to override the `LocationStrategy`
|
||||||
|
import {provide} from '@angular/core';
|
||||||
|
import {LocationStrategy,
|
||||||
|
HashLocationStrategy} from '@angular/common';
|
||||||
|
// #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';
|
||||||
|
|
||||||
|
bootstrap(ac, [
|
||||||
|
// #docregion
|
||||||
|
ROUTER_PROVIDERS,
|
||||||
|
provide(LocationStrategy,
|
||||||
|
{useClass: HashLocationStrategy}) // .../#/crisis-center/
|
||||||
|
]);
|
||||||
|
// #enddocregion
|
|
@ -0,0 +1,7 @@
|
||||||
|
// #docregion
|
||||||
|
import {bootstrap} from '@angular/platform-browser-dynamic';
|
||||||
|
import {ROUTER_PROVIDERS} from '@angular/router-deprecated';
|
||||||
|
|
||||||
|
import {AppComponent} from './app.component.3';
|
||||||
|
|
||||||
|
bootstrap(AppComponent, [ROUTER_PROVIDERS]);
|
|
@ -0,0 +1,7 @@
|
||||||
|
// #docregion
|
||||||
|
import {bootstrap} from '@angular/platform-browser-dynamic';
|
||||||
|
import {ROUTER_PROVIDERS} from '@angular/router-deprecated';
|
||||||
|
|
||||||
|
import {AppComponent} from './app.component';
|
||||||
|
|
||||||
|
bootstrap(AppComponent, [ROUTER_PROVIDERS]);
|
|
@ -0,0 +1,33 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<!-- #docregion -->
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<!-- #docregion base-href -->
|
||||||
|
<base href="/">
|
||||||
|
<!-- #enddocregion base-href -->
|
||||||
|
<title>Router Sample v.1</title>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
<link rel="stylesheet" href="styles.css">
|
||||||
|
|
||||||
|
<!-- Polyfill(s) for older browsers -->
|
||||||
|
<script src="node_modules/es6-shim/es6-shim.min.js"></script>
|
||||||
|
|
||||||
|
<script src="node_modules/zone.js/dist/zone.js"></script>
|
||||||
|
<script src="node_modules/reflect-metadata/Reflect.js"></script>
|
||||||
|
<script src="node_modules/systemjs/dist/system.src.js"></script>
|
||||||
|
|
||||||
|
<script src="systemjs.config.js"></script>
|
||||||
|
<script>
|
||||||
|
System.import('app/main.1') // <----- ONLY CHANGE
|
||||||
|
.then(null, console.error.bind(console));
|
||||||
|
</script>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<h1>Milestone 1</h1>
|
||||||
|
<my-app>loading...</my-app>
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</html>
|
||||||
|
<!-- #enddocregion -->
|
|
@ -0,0 +1,31 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<!-- #docregion -->
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<base href="/">
|
||||||
|
<title>Router Sample v.2</title>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
<link rel="stylesheet" href="styles.css">
|
||||||
|
|
||||||
|
<!-- Polyfill(s) for older browsers -->
|
||||||
|
<script src="node_modules/es6-shim/es6-shim.min.js"></script>
|
||||||
|
|
||||||
|
<script src="node_modules/zone.js/dist/zone.js"></script>
|
||||||
|
<script src="node_modules/reflect-metadata/Reflect.js"></script>
|
||||||
|
<script src="node_modules/systemjs/dist/system.src.js"></script>
|
||||||
|
|
||||||
|
<script src="systemjs.config.js"></script>
|
||||||
|
<script>
|
||||||
|
System.import('app/main.2') // <----- ONLY CHANGE
|
||||||
|
.then(null, console.error.bind(console));
|
||||||
|
</script>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<h1>Milestone 2</h1>
|
||||||
|
<my-app>loading...</my-app>
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</html>
|
||||||
|
<!-- #enddocregion -->
|
|
@ -0,0 +1,31 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<!-- #docregion -->
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<base href="/">
|
||||||
|
<title>Router Sample v.3</title>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
<link rel="stylesheet" href="styles.css">
|
||||||
|
|
||||||
|
<!-- Polyfill(s) for older browsers -->
|
||||||
|
<script src="node_modules/es6-shim/es6-shim.min.js"></script>
|
||||||
|
|
||||||
|
<script src="node_modules/zone.js/dist/zone.js"></script>
|
||||||
|
<script src="node_modules/reflect-metadata/Reflect.js"></script>
|
||||||
|
<script src="node_modules/systemjs/dist/system.src.js"></script>
|
||||||
|
|
||||||
|
<script src="systemjs.config.js"></script>
|
||||||
|
<script>
|
||||||
|
System.import('app/main.3') // <----- ONLY CHANGE
|
||||||
|
.then(null, console.error.bind(console));
|
||||||
|
</script>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<h1>Milestone 3</h1>
|
||||||
|
<my-app>loading...</my-app>
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</html>
|
||||||
|
<!-- #enddocregion -->
|
|
@ -0,0 +1,30 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<!-- #docregion -->
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<!-- Set the base href -->
|
||||||
|
<base href="/">
|
||||||
|
<title>Router Sample</title>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
<link rel="stylesheet" href="styles.css">
|
||||||
|
|
||||||
|
<!-- Polyfill(s) for older browsers -->
|
||||||
|
<script src="node_modules/es6-shim/es6-shim.min.js"></script>
|
||||||
|
|
||||||
|
<script src="node_modules/zone.js/dist/zone.js"></script>
|
||||||
|
<script src="node_modules/reflect-metadata/Reflect.js"></script>
|
||||||
|
<script src="node_modules/systemjs/dist/system.src.js"></script>
|
||||||
|
|
||||||
|
<script src="systemjs.config.js"></script>
|
||||||
|
<script>
|
||||||
|
System.import('app').catch(function(err){ console.error(err); });
|
||||||
|
</script>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<my-app>loading...</my-app>
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</html>
|
||||||
|
<!-- #enddocregion -->
|
|
@ -3,12 +3,10 @@
|
||||||
|
|
||||||
// #docregion
|
// #docregion
|
||||||
import { Component } from '@angular/core';
|
import { Component } from '@angular/core';
|
||||||
// #docregion import-router
|
import { Routes, ROUTER_DIRECTIVES } from '@angular/router';
|
||||||
import { RouteConfig, ROUTER_DIRECTIVES } from '@angular/router-deprecated';
|
|
||||||
// #enddocregion import-router
|
|
||||||
|
|
||||||
import { CrisisListComponent } from './crisis-list.component';
|
import { CrisisListComponent } from './crisis-list.component';
|
||||||
import { HeroListComponent } from './hero-list.component';
|
import { HeroListComponent } from './hero-list.component';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'my-app',
|
selector: 'my-app',
|
||||||
|
@ -16,8 +14,8 @@ import { HeroListComponent } from './hero-list.component';
|
||||||
template: `
|
template: `
|
||||||
<h1>Component Router</h1>
|
<h1>Component Router</h1>
|
||||||
<nav>
|
<nav>
|
||||||
<a [routerLink]="['CrisisCenter']">Crisis Center</a>
|
<a [routerLink]="['/crisis-center']">Crisis Center</a>
|
||||||
<a [routerLink]="['Heroes']">Heroes</a>
|
<a [routerLink]="['/heroes']">Heroes</a>
|
||||||
</nav>
|
</nav>
|
||||||
<router-outlet></router-outlet>
|
<router-outlet></router-outlet>
|
||||||
`,
|
`,
|
||||||
|
@ -26,16 +24,17 @@ import { HeroListComponent } from './hero-list.component';
|
||||||
})
|
})
|
||||||
// #enddocregion
|
// #enddocregion
|
||||||
/*
|
/*
|
||||||
// #docregion route-config
|
// #docregion route-config
|
||||||
@Component({ ... })
|
@Component({ ... })
|
||||||
// #enddocregion route-config
|
// #enddocregion route-config
|
||||||
*/
|
*/
|
||||||
// #docregion
|
// #docregion
|
||||||
// #docregion route-config
|
// #docregion route-config
|
||||||
@RouteConfig([
|
@Routes([
|
||||||
// #docregion route-defs
|
// #docregion route-defs
|
||||||
{path: '/crisis-center', name: 'CrisisCenter', component: CrisisListComponent},
|
{path: '/crisis-center', component: CrisisListComponent},
|
||||||
{path: '/heroes', name: 'Heroes', component: HeroListComponent}
|
{path: '/heroes', component: HeroListComponent},
|
||||||
|
{path: '*', component: CrisisListComponent}
|
||||||
// #enddocregion route-defs
|
// #enddocregion route-defs
|
||||||
])
|
])
|
||||||
export class AppComponent { }
|
export class AppComponent { }
|
||||||
|
|
|
@ -2,25 +2,25 @@
|
||||||
// #docplaster
|
// #docplaster
|
||||||
|
|
||||||
// #docregion
|
// #docregion
|
||||||
import {Component} from '@angular/core';
|
import { Component, OnInit } from '@angular/core';
|
||||||
import {RouteConfig, ROUTER_DIRECTIVES} from '@angular/router-deprecated';
|
import { Routes, ROUTER_DIRECTIVES, Router } from '@angular/router';
|
||||||
|
|
||||||
import {CrisisListComponent} from './crisis-list.component';
|
import { CrisisListComponent } from './crisis-list.component';
|
||||||
// #enddocregion
|
// #enddocregion
|
||||||
/*
|
/*
|
||||||
// Apparent Milestone 2 imports
|
// Apparent Milestone 2 imports
|
||||||
// #docregion
|
// #docregion
|
||||||
// #docregion hero-import
|
// #docregion hero-import
|
||||||
import {HeroListComponent} from './heroes/hero-list.component';
|
import { HeroListComponent } from './heroes/hero-list.component';
|
||||||
import {HeroDetailComponent} from './heroes/hero-detail.component';
|
import { HeroDetailComponent } from './heroes/hero-detail.component';
|
||||||
import {HeroService} from './heroes/hero.service';
|
import { HeroService } from './heroes/hero.service';
|
||||||
// #enddocregion hero-import
|
// #enddocregion hero-import
|
||||||
// #enddocregion
|
// #enddocregion
|
||||||
*/
|
*/
|
||||||
// Actual Milestone 2 imports
|
// Actual Milestone 2 imports
|
||||||
import {HeroListComponent} from './heroes/hero-list.component.1';
|
import { HeroListComponent } from './heroes/hero-list.component.1';
|
||||||
import {HeroDetailComponent} from './heroes/hero-detail.component.1';
|
import { HeroDetailComponent } from './heroes/hero-detail.component.1';
|
||||||
import {HeroService} from './heroes/hero.service';
|
import { HeroService } from './heroes/hero.service';
|
||||||
// #docregion
|
// #docregion
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
|
@ -28,8 +28,8 @@ import {HeroService} from './heroes/hero.service';
|
||||||
template: `
|
template: `
|
||||||
<h1>Component Router</h1>
|
<h1>Component Router</h1>
|
||||||
<nav>
|
<nav>
|
||||||
<a [routerLink]="['CrisisCenter']">Crisis Center</a>
|
<a [routerLink]="['/crisis-center']">Crisis Center</a>
|
||||||
<a [routerLink]="['Heroes']">Heroes</a>
|
<a [routerLink]="['/heroes']">Heroes</a>
|
||||||
</nav>
|
</nav>
|
||||||
<router-outlet></router-outlet>
|
<router-outlet></router-outlet>
|
||||||
`,
|
`,
|
||||||
|
@ -38,21 +38,27 @@ import {HeroService} from './heroes/hero.service';
|
||||||
})
|
})
|
||||||
// #enddocregion
|
// #enddocregion
|
||||||
/*
|
/*
|
||||||
// #docregion route-config
|
// #docregion route-config
|
||||||
@Component({ ... })
|
@Component({ ... })
|
||||||
// #enddocregion route-config
|
// #enddocregion route-config
|
||||||
*/
|
*/
|
||||||
// #docregion
|
// #docregion
|
||||||
// #docregion route-config
|
// #docregion route-config
|
||||||
@RouteConfig([
|
@Routes([
|
||||||
// #docregion route-defs
|
// #docregion route-defs
|
||||||
{path: '/crisis-center', name: 'CrisisCenter', component: CrisisListComponent},
|
{path: '/crisis-center', component: CrisisListComponent},
|
||||||
{path: '/heroes', name: 'Heroes', component: HeroListComponent},
|
{path: '/heroes', component: HeroListComponent},
|
||||||
// #docregion hero-detail-route
|
// #docregion hero-detail-route
|
||||||
{path: '/hero/:id', name: 'HeroDetail', component: HeroDetailComponent}
|
{path: '/hero/:id', component: HeroDetailComponent}
|
||||||
// #enddocregion hero-detail-route
|
// #enddocregion hero-detail-route
|
||||||
// #enddocregion route-defs
|
// #enddocregion route-defs
|
||||||
])
|
])
|
||||||
export class AppComponent { }
|
export class AppComponent implements OnInit {
|
||||||
|
constructor(private router: Router) {}
|
||||||
|
|
||||||
|
ngOnInit() {
|
||||||
|
this.router.navigate(['/crisis-center']);
|
||||||
|
}
|
||||||
|
}
|
||||||
// #enddocregion route-config
|
// #enddocregion route-config
|
||||||
// #enddocregion
|
// #enddocregion
|
||||||
|
|
|
@ -1,45 +1,48 @@
|
||||||
|
/* tslint:disable:no-unused-variable */
|
||||||
// #docplaster
|
// #docplaster
|
||||||
import {Component} from '@angular/core';
|
import { Component, OnInit } from '@angular/core';
|
||||||
import {RouteConfig, ROUTER_DIRECTIVES} from '@angular/router-deprecated';
|
import { Routes, ROUTER_DIRECTIVES, Router } from '@angular/router';
|
||||||
|
|
||||||
import {CrisisCenterComponent} from './crisis-center/crisis-center.component.1';
|
import { CrisisCenterComponent } from './crisis-center/crisis-center.component.1';
|
||||||
|
import { HeroListComponent } from './heroes/hero-list.component.1';
|
||||||
|
import { HeroDetailComponent } from './heroes/hero-detail.component.1';
|
||||||
|
|
||||||
import {DialogService} from './dialog.service';
|
import { DialogService } from './dialog.service';
|
||||||
import {HeroService} from './heroes/hero.service';
|
import { HeroService } from './heroes/hero.service';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'my-app',
|
selector: 'my-app',
|
||||||
// #enddocregion
|
// #enddocregion
|
||||||
/* Typical link
|
/* Typical link
|
||||||
// #docregion h-anchor
|
// #docregion h-anchor
|
||||||
<a [routerLink]="['Heroes']">Heroes</a>
|
<a [routerLink]="['/heroes']">Heroes</a>
|
||||||
// #enddocregion h-anchor
|
// #enddocregion h-anchor
|
||||||
*/
|
*/
|
||||||
/* Incomplete Crisis Center link when CC lacks a default
|
/* Incomplete Crisis Center link when CC lacks a default
|
||||||
// #docregion cc-anchor-fail
|
// #docregion cc-anchor-fail
|
||||||
// The link now fails with a "non-terminal link" error
|
// The link now fails with a "non-terminal link" error
|
||||||
// #docregion cc-anchor-w-default
|
// #docregion cc-anchor-w-default
|
||||||
<a [routerLink]="['CrisisCenter']">Crisis Center</a>
|
<a [routerLink]="['/crisis-center']">Crisis Center</a>
|
||||||
// #enddocregion cc-anchor-w-default
|
// #enddocregion cc-anchor-w-default
|
||||||
// #enddocregion cc-anchor-fail
|
// #enddocregion cc-anchor-fail
|
||||||
*/
|
*/
|
||||||
/* Crisis Center link when CC lacks a default
|
/* Crisis Center link when CC lacks a default
|
||||||
// #docregion cc-anchor-no-default
|
// #docregion cc-anchor-no-default
|
||||||
<a [routerLink]="['CrisisCenter', 'CrisisList']">Crisis Center</a>
|
<a [routerLink]="['/crisis-center/']">Crisis Center</a>
|
||||||
// #enddocregion cc-anchor-no-default
|
// #enddocregion cc-anchor-no-default
|
||||||
*/
|
*/
|
||||||
/* Crisis Center Detail link
|
/* Crisis Center Detail link
|
||||||
// #docregion Dragon-anchor
|
// #docregion Dragon-anchor
|
||||||
<a [routerLink]="['CrisisCenter', 'CrisisDetail', {id:1}]">Dragon Crisis</a>
|
<a [routerLink]="['/crisis-center/1']">Dragon Crisis</a>
|
||||||
// #enddocregion Dragon-anchor
|
// #enddocregion Dragon-anchor
|
||||||
*/
|
*/
|
||||||
// #docregion template
|
// #docregion template
|
||||||
template: `
|
template: `
|
||||||
<h1 class="title">Component Router</h1>
|
<h1 class="title">Component Router</h1>
|
||||||
<nav>
|
<nav>
|
||||||
<a [routerLink]="['CrisisCenter', 'CrisisList']">Crisis Center</a>
|
<a [routerLink]="['/crisis-center']">Crisis Center</a>
|
||||||
<a [routerLink]="['CrisisCenter', 'CrisisDetail', {id:1}]">Dragon Crisis</a>
|
<a [routerLink]="['/crisis-center', 1]">Dragon Crisis</a>
|
||||||
<a [routerLink]="['CrisisCenter', 'CrisisDetail', {id:2}]">Shark Crisis</a>
|
<a [routerLink]="['/crisis-center', 2]">Shark Crisis</a>
|
||||||
</nav>
|
</nav>
|
||||||
<router-outlet></router-outlet>
|
<router-outlet></router-outlet>
|
||||||
`,
|
`,
|
||||||
|
@ -47,7 +50,14 @@ import {HeroService} from './heroes/hero.service';
|
||||||
providers: [DialogService, HeroService],
|
providers: [DialogService, HeroService],
|
||||||
directives: [ROUTER_DIRECTIVES]
|
directives: [ROUTER_DIRECTIVES]
|
||||||
})
|
})
|
||||||
@RouteConfig([
|
@Routes([
|
||||||
{path: '/crisis-center/...', name: 'CrisisCenter', component: CrisisCenterComponent},
|
{path: '/crisis-center', component: CrisisCenterComponent},
|
||||||
|
{path: '*', component: CrisisCenterComponent}
|
||||||
])
|
])
|
||||||
export class AppComponent { }
|
export class AppComponent implements OnInit {
|
||||||
|
constructor(private router: Router) {}
|
||||||
|
|
||||||
|
ngOnInit() {
|
||||||
|
this.router.navigate(['/crisis-center']);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,14 +1,14 @@
|
||||||
// #docplaster
|
// #docplaster
|
||||||
// #docregion
|
// #docregion
|
||||||
import {Component} from '@angular/core';
|
import { Component, OnInit } from '@angular/core';
|
||||||
import {RouteConfig, ROUTER_DIRECTIVES} from '@angular/router-deprecated';
|
import { Routes, Router, ROUTER_DIRECTIVES } from '@angular/router';
|
||||||
|
|
||||||
import {CrisisCenterComponent} from './crisis-center/crisis-center.component';
|
import { CrisisCenterComponent } from './crisis-center/crisis-center.component';
|
||||||
import {HeroListComponent} from './heroes/hero-list.component';
|
import { HeroListComponent } from './heroes/hero-list.component';
|
||||||
import {HeroDetailComponent} from './heroes/hero-detail.component';
|
import { HeroDetailComponent } from './heroes/hero-detail.component';
|
||||||
|
|
||||||
import {DialogService} from './dialog.service';
|
import { DialogService } from './dialog.service';
|
||||||
import {HeroService} from './heroes/hero.service';
|
import { HeroService } from './heroes/hero.service';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'my-app',
|
selector: 'my-app',
|
||||||
|
@ -16,8 +16,8 @@ import {HeroService} from './heroes/hero.service';
|
||||||
template: `
|
template: `
|
||||||
<h1 class="title">Component Router</h1>
|
<h1 class="title">Component Router</h1>
|
||||||
<nav>
|
<nav>
|
||||||
<a [routerLink]="['CrisisCenter']">Crisis Center</a>
|
<a [routerLink]="['/crisis-center']">Crisis Center</a>
|
||||||
<a [routerLink]="['Heroes']">Heroes</a>
|
<a [routerLink]="['/heroes']">Heroes</a>
|
||||||
</nav>
|
</nav>
|
||||||
<router-outlet></router-outlet>
|
<router-outlet></router-outlet>
|
||||||
`,
|
`,
|
||||||
|
@ -25,20 +25,17 @@ import {HeroService} from './heroes/hero.service';
|
||||||
providers: [DialogService, HeroService],
|
providers: [DialogService, HeroService],
|
||||||
directives: [ROUTER_DIRECTIVES]
|
directives: [ROUTER_DIRECTIVES]
|
||||||
})
|
})
|
||||||
// #docregion route-config
|
// #docregion routes
|
||||||
@RouteConfig([
|
@Routes([
|
||||||
|
{path: '/crisis-center', component: CrisisCenterComponent},
|
||||||
// #docregion route-config-cc
|
{path: '/heroes', component: HeroListComponent},
|
||||||
{ // Crisis Center child route
|
{path: '/hero/:id', component: HeroDetailComponent},
|
||||||
path: '/crisis-center/...',
|
|
||||||
name: 'CrisisCenter',
|
|
||||||
component: CrisisCenterComponent,
|
|
||||||
useAsDefault: true
|
|
||||||
},
|
|
||||||
// #enddocregion route-config-cc
|
|
||||||
|
|
||||||
{path: '/heroes', name: 'Heroes', component: HeroListComponent},
|
|
||||||
{path: '/hero/:id', name: 'HeroDetail', component: HeroDetailComponent},
|
|
||||||
])
|
])
|
||||||
// #enddocregion route-config
|
// #enddocregion routes
|
||||||
export class AppComponent { }
|
export class AppComponent implements OnInit {
|
||||||
|
constructor(private router: Router) {}
|
||||||
|
|
||||||
|
ngOnInit() {
|
||||||
|
this.router.navigate(['/crisis-center']);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
import {Component} from '@angular/core';
|
import { Component } from '@angular/core';
|
||||||
import {RouteConfig, RouterOutlet} from '@angular/router-deprecated';
|
import { Routes, ROUTER_DIRECTIVES } from '@angular/router';
|
||||||
|
|
||||||
import {CrisisListComponent} from './crisis-list.component.1';
|
import { CrisisListComponent } from './crisis-list.component.1';
|
||||||
import {CrisisDetailComponent} from './crisis-detail.component.1';
|
import { CrisisDetailComponent } from './crisis-detail.component.1';
|
||||||
import {CrisisService} from './crisis.service';
|
import { CrisisService } from './crisis.service';
|
||||||
|
|
||||||
// #docregion minus-imports
|
// #docregion minus-imports
|
||||||
@Component({
|
@Component({
|
||||||
|
@ -11,17 +11,17 @@ import {CrisisService} from './crisis.service';
|
||||||
<h2>CRISIS CENTER</h2>
|
<h2>CRISIS CENTER</h2>
|
||||||
<router-outlet></router-outlet>
|
<router-outlet></router-outlet>
|
||||||
`,
|
`,
|
||||||
directives: [RouterOutlet],
|
directives: [ROUTER_DIRECTIVES],
|
||||||
// #docregion providers
|
// #docregion providers
|
||||||
providers: [CrisisService]
|
providers: [CrisisService]
|
||||||
// #enddocregion providers
|
// #enddocregion providers
|
||||||
})
|
})
|
||||||
// #docregion route-config
|
// #docregion route-config
|
||||||
@RouteConfig([
|
@Routes([
|
||||||
// #docregion default-route
|
// #docregion default-route
|
||||||
{path:'/', name: 'CrisisList', component: CrisisListComponent, useAsDefault: true},
|
{path: '/', component: CrisisListComponent}, // , useAsDefault: true}, // coming soon
|
||||||
// #enddocregion default-route
|
// #enddocregion default-route
|
||||||
{path:'/:id', name: 'CrisisDetail', component: CrisisDetailComponent}
|
{path: '/:id', component: CrisisDetailComponent}
|
||||||
])
|
])
|
||||||
// #enddocregion route-config
|
// #enddocregion route-config
|
||||||
export class CrisisCenterComponent { }
|
export class CrisisCenterComponent { }
|
||||||
|
|
|
@ -1,22 +1,22 @@
|
||||||
// #docregion
|
// #docregion
|
||||||
import {Component} from '@angular/core';
|
import { Component } from '@angular/core';
|
||||||
import {RouteConfig, RouterOutlet} from '@angular/router-deprecated';
|
import { Routes, ROUTER_DIRECTIVES } from '@angular/router';
|
||||||
|
|
||||||
import {CrisisListComponent} from './crisis-list.component';
|
import { CrisisListComponent } from './crisis-list.component';
|
||||||
import {CrisisDetailComponent} from './crisis-detail.component';
|
import { CrisisDetailComponent } from './crisis-detail.component';
|
||||||
import {CrisisService} from './crisis.service';
|
import { CrisisService } from './crisis.service';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
template: `
|
template: `
|
||||||
<h2>CRISIS CENTER</h2>
|
<h2>CRISIS CENTER</h2>
|
||||||
<router-outlet></router-outlet>
|
<router-outlet></router-outlet>
|
||||||
`,
|
`,
|
||||||
directives: [RouterOutlet],
|
directives: [ROUTER_DIRECTIVES],
|
||||||
providers: [CrisisService]
|
providers: [CrisisService]
|
||||||
})
|
})
|
||||||
@RouteConfig([
|
@Routes([
|
||||||
{path:'/', name: 'CrisisList', component: CrisisListComponent, useAsDefault: true},
|
{path: '', component: CrisisListComponent}, // , useAsDefault: true}, // coming soon
|
||||||
{path:'/:id', name: 'CrisisDetail', component: CrisisDetailComponent}
|
{path: '/:id', component: CrisisDetailComponent}
|
||||||
])
|
])
|
||||||
export class CrisisCenterComponent { }
|
export class CrisisCenterComponent { }
|
||||||
// #enddocregion
|
// #enddocregion
|
||||||
|
|
|
@ -1,15 +1,13 @@
|
||||||
// #docplaster
|
// #docplaster
|
||||||
|
|
||||||
// #docregion
|
// #docregion
|
||||||
import {Component, OnInit} from '@angular/core';
|
import { Component } from '@angular/core';
|
||||||
import {Crisis, CrisisService} from './crisis.service';
|
import { Crisis, CrisisService } from './crisis.service';
|
||||||
import {RouteParams, Router} from '@angular/router-deprecated';
|
import { Router, OnActivate, RouteSegment } from '@angular/router';
|
||||||
// #docregion routerCanDeactivate
|
// #docregion routerCanDeactivate
|
||||||
import {CanDeactivate, ComponentInstruction} from '@angular/router-deprecated';
|
// import { CanDeactivate } from '@angular/router';
|
||||||
import {DialogService} from '../dialog.service';
|
import { DialogService } from '../dialog.service';
|
||||||
|
|
||||||
// #enddocregion routerCanDeactivate
|
// #enddocregion routerCanDeactivate
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
// #docregion template
|
// #docregion template
|
||||||
template: `
|
template: `
|
||||||
|
@ -31,23 +29,22 @@ import {DialogService} from '../dialog.service';
|
||||||
styles: ['input {width: 20em}']
|
styles: ['input {width: 20em}']
|
||||||
})
|
})
|
||||||
// #docregion routerCanDeactivate, cancel-save
|
// #docregion routerCanDeactivate, cancel-save
|
||||||
export class CrisisDetailComponent implements OnInit, CanDeactivate {
|
export class CrisisDetailComponent implements OnActivate {// , CanDeactivate {
|
||||||
|
|
||||||
crisis: Crisis;
|
crisis: Crisis;
|
||||||
editName: string;
|
editName: string;
|
||||||
|
|
||||||
// #enddocregion routerCanDeactivate, cancel-save
|
// #enddocregion routerCanDeactivate, cancel-save
|
||||||
constructor(
|
constructor(
|
||||||
private _service: CrisisService,
|
private service: CrisisService,
|
||||||
private _router: Router,
|
private router: Router,
|
||||||
private _routeParams: RouteParams,
|
private dialog: DialogService
|
||||||
private _dialog: DialogService
|
|
||||||
) { }
|
) { }
|
||||||
|
|
||||||
// #docregion ngOnInit
|
// #docregion ngOnActivate
|
||||||
ngOnInit() {
|
routerOnActivate(curr: RouteSegment): void {
|
||||||
let id = +this._routeParams.get('id');
|
let id = +curr.getParam('id');
|
||||||
this._service.getCrisis(id).then(crisis => {
|
this.service.getCrisis(id).then(crisis => {
|
||||||
if (crisis) {
|
if (crisis) {
|
||||||
this.editName = crisis.name;
|
this.editName = crisis.name;
|
||||||
this.crisis = crisis;
|
this.crisis = crisis;
|
||||||
|
@ -56,17 +53,18 @@ export class CrisisDetailComponent implements OnInit, CanDeactivate {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
// #enddocregion ngOnInit
|
// #enddocregion ngOnActivate
|
||||||
|
|
||||||
// #docregion routerCanDeactivate
|
// #docregion routerCanDeactivate
|
||||||
routerCanDeactivate(next: ComponentInstruction, prev: ComponentInstruction) : any {
|
// NOT IMPLEMENTED YET
|
||||||
|
routerCanDeactivate(): any {
|
||||||
// Allow synchronous navigation (`true`) if no crisis or the crisis is unchanged.
|
// Allow synchronous navigation (`true`) if no crisis or the crisis is unchanged.
|
||||||
if (!this.crisis || this.crisis.name === this.editName) {
|
if (!this.crisis || this.crisis.name === this.editName) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
// Otherwise ask the user with the dialog service and return its
|
// Otherwise ask the user with the dialog service and return its
|
||||||
// promise which resolves to true or false when the user decides
|
// promise which resolves to true or false when the user decides
|
||||||
return this._dialog.confirm('Discard changes?');
|
return this.dialog.confirm('Discard changes?');
|
||||||
}
|
}
|
||||||
// #enddocregion routerCanDeactivate
|
// #enddocregion routerCanDeactivate
|
||||||
|
|
||||||
|
@ -84,8 +82,8 @@ export class CrisisDetailComponent implements OnInit, CanDeactivate {
|
||||||
|
|
||||||
// #docregion gotoCrises
|
// #docregion gotoCrises
|
||||||
gotoCrises() {
|
gotoCrises() {
|
||||||
// Like <a [routerLink]="['CrisisList']">Crisis Center</a
|
// Like <a [routerLink]="[/crisis-center/]">Crisis Center</a
|
||||||
this._router.navigate(['CrisisList']);
|
this.router.navigateByUrl('/crisis-center/'); // absolute url
|
||||||
}
|
}
|
||||||
// #enddocregion gotoCrises
|
// #enddocregion gotoCrises
|
||||||
// #docregion routerCanDeactivate, cancel-save
|
// #docregion routerCanDeactivate, cancel-save
|
||||||
|
|
|
@ -1,11 +1,9 @@
|
||||||
// #docplaster
|
// #docplaster
|
||||||
|
|
||||||
// #docregion
|
// #docregion
|
||||||
import {Component, OnInit} from '@angular/core';
|
import { Component } from '@angular/core';
|
||||||
import {Crisis, CrisisService} from './crisis.service';
|
import { Crisis, CrisisService } from './crisis.service';
|
||||||
import {RouteParams, Router} from '@angular/router-deprecated';
|
import { Router, OnActivate, CanDeactivate, RouteSegment } from '@angular/router';
|
||||||
import {CanDeactivate, ComponentInstruction} from '@angular/router-deprecated';
|
import { DialogService } from '../dialog.service';
|
||||||
import {DialogService} from '../dialog.service';
|
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
template: `
|
template: `
|
||||||
|
@ -26,21 +24,22 @@ import {DialogService} from '../dialog.service';
|
||||||
styles: ['input {width: 20em}']
|
styles: ['input {width: 20em}']
|
||||||
})
|
})
|
||||||
|
|
||||||
export class CrisisDetailComponent implements OnInit, CanDeactivate {
|
export class CrisisDetailComponent implements OnActivate, CanDeactivate {
|
||||||
|
|
||||||
crisis: Crisis;
|
crisis: Crisis;
|
||||||
editName: string;
|
editName: string;
|
||||||
|
private curSegment: RouteSegment;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private _service: CrisisService,
|
private service: CrisisService,
|
||||||
private _router: Router,
|
private router: Router,
|
||||||
private _routeParams: RouteParams,
|
private dialog: DialogService
|
||||||
private _dialog: DialogService
|
|
||||||
) { }
|
) { }
|
||||||
|
|
||||||
ngOnInit() {
|
routerOnActivate(curr: RouteSegment) {
|
||||||
let id = +this._routeParams.get('id');
|
this.curSegment = curr;
|
||||||
this._service.getCrisis(id).then(crisis => {
|
|
||||||
|
let id = +curr.getParam('id');
|
||||||
|
this.service.getCrisis(id).then(crisis => {
|
||||||
if (crisis) {
|
if (crisis) {
|
||||||
this.editName = crisis.name;
|
this.editName = crisis.name;
|
||||||
this.crisis = crisis;
|
this.crisis = crisis;
|
||||||
|
@ -50,18 +49,17 @@ export class CrisisDetailComponent implements OnInit, CanDeactivate {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
routerCanDeactivate(next: ComponentInstruction, prev: ComponentInstruction) : any {
|
routerCanDeactivate(): any {
|
||||||
// Allow synchronous navigation (`true`) if no crisis or the crisis is unchanged.
|
// Allow synchronous navigation (`true`) if no crisis or the crisis is unchanged.
|
||||||
if (!this.crisis || this.crisis.name === this.editName) {
|
if (!this.crisis || this.crisis.name === this.editName) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
// Otherwise ask the user with the dialog service and return its
|
// Otherwise ask the user with the dialog service and return its
|
||||||
// promise which resolves to true or false when the user decides
|
// promise which resolves to true or false when the user decides
|
||||||
return this._dialog.confirm('Discard changes?');
|
return this.dialog.confirm('Discard changes?');
|
||||||
}
|
}
|
||||||
|
|
||||||
cancel() {
|
cancel() {
|
||||||
this.editName = this.crisis.name;
|
|
||||||
this.gotoCrises();
|
this.gotoCrises();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -77,7 +75,11 @@ export class CrisisDetailComponent implements OnInit, CanDeactivate {
|
||||||
// so that the CrisisListComponent can select that hero.
|
// so that the CrisisListComponent can select that hero.
|
||||||
// Add a totally useless `foo` parameter for kicks.
|
// Add a totally useless `foo` parameter for kicks.
|
||||||
// #docregion gotoCrises-navigate
|
// #docregion gotoCrises-navigate
|
||||||
this._router.navigate(['CrisisList', {id: crisisId, foo: 'foo'} ]);
|
// 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-navigate
|
||||||
}
|
}
|
||||||
// #enddocregion gotoCrises
|
// #enddocregion gotoCrises
|
||||||
|
|
|
@ -1,9 +1,8 @@
|
||||||
// #docplaster
|
// #docplaster
|
||||||
|
|
||||||
// #docregion
|
// #docregion
|
||||||
import {Component, OnInit} from '@angular/core';
|
import { Component } from '@angular/core';
|
||||||
import {Crisis, CrisisService} from './crisis.service';
|
import { Crisis, CrisisService } from './crisis.service';
|
||||||
import {Router} from '@angular/router-deprecated';
|
import { Router, OnActivate, RouteSegment } from '@angular/router';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
// #docregion template
|
// #docregion template
|
||||||
|
@ -17,20 +16,20 @@ import {Router} from '@angular/router-deprecated';
|
||||||
`,
|
`,
|
||||||
// #enddocregion template
|
// #enddocregion template
|
||||||
})
|
})
|
||||||
export class CrisisListComponent implements OnInit {
|
export class CrisisListComponent implements OnActivate {
|
||||||
crises: Crisis[];
|
crises: Crisis[];
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private _service: CrisisService,
|
private service: CrisisService,
|
||||||
private _router: Router) {}
|
private router: Router) {}
|
||||||
|
|
||||||
ngOnInit() {
|
routerOnActivate(curr: RouteSegment): void {
|
||||||
this._service.getCrises().then(crises => this.crises = crises);
|
this.service.getCrises().then(crises => this.crises = crises);
|
||||||
}
|
}
|
||||||
|
|
||||||
// #docregion select
|
// #docregion select
|
||||||
onSelect(crisis: Crisis) {
|
onSelect(crisis: Crisis) {
|
||||||
this._router.navigate(['CrisisDetail', { id: crisis.id }] );
|
this.router.navigateByUrl( `/crisis-list/${crisis.id}`);
|
||||||
}
|
}
|
||||||
// #enddocregion select
|
// #enddocregion select
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,8 @@
|
||||||
// #docplaster
|
// #docplaster
|
||||||
|
|
||||||
// #docregion
|
// #docregion
|
||||||
import {Component, OnInit} from '@angular/core';
|
import { Component } from '@angular/core';
|
||||||
import {Crisis, CrisisService} from './crisis.service';
|
import { Crisis, CrisisService } from './crisis.service';
|
||||||
import {Router, RouteParams} from '@angular/router-deprecated';
|
import { Router, OnActivate, RouteSegment, RouteTree } from '@angular/router';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
template: `
|
template: `
|
||||||
|
@ -16,25 +15,28 @@ import {Router, RouteParams} from '@angular/router-deprecated';
|
||||||
</ul>
|
</ul>
|
||||||
`,
|
`,
|
||||||
})
|
})
|
||||||
export class CrisisListComponent implements OnInit {
|
export class CrisisListComponent implements OnActivate {
|
||||||
crises: Crisis[];
|
crises: Crisis[];
|
||||||
|
private currSegment: RouteSegment;
|
||||||
private _selectedId: number;
|
private selectedId: number;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private _service: CrisisService,
|
private service: CrisisService,
|
||||||
private _router: Router,
|
private router: Router) { }
|
||||||
routeParams: RouteParams) {
|
|
||||||
this._selectedId = +routeParams.get('id');
|
|
||||||
}
|
|
||||||
|
|
||||||
isSelected(crisis: Crisis) { return crisis.id === this._selectedId; }
|
isSelected(crisis: Crisis) { return crisis.id === this.selectedId; }
|
||||||
|
|
||||||
ngOnInit() {
|
routerOnActivate(curr: RouteSegment, prev: RouteSegment, currTree: RouteTree) {
|
||||||
this._service.getCrises().then(crises => this.crises = crises);
|
this.currSegment = curr;
|
||||||
|
this.selectedId = +currTree.parent(curr).getParam('id');
|
||||||
|
this.service.getCrises().then(crises => this.crises = crises);
|
||||||
}
|
}
|
||||||
|
|
||||||
onSelect(crisis: Crisis) {
|
onSelect(crisis: Crisis) {
|
||||||
this._router.navigate( ['CrisisDetail', { id: crisis.id }] );
|
// Absolute link
|
||||||
|
// this.router.navigate([`/crisis-center`, crisis.id]);
|
||||||
|
|
||||||
|
// Relative link
|
||||||
|
this.router.navigate([`./${crisis.id}`], this.currSegment);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,14 +1,26 @@
|
||||||
// #docplaster
|
// #docplaster
|
||||||
|
|
||||||
// #docregion
|
|
||||||
import {Injectable} from '@angular/core';
|
|
||||||
|
|
||||||
export class Crisis {
|
export class Crisis {
|
||||||
constructor(public id: number, public name: string) { }
|
constructor(public id: number, public name: string) { }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const CRISES = [
|
||||||
|
new Crisis(1, 'Dragon Burning Cities'),
|
||||||
|
new Crisis(2, 'Sky Rains Great White Sharks'),
|
||||||
|
new Crisis(3, 'Giant Asteroid Heading For Earth'),
|
||||||
|
new Crisis(4, 'Procrastinators Meeting Delayed Again'),
|
||||||
|
];
|
||||||
|
|
||||||
|
let crisesPromise = Promise.resolve(CRISES);
|
||||||
|
|
||||||
|
// #docregion
|
||||||
|
import { Injectable } from '@angular/core';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class CrisisService {
|
export class CrisisService {
|
||||||
|
|
||||||
|
static nextCrisisId = 100;
|
||||||
|
|
||||||
getCrises() { return crisesPromise; }
|
getCrises() { return crisesPromise; }
|
||||||
|
|
||||||
getCrisis(id: number | string) {
|
getCrisis(id: number | string) {
|
||||||
|
@ -18,24 +30,13 @@ export class CrisisService {
|
||||||
|
|
||||||
// #enddocregion
|
// #enddocregion
|
||||||
|
|
||||||
static nextCrisisId = 100;
|
addCrisis(name: string) {
|
||||||
|
|
||||||
addCrisis(name:string) {
|
|
||||||
name = name.trim();
|
name = name.trim();
|
||||||
if (name){
|
if (name) {
|
||||||
let crisis = new Crisis(CrisisService.nextCrisisId++, name);
|
let crisis = new Crisis(CrisisService.nextCrisisId++, name);
|
||||||
crisesPromise.then(crises => crises.push(crisis));
|
crisesPromise.then(crises => crises.push(crisis));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// #docregion
|
// #docregion
|
||||||
}
|
}
|
||||||
|
|
||||||
var crises = [
|
|
||||||
new Crisis(1, 'Dragon Burning Cities'),
|
|
||||||
new Crisis(2, 'Sky Rains Great White Sharks'),
|
|
||||||
new Crisis(3, 'Giant Asteroid Heading For Earth'),
|
|
||||||
new Crisis(4, 'Procrastinators Meeting Delayed Again'),
|
|
||||||
];
|
|
||||||
|
|
||||||
var crisesPromise = Promise.resolve(crises);
|
|
||||||
// #enddocregion
|
// #enddocregion
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
// Initial empty version
|
// Initial empty version
|
||||||
// #docregion
|
// #docregion
|
||||||
import {Component} from '@angular/core';
|
import { Component } from '@angular/core';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
template: `
|
template: `
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
// #docregion
|
// #docregion
|
||||||
import {Injectable} from '@angular/core';
|
import { Injectable } from '@angular/core';
|
||||||
/**
|
/**
|
||||||
* Async modal dialog service
|
* Async modal dialog service
|
||||||
* DialogService makes this app easier to test by faking this service.
|
* DialogService makes this app easier to test by faking this service.
|
||||||
|
@ -11,7 +11,7 @@ export class DialogService {
|
||||||
* Ask user to confirm an action. `message` explains the action and choices.
|
* Ask user to confirm an action. `message` explains the action and choices.
|
||||||
* Returns promise resolving to `true`=confirm or `false`=cancel
|
* Returns promise resolving to `true`=confirm or `false`=cancel
|
||||||
*/
|
*/
|
||||||
confirm(message?:string) {
|
confirm(message?: string) {
|
||||||
return new Promise<boolean>((resolve, reject) =>
|
return new Promise<boolean>((resolve, reject) =>
|
||||||
resolve(window.confirm(message || 'Is it OK?')));
|
resolve(window.confirm(message || 'Is it OK?')));
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/// Initial empty version
|
/// Initial empty version
|
||||||
// #docregion
|
// #docregion
|
||||||
import {Component} from '@angular/core';
|
import { Component } from '@angular/core';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
template: `
|
template: `
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
// #docregion
|
// #docregion
|
||||||
import {Component, OnInit} from '@angular/core';
|
import { Component } from '@angular/core';
|
||||||
import {Hero, HeroService} from './hero.service';
|
import { Hero, HeroService } from './hero.service';
|
||||||
import {RouteParams, Router} from '@angular/router-deprecated';
|
import { Router, OnActivate, RouteSegment } from '@angular/router';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
template: `
|
template: `
|
||||||
|
@ -20,27 +20,26 @@ import {RouteParams, Router} from '@angular/router-deprecated';
|
||||||
</div>
|
</div>
|
||||||
`,
|
`,
|
||||||
})
|
})
|
||||||
export class HeroDetailComponent implements OnInit {
|
export class HeroDetailComponent implements OnActivate {
|
||||||
hero: Hero;
|
hero: Hero;
|
||||||
|
|
||||||
// #docregion ctor
|
// #docregion ctor
|
||||||
constructor(
|
constructor(
|
||||||
private _router:Router,
|
private router: Router,
|
||||||
private _routeParams:RouteParams,
|
private service: HeroService) {}
|
||||||
private _service:HeroService){}
|
|
||||||
// #enddocregion ctor
|
// #enddocregion ctor
|
||||||
|
|
||||||
// #docregion ngOnInit
|
// #docregion OnActivate
|
||||||
ngOnInit() {
|
routerOnActivate(curr: RouteSegment): void {
|
||||||
let id = this._routeParams.get('id');
|
let id = +curr.getParam('id');
|
||||||
this._service.getHero(id).then(hero => this.hero = hero);
|
this.service.getHero(id).then(hero => this.hero = hero);
|
||||||
}
|
}
|
||||||
// #enddocregion ngOnInit
|
// #enddocregion OnActivate
|
||||||
|
|
||||||
// #docregion gotoHeroes
|
// #docregion gotoHeroes
|
||||||
gotoHeroes() {
|
gotoHeroes() {
|
||||||
// Like <a [routerLink]="['Heroes']">Heroes</a>
|
// Like <a [routerLink]="['/heroes']">Heroes</a>
|
||||||
this._router.navigate(['Heroes']);
|
this.router.navigate(['/heroes']);
|
||||||
}
|
}
|
||||||
// #enddocregion gotoHeroes
|
// #enddocregion gotoHeroes
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
// #docregion
|
// #docregion
|
||||||
import {Component, OnInit} from '@angular/core';
|
import { Component } from '@angular/core';
|
||||||
import {Hero, HeroService} from './hero.service';
|
import { Hero, HeroService } from './hero.service';
|
||||||
import {RouteParams, Router} from '@angular/router-deprecated';
|
import { Router, OnActivate, RouteSegment } from '@angular/router';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
template: `
|
template: `
|
||||||
|
@ -20,32 +20,30 @@ import {RouteParams, Router} from '@angular/router-deprecated';
|
||||||
</div>
|
</div>
|
||||||
`,
|
`,
|
||||||
})
|
})
|
||||||
export class HeroDetailComponent implements OnInit {
|
export class HeroDetailComponent implements OnActivate {
|
||||||
hero: Hero;
|
hero: Hero;
|
||||||
|
|
||||||
// #docregion ctor
|
// #docregion ctor
|
||||||
constructor(
|
constructor(
|
||||||
private _router:Router,
|
private router: Router,
|
||||||
private _routeParams:RouteParams,
|
private service: HeroService) {}
|
||||||
private _service:HeroService){}
|
|
||||||
// #enddocregion ctor
|
// #enddocregion ctor
|
||||||
|
|
||||||
// #docregion ngOnInit
|
|
||||||
ngOnInit() {
|
|
||||||
let id = this._routeParams.get('id');
|
|
||||||
this._service.getHero(id).then(hero => this.hero = hero);
|
|
||||||
}
|
|
||||||
// #enddocregion ngOnInit
|
|
||||||
|
|
||||||
// #docregion gotoHeroes
|
// #docregion OnActivate
|
||||||
|
routerOnActivate(curr: RouteSegment): void {
|
||||||
|
let id = +curr.getParam('id');
|
||||||
|
this.service.getHero(id).then(hero => this.hero = hero);
|
||||||
|
}
|
||||||
|
// #enddocregion OnActivate
|
||||||
|
|
||||||
gotoHeroes() {
|
gotoHeroes() {
|
||||||
let heroId = this.hero ? this.hero.id : null;
|
let heroId = this.hero ? this.hero.id : null;
|
||||||
// Pass along the hero id if available
|
// Pass along the hero id if available
|
||||||
// so that the HeroList component can select that hero.
|
// so that the HeroList component can select that hero.
|
||||||
// Add a totally useless `foo` parameter for kicks.
|
// Add a totally useless `foo` parameter for kicks.
|
||||||
// #docregion gotoHeroes-navigate
|
// #docregion gotoHeroes-navigate
|
||||||
this._router.navigate(['Heroes', {id: heroId, foo: 'foo'} ]);
|
this.router.navigate([`/heroes`, {id: heroId, foo: 'foo'}]);
|
||||||
// #enddocregion gotoHeroes-navigate
|
// #enddocregion gotoHeroes-navigate
|
||||||
}
|
}
|
||||||
// #enddocregion gotoHeroes
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
// #docplaster
|
// #docplaster
|
||||||
|
|
||||||
// #docregion
|
// #docregion
|
||||||
// TODO SOMEDAY: Feature Componetized like HeroCenter
|
// TODO SOMEDAY: Feature Componetized like HeroCenter
|
||||||
import {Component, OnInit} from '@angular/core';
|
import {Component, OnInit} from '@angular/core';
|
||||||
|
@ -24,18 +23,18 @@ export class HeroListComponent implements OnInit {
|
||||||
|
|
||||||
// #docregion ctor
|
// #docregion ctor
|
||||||
constructor(
|
constructor(
|
||||||
private _router: Router,
|
private router: Router,
|
||||||
private _service: HeroService) { }
|
private service: HeroService) { }
|
||||||
// #enddocregion ctor
|
// #enddocregion ctor
|
||||||
|
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
this._service.getHeroes().then(heroes => this.heroes = heroes)
|
this.service.getHeroes().then(heroes => this.heroes = heroes)
|
||||||
}
|
}
|
||||||
|
|
||||||
// #docregion select
|
// #docregion select
|
||||||
onSelect(hero: Hero) {
|
onSelect(hero: Hero) {
|
||||||
// #docregion nav-to-detail
|
// #docregion nav-to-detail
|
||||||
this._router.navigate( ['HeroDetail', { id: hero.id }] );
|
this.router.navigate(['/hero', hero.id]);
|
||||||
// #enddocregion nav-to-detail
|
// #enddocregion nav-to-detail
|
||||||
}
|
}
|
||||||
// #enddocregion select
|
// #enddocregion select
|
||||||
|
@ -43,7 +42,7 @@ export class HeroListComponent implements OnInit {
|
||||||
// #enddocregion
|
// #enddocregion
|
||||||
|
|
||||||
/* A link parameters array
|
/* A link parameters array
|
||||||
// #docregion link-parameters-array
|
// #docregion link-parameters-array
|
||||||
['HeroDetail', { id: hero.id }] // {id: 15}
|
['HeroDetail', { id: hero.id }] // {id: 15}
|
||||||
// #enddocregion link-parameters-array
|
// #enddocregion link-parameters-array
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -1,11 +1,10 @@
|
||||||
// #docplaster
|
// #docplaster
|
||||||
|
|
||||||
// TODO SOMEDAY: Feature Componetized like CrisisCenter
|
|
||||||
// #docregion
|
// #docregion
|
||||||
import {Component, OnInit} from '@angular/core';
|
// TODO SOMEDAY: Feature Componetized like CrisisCenter
|
||||||
import {Hero, HeroService} from './hero.service';
|
import { Component } from '@angular/core';
|
||||||
|
import { Hero, HeroService} from './hero.service';
|
||||||
// #docregion import-route-params
|
// #docregion import-route-params
|
||||||
import {Router, RouteParams} from '@angular/router-deprecated';
|
import { Router, RouteSegment, Tree, OnActivate, RouteTree } from '@angular/router';
|
||||||
// #enddocregion import-route-params
|
// #enddocregion import-route-params
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
|
@ -22,32 +21,31 @@ import {Router, RouteParams} from '@angular/router-deprecated';
|
||||||
`
|
`
|
||||||
// #enddocregion template
|
// #enddocregion template
|
||||||
})
|
})
|
||||||
export class HeroListComponent implements OnInit {
|
export class HeroListComponent implements OnActivate {
|
||||||
heroes: Hero[];
|
heroes: Hero[];
|
||||||
|
|
||||||
// #docregion ctor
|
// #docregion ctor
|
||||||
private _selectedId: number;
|
private selectedId: number;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private _service: HeroService,
|
private service: HeroService,
|
||||||
private _router: Router,
|
private router: Router) { }
|
||||||
routeParams: RouteParams) {
|
|
||||||
this._selectedId = +routeParams.get('id');
|
|
||||||
}
|
|
||||||
// #enddocregion ctor
|
// #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);
|
||||||
|
}
|
||||||
|
|
||||||
// #docregion isSelected
|
// #docregion isSelected
|
||||||
isSelected(hero: Hero) { return hero.id === this._selectedId; }
|
isSelected(hero: Hero) { return hero.id === this.selectedId; }
|
||||||
// #enddocregion isSelected
|
// #enddocregion isSelected
|
||||||
|
|
||||||
// #docregion select
|
// #docregion select
|
||||||
onSelect(hero: Hero) {
|
onSelect(hero: Hero) {
|
||||||
this._router.navigate( ['HeroDetail', { id: hero.id }] );
|
this.router.navigate(['/hero', hero.id]);
|
||||||
}
|
}
|
||||||
// #enddocregion select
|
// #enddocregion select
|
||||||
|
|
||||||
ngOnInit() {
|
|
||||||
this._service.getHeroes().then(heroes => this.heroes = heroes)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
// #enddocregion
|
// #enddocregion
|
||||||
|
|
|
@ -5,6 +5,17 @@ export class Hero {
|
||||||
constructor(public id: number, public name: string) { }
|
constructor(public id: number, public name: string) { }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let HEROES = [
|
||||||
|
new Hero(11, 'Mr. Nice'),
|
||||||
|
new Hero(12, 'Narco'),
|
||||||
|
new Hero(13, 'Bombasto'),
|
||||||
|
new Hero(14, 'Celeritas'),
|
||||||
|
new Hero(15, 'Magneta'),
|
||||||
|
new Hero(16, 'RubberMan')
|
||||||
|
];
|
||||||
|
|
||||||
|
let heroesPromise = Promise.resolve(HEROES);
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class HeroService {
|
export class HeroService {
|
||||||
getHeroes() { return heroesPromise; }
|
getHeroes() { return heroesPromise; }
|
||||||
|
@ -14,14 +25,3 @@ export class HeroService {
|
||||||
.then(heroes => heroes.filter(h => h.id === +id)[0]);
|
.then(heroes => heroes.filter(h => h.id === +id)[0]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var HEROES = [
|
|
||||||
new Hero(11, 'Mr. Nice'),
|
|
||||||
new Hero(12, 'Narco'),
|
|
||||||
new Hero(13, 'Bombasto'),
|
|
||||||
new Hero(14, 'Celeritas'),
|
|
||||||
new Hero(15, 'Magneta'),
|
|
||||||
new Hero(16, 'RubberMan')
|
|
||||||
];
|
|
||||||
|
|
||||||
var heroesPromise = Promise.resolve(HEROES);
|
|
||||||
|
|
|
@ -2,10 +2,10 @@
|
||||||
// #docplaster
|
// #docplaster
|
||||||
|
|
||||||
// #docregion all
|
// #docregion all
|
||||||
import {AppComponent} from './app.component';
|
import { bootstrap } from '@angular/platform-browser-dynamic';
|
||||||
import {bootstrap} from '@angular/platform-browser-dynamic';
|
import { ROUTER_PROVIDERS } from '@angular/router';
|
||||||
import {ROUTER_PROVIDERS} from '@angular/router-deprecated';
|
|
||||||
|
|
||||||
|
import { AppComponent } from './app.component';
|
||||||
// #enddocregion all
|
// #enddocregion all
|
||||||
|
|
||||||
/* Can't use AppComponent ... but display as if we can
|
/* Can't use AppComponent ... but display as if we can
|
||||||
|
@ -15,9 +15,9 @@ bootstrap(AppComponent, [
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// Actually use the v.1 component
|
// Actually use the v.1 component
|
||||||
import {AppComponent as ac} from './app.component.1';
|
import { AppComponent as ac } from './app.component.1';
|
||||||
bootstrap(ac, [
|
bootstrap(ac, [
|
||||||
// #docregion all
|
// #docregion all
|
||||||
ROUTER_PROVIDERS
|
ROUTER_PROVIDERS
|
||||||
]);
|
]);
|
||||||
// #enddocregion all
|
// #enddocregion all
|
||||||
|
|
|
@ -4,14 +4,15 @@
|
||||||
// #docplaster
|
// #docplaster
|
||||||
|
|
||||||
// #docregion
|
// #docregion
|
||||||
import {bootstrap} from '@angular/platform-browser-dynamic';
|
import { bootstrap } from '@angular/platform-browser-dynamic';
|
||||||
import {ROUTER_PROVIDERS} from '@angular/router-deprecated';
|
import { ROUTER_PROVIDERS } from '@angular/router';
|
||||||
import {AppComponent} from './app.component';
|
|
||||||
|
import { AppComponent } from './app.component';
|
||||||
|
|
||||||
// Add these symbols to override the `LocationStrategy`
|
// Add these symbols to override the `LocationStrategy`
|
||||||
import {provide} from '@angular/core';
|
import { provide } from '@angular/core';
|
||||||
import {LocationStrategy,
|
import { LocationStrategy,
|
||||||
HashLocationStrategy} from '@angular/common';
|
HashLocationStrategy } from '@angular/common';
|
||||||
// #enddocregion
|
// #enddocregion
|
||||||
/* Can't use AppComponent ... but display as if we can
|
/* Can't use AppComponent ... but display as if we can
|
||||||
// #docregion
|
// #docregion
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
// #docregion
|
// #docregion
|
||||||
import {bootstrap} from '@angular/platform-browser-dynamic';
|
import { bootstrap } from '@angular/platform-browser-dynamic';
|
||||||
import {ROUTER_PROVIDERS} from '@angular/router-deprecated';
|
import { ROUTER_PROVIDERS } from '@angular/router';
|
||||||
|
|
||||||
import {AppComponent} from './app.component.3';
|
import { AppComponent } from './app.component.3';
|
||||||
|
|
||||||
bootstrap(AppComponent, [ROUTER_PROVIDERS]);
|
bootstrap(AppComponent, [ROUTER_PROVIDERS]);
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
// #docregion
|
// #docregion
|
||||||
import {bootstrap} from '@angular/platform-browser-dynamic';
|
import { bootstrap } from '@angular/platform-browser-dynamic';
|
||||||
import {ROUTER_PROVIDERS} from '@angular/router-deprecated';
|
import { ROUTER_PROVIDERS } from '@angular/router';
|
||||||
|
|
||||||
import {AppComponent} from './app.component';
|
import { AppComponent } from './app.component';
|
||||||
|
|
||||||
bootstrap(AppComponent, [ROUTER_PROVIDERS]);
|
bootstrap(AppComponent, [ROUTER_PROVIDERS]);
|
||||||
|
|
|
@ -2,9 +2,7 @@
|
||||||
<!-- #docregion -->
|
<!-- #docregion -->
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<!-- #docregion base-href -->
|
|
||||||
<base href="/">
|
<base href="/">
|
||||||
<!-- #enddocregion base-href -->
|
|
||||||
<title>Router Sample v.2</title>
|
<title>Router Sample v.2</title>
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
@ -29,5 +27,10 @@
|
||||||
<my-app>loading...</my-app>
|
<my-app>loading...</my-app>
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<h1>Milestone 2</h1>
|
||||||
|
<my-app>loading...</my-app>
|
||||||
|
</body>
|
||||||
|
|
||||||
</html>
|
</html>
|
||||||
<!-- #enddocregion -->
|
<!-- #enddocregion -->
|
||||||
|
|
|
@ -2,10 +2,8 @@
|
||||||
<!-- #docregion -->
|
<!-- #docregion -->
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<!-- #docregion base-href -->
|
|
||||||
<base href="/">
|
<base href="/">
|
||||||
<!-- #enddocregion base-href -->
|
<title>Router Sample v.3</title>
|
||||||
<title>Router Sample v.4</title>
|
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
<link rel="stylesheet" href="styles.css">
|
<link rel="stylesheet" href="styles.css">
|
||||||
|
|
|
@ -1,12 +1,10 @@
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<!-- #docregion -->
|
<!-- #docregion -->
|
||||||
|
<html>
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<!-- Set the base href -->
|
<!-- Set the base href -->
|
||||||
<!-- #docregion base-href -->
|
|
||||||
<base href="/">
|
<base href="/">
|
||||||
<!-- #enddocregion base-href -->
|
|
||||||
<meta charset="UTF-8">
|
|
||||||
<title>Router Sample</title>
|
<title>Router Sample</title>
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
|
|
@ -27,8 +27,8 @@
|
||||||
'@angular/http',
|
'@angular/http',
|
||||||
'@angular/platform-browser',
|
'@angular/platform-browser',
|
||||||
'@angular/platform-browser-dynamic',
|
'@angular/platform-browser-dynamic',
|
||||||
|
'@angular/router',
|
||||||
'@angular/router-deprecated',
|
'@angular/router-deprecated',
|
||||||
'@angular/testing',
|
|
||||||
'@angular/upgrade',
|
'@angular/upgrade',
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
|
@ -29,8 +29,8 @@
|
||||||
'@angular/http',
|
'@angular/http',
|
||||||
'@angular/platform-browser',
|
'@angular/platform-browser',
|
||||||
'@angular/platform-browser-dynamic',
|
'@angular/platform-browser-dynamic',
|
||||||
|
'@angular/router',
|
||||||
'@angular/router-deprecated',
|
'@angular/router-deprecated',
|
||||||
'@angular/testing',
|
|
||||||
'@angular/upgrade',
|
'@angular/upgrade',
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
|
@ -100,9 +100,15 @@
|
||||||
"intro": "Pipes transform displayed values within a template."
|
"intro": "Pipes transform displayed values within a template."
|
||||||
},
|
},
|
||||||
|
|
||||||
|
"router-deprecated": {
|
||||||
|
"title": "Beta Router (Deprecated)",
|
||||||
|
"intro": "The deprecated Beta Router."
|
||||||
|
},
|
||||||
|
|
||||||
"router": {
|
"router": {
|
||||||
"title": "Routing & Navigation",
|
"title": "Routing & Navigation",
|
||||||
"intro": "Discover the basics of screen navigation with the Angular 2 router."
|
"intro": "Discover the basics of screen navigation with the Angular 2 router.",
|
||||||
|
"hide": true
|
||||||
},
|
},
|
||||||
|
|
||||||
"structural-directives": {
|
"structural-directives": {
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
!= partial("../../../_includes/_ts-temp")
|
|
@ -99,9 +99,15 @@
|
||||||
"intro": "Pipes transform displayed values within a template."
|
"intro": "Pipes transform displayed values within a template."
|
||||||
},
|
},
|
||||||
|
|
||||||
|
"router-deprecated": {
|
||||||
|
"title": "Beta Router (Deprecated)",
|
||||||
|
"intro": "The deprecated Beta Router."
|
||||||
|
},
|
||||||
|
|
||||||
"router": {
|
"router": {
|
||||||
"title": "Routing & Navigation",
|
"title": "Routing & Navigation",
|
||||||
"intro": "Discover the basics of screen navigation with the Angular 2 router."
|
"intro": "Discover the basics of screen navigation with the Angular 2 router.",
|
||||||
|
"hide": true
|
||||||
},
|
},
|
||||||
|
|
||||||
"structural-directives": {
|
"structural-directives": {
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
!= partial("../../../_includes/_ts-temp")
|
|
@ -99,9 +99,16 @@
|
||||||
"intro": "Pipes transform displayed values within a template."
|
"intro": "Pipes transform displayed values within a template."
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
|
"router-deprecated": {
|
||||||
|
"title": "Beta Router (Deprecated)",
|
||||||
|
"intro": "The deprecated Beta Router."
|
||||||
|
},
|
||||||
|
|
||||||
"router": {
|
"router": {
|
||||||
"title": "Routing & Navigation",
|
"title": "Routing & Navigation",
|
||||||
"intro": "Discover the basics of screen navigation with the Angular 2 router."
|
"intro": "Discover the basics of screen navigation with the Angular 2 Component Router.",
|
||||||
|
"hide": true
|
||||||
},
|
},
|
||||||
|
|
||||||
"structural-directives": {
|
"structural-directives": {
|
||||||
|
|
|
@ -1,185 +0,0 @@
|
||||||
//
|
|
||||||
TODO: REVIVE AUX ROUTE MATERIAL WHEN THAT FEATURE WORKS AS EXPECTED
|
|
||||||
|
|
||||||
PLEASE DO NOT CREATE ISSUES OR PULL REQUESTS FOR THIS PAGE
|
|
||||||
|
|
||||||
<a id="chat-feature"></a>
|
|
||||||
.l-main-section
|
|
||||||
:marked
|
|
||||||
## Milestone #4: Auxiliary Routes
|
|
||||||
Auxiliary routes are routes that can be activated independently of the current
|
|
||||||
route. They are entirely optional, depending on your app needs.
|
|
||||||
|
|
||||||
For example, your application may have a modal that appears and this could
|
|
||||||
be an auxiliary route. The modal may have its own navigation needs, such as a slideshow
|
|
||||||
and that auxiliary route is able to manage the navigation stack independently of the
|
|
||||||
primary routes.
|
|
||||||
|
|
||||||
In our sample application, we also want to have a chat feature that allows people
|
|
||||||
the ability to have a live agent assist them. The chat window will have first an
|
|
||||||
initial route that contains a prompt to ask the visitor if they'd like to chat with
|
|
||||||
an agent. Once they initiate a chat, they go to a new route for the chat experience.
|
|
||||||
|
|
||||||
.alert.is-critical Make diagram of chat routes
|
|
||||||
|
|
||||||
:marked
|
|
||||||
In this auxiliary chat experience, it overlays the current screen and persists.
|
|
||||||
If you navigate from the Heroes to Crisis Center, the chat auxiliary route remains
|
|
||||||
active and in view.
|
|
||||||
|
|
||||||
Therefore the auxiliary routing is truly independent of the other
|
|
||||||
routing. In most respects, an auxiliary route behaves the same outside of it is rendered
|
|
||||||
in its own outlet and modifies the url differently.
|
|
||||||
|
|
||||||
We'll look at how to setup an auxiliary route and considerations for when to use them.
|
|
||||||
|
|
||||||
### Auxiliary Route Outlet
|
|
||||||
In order to get an auxiliary route, it needs a place to be rendered. So far the app has
|
|
||||||
a single `RouterOutet` that the rest of our routes are rendered into. Auxiliary routes need to
|
|
||||||
have their own `RouterOutlet`, and that is done by giving it a name attribute. Open the
|
|
||||||
`app.component.ts` file and let's add the new outlet to the template.
|
|
||||||
.alert.is-critical Should remove app.component.4.ts based example (next) when we know what's what
|
|
||||||
+_makeExample('router/ts/app/app.component.4.ts', 'chat-outlet', 'app/app.component.ts')
|
|
||||||
.alert.is-critical Should be able to project from app.component.ts like this
|
|
||||||
+_makeExample('router/ts/app/app.component.ts', 'template', 'app/app.component.ts (excerpt)')
|
|
||||||
:marked
|
|
||||||
The name of the outlet must be unique to the component. You could reuse the name across
|
|
||||||
different components, so you don't have to worry about collisions.
|
|
||||||
|
|
||||||
Here we give it a name of "chat", which will be used by the router when we setup our
|
|
||||||
route configs. The app component needs to know about this Auxiliary route, so we
|
|
||||||
import the `ChatComponent`, add a new ROUTE_NAME (`chat`),
|
|
||||||
and add a new 'Chat' route to the `ROUTES` in `app.routes.ts` (just below the redirect) .
|
|
||||||
+_makeExample('router/ts/app/routes.ts', null, 'app/routes.ts')
|
|
||||||
:marked
|
|
||||||
Look again at the 'Chat' route
|
|
||||||
+_makeExample('router/ts/app/routes.ts','chat-route')
|
|
||||||
:marked
|
|
||||||
You can see the route definition is nearly the same, except instead of `path` there is
|
|
||||||
an `aux`. The `aux` property makes this an Auxiliary route.
|
|
||||||
|
|
||||||
@TODO Explain how a named outlet is paired with an aux route.
|
|
||||||
|
|
||||||
The chat component defines its own routes just like the other components, even though
|
|
||||||
it is an Auxiliary route.
|
|
||||||
|
|
||||||
+_makeExample('router/ts/app/chat/routes.ts', null, 'app/chat/routes.ts')
|
|
||||||
:marked
|
|
||||||
Even though this is an Auxiliary route, you notice there is no difference in how we've
|
|
||||||
configured the route config for the primary chat component. The chat component also has
|
|
||||||
the `RouterOutlet` Directive in the template so the child components render inside of
|
|
||||||
the chat window.
|
|
||||||
|
|
||||||
In the chat components, we can use `RouterLink` to reference routes just the same as
|
|
||||||
a normal route. Since this is inside of an Auxiliary route, these relative links will
|
|
||||||
resolve within the chat component and not change the primary route (the Crisis Center or
|
|
||||||
Heroes pages).
|
|
||||||
|
|
||||||
+_makeExample('router/ts/app/chat/chat-init.component.ts', 'chat-links')
|
|
||||||
|
|
||||||
:marked
|
|
||||||
When the chat component opens, it first initializes this template to ask the user if
|
|
||||||
they'd like to chat or not. If they agree, it takes them to the chat window where they
|
|
||||||
begin to send messages to the 'live' agent.
|
|
||||||
|
|
||||||
The behavior of the chat components may be interesting, but have no additional insights
|
|
||||||
for routing, except for the ability to deactivate an active Auxiliary route.
|
|
||||||
|
|
||||||
### Exiting an Auxiliary Route
|
|
||||||
|
|
||||||
@TODO Figure out how to close/deactivate an aux route
|
|
||||||
|
|
||||||
### Auxiliary Route URLs
|
|
||||||
|
|
||||||
Auxiliary Routes do modify the url using parens, like so.
|
|
||||||
code-example(format=".", language="bash").
|
|
||||||
localhost:3002/crisis-center(chat)/2(details)
|
|
||||||
:marked
|
|
||||||
This would be the url on a page where the user was viewing an item in the Crisis Center,
|
|
||||||
in this case the "Dragon Burning Cities" crisis, and the `(chat)` Auxiliary Route would
|
|
||||||
active and on the details child route.
|
|
||||||
|
|
||||||
### Multiple Auxiliary Routes
|
|
||||||
|
|
||||||
There is no limit to how many Auxiliary Routes you have defined or active. There is probably
|
|
||||||
a practical limit where too much appears on the screen for a user, but you can have as many
|
|
||||||
Auxiliary Routes as you have named `RouteOutlet`s.
|
|
||||||
|
|
||||||
:marked
|
|
||||||
### Auxiliary Route Summary
|
|
||||||
|
|
||||||
* Auxiliary routes are normal routes that are rendered outside of the primary `RouterOutlet`
|
|
||||||
* They must use a named `RouterOutlet` to render.
|
|
||||||
* Can be activated as long as the parent component is active.
|
|
||||||
* Links inside of child components are resolved against the aux parent component.
|
|
||||||
* Auxiliary routes are deactivated by @TODO?
|
|
||||||
* Routes are indicated in the url using parens.
|
|
||||||
* Multiple aux routes can be active at once.
|
|
||||||
|
|
||||||
### Chat
|
|
||||||
The "Chat" feature area within the `chat` folder looks like this:
|
|
||||||
```
|
|
||||||
app/
|
|
||||||
chat/
|
|
||||||
├── chat-detail.component.ts
|
|
||||||
├── chat-init.component.ts
|
|
||||||
├── chat.component.ts
|
|
||||||
├── chat.service.ts
|
|
||||||
└── routes.ts
|
|
||||||
```
|
|
||||||
+_makeTabs(
|
|
||||||
`router/ts/app/chat/chat.component.ts,
|
|
||||||
router/ts/app/chat/routes.ts,
|
|
||||||
router/ts/app/chat/chat-init.component.ts,
|
|
||||||
router/ts/app/chat/chat-detail.component.ts,
|
|
||||||
router/ts/app/chat/chat.service.ts
|
|
||||||
`,
|
|
||||||
null,
|
|
||||||
`chat.component.ts,
|
|
||||||
chat/routes.ts,
|
|
||||||
chat-init.component.ts,
|
|
||||||
chat-detail.component.ts,
|
|
||||||
chat.service.ts,
|
|
||||||
`)
|
|
||||||
|
|
||||||
|
|
||||||
The following are styles extracted from `styles.css`
|
|
||||||
that only belong if/when we add chat back
|
|
||||||
```
|
|
||||||
/* chat styles */
|
|
||||||
.chat {
|
|
||||||
position: fixed;
|
|
||||||
bottom: 0;
|
|
||||||
right: 20px;
|
|
||||||
border: 1px solid #1171a3;
|
|
||||||
width: 400px;
|
|
||||||
height: 300px;
|
|
||||||
}
|
|
||||||
.chat h2 {
|
|
||||||
background: #1171a3;
|
|
||||||
color: #fff;
|
|
||||||
margin: 0;
|
|
||||||
padding: 8px;
|
|
||||||
}
|
|
||||||
.chat .close {
|
|
||||||
float: right;
|
|
||||||
display: block;
|
|
||||||
padding: 0 10px;
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
.chat .chat-content {
|
|
||||||
padding: 10px;
|
|
||||||
}
|
|
||||||
.chat .chat-messages {
|
|
||||||
height: 190px;
|
|
||||||
overflow-y: scroll;
|
|
||||||
}
|
|
||||||
.chat .chat-input {
|
|
||||||
border-top: 1px solid #ccc;
|
|
||||||
padding-top: 10px;
|
|
||||||
}
|
|
||||||
.chat .chat-input input {
|
|
||||||
width: 370px;
|
|
||||||
padding: 3px;
|
|
||||||
}
|
|
||||||
```
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,4 +1,10 @@
|
||||||
include ../_util-fns
|
include ../_util-fns
|
||||||
|
.alert.is-critical
|
||||||
|
:marked
|
||||||
|
This chapter is a *work in progress*.
|
||||||
|
|
||||||
|
It describes the *release candidate* Component Router which
|
||||||
|
replaces the [*beta* router](router-deprecated.html).
|
||||||
|
|
||||||
:marked
|
:marked
|
||||||
The Angular ***Component Router*** enables navigation from one [view](./glossary.html#view) to the next
|
The Angular ***Component Router*** enables navigation from one [view](./glossary.html#view) to the next
|
||||||
|
@ -65,7 +71,7 @@ include ../_util-fns
|
||||||
|
|
||||||
If the `app` folder is the application root, as it is for our sample application,
|
If the `app` folder is the application root, as it is for our sample application,
|
||||||
set the `href` value *exactly* as shown here.
|
set the `href` value *exactly* as shown here.
|
||||||
+makeExample('router/ts/index.html','base-href', 'index.html (base href)')(format=".")
|
+makeExample('router/ts/index.1.html','base-href', 'index.html (base href)')(format=".")
|
||||||
|
|
||||||
:marked
|
:marked
|
||||||
### Router imports
|
### Router imports
|
||||||
|
@ -299,7 +305,7 @@ figure.image-display
|
||||||
If the `app` folder is the application root, as it is for our application,
|
If the `app` folder is the application root, as it is for our application,
|
||||||
set the `href` value in **`index.html`** *exactly* as shown here.
|
set the `href` value in **`index.html`** *exactly* as shown here.
|
||||||
|
|
||||||
+makeExample('router/ts/index.html','base-href', 'index.html (base href)')(format=".")
|
+makeExample('router/ts/index.1.html','base-href', 'index.html (base href)')(format=".")
|
||||||
.l-sub-section
|
.l-sub-section
|
||||||
:marked
|
:marked
|
||||||
HTML 5 style navigation is the Component Router default.
|
HTML 5 style navigation is the Component Router default.
|
||||||
|
@ -1443,7 +1449,7 @@ code-example(format=".", language="bash").
|
||||||
The preferred way to configure the strategy is to add a
|
The preferred way to configure the strategy is to add a
|
||||||
[<base href> element](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/base) tag
|
[<base href> element](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/base) tag
|
||||||
in the `<head>` of the `index.html`.
|
in the `<head>` of the `index.html`.
|
||||||
+makeExample('router/ts/index.html','base-href')(format=".")
|
+makeExample('router/ts/index.1.html','base-href')(format=".")
|
||||||
:marked
|
:marked
|
||||||
Without that tag, the browser may not be able to load resources
|
Without that tag, the browser may not be able to load resources
|
||||||
(images, css, scripts) when "deep linking" into the app.
|
(images, css, scripts) when "deep linking" into the app.
|
||||||
|
|
Loading…
Reference in New Issue