docs(aio): Updated usage of Observables in router guide. Added section for advanced redirects (#18197)
PR Close #18197
This commit is contained in:

committed by
Miško Hevery

parent
fa6b802be4
commit
53be85a7fb
@ -12,13 +12,13 @@ describe('Router', () => {
|
||||
beforeAll(() => browser.get(''));
|
||||
|
||||
function getPageStruct() {
|
||||
const hrefEles = element.all(by.css('my-app a'));
|
||||
const hrefEles = element.all(by.css('my-app > nav a'));
|
||||
const crisisDetail = element.all(by.css('my-app > ng-component > ng-component > ng-component > div')).first();
|
||||
const heroDetail = element(by.css('my-app > ng-component > div'));
|
||||
|
||||
return {
|
||||
hrefs: hrefEles,
|
||||
activeHref: element(by.css('my-app a.active')),
|
||||
activeHref: element(by.css('my-app > nav a.active')),
|
||||
|
||||
crisisHref: hrefEles.get(0),
|
||||
crisisList: element.all(by.css('my-app > ng-component > ng-component li')),
|
||||
|
@ -15,6 +15,10 @@
|
||||
height: 1.6em;
|
||||
border-radius: 4px;
|
||||
}
|
||||
.items li a {
|
||||
display: block;
|
||||
text-decoration: none;
|
||||
}
|
||||
.items li:hover {
|
||||
color: #607D8B;
|
||||
background-color: #DDD;
|
||||
|
@ -28,7 +28,7 @@ const appRoutes: Routes = [
|
||||
data: { preload: true }
|
||||
},
|
||||
// #enddocregion preload-v2
|
||||
{ path: '', redirectTo: '/heroes', pathMatch: 'full' },
|
||||
{ path: '', redirectTo: '/superheroes', pathMatch: 'full' },
|
||||
{ path: '**', component: PageNotFoundComponent }
|
||||
];
|
||||
|
||||
|
23
aio/content/examples/router/src/app/app.component.6.ts
Normal file
23
aio/content/examples/router/src/app/app.component.6.ts
Normal file
@ -0,0 +1,23 @@
|
||||
// #docplaster
|
||||
// #docregion
|
||||
import { Component } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'my-app',
|
||||
// #docregion template
|
||||
template: `
|
||||
<h1 class="title">Angular Router</h1>
|
||||
<nav>
|
||||
<a routerLink="/crisis-center" routerLinkActive="active">Crisis Center</a>
|
||||
<a routerLink="/heroes" routerLinkActive="active">Heroes</a>
|
||||
<a routerLink="/admin" routerLinkActive="active">Admin</a>
|
||||
<a routerLink="/login" routerLinkActive="active">Login</a>
|
||||
<a [routerLink]="[{ outlets: { popup: ['compose'] } }]">Contact</a>
|
||||
</nav>
|
||||
<router-outlet></router-outlet>
|
||||
<router-outlet name="popup"></router-outlet>
|
||||
`
|
||||
// #enddocregion template
|
||||
})
|
||||
export class AppComponent {
|
||||
}
|
@ -9,7 +9,7 @@ import { Component } from '@angular/core';
|
||||
<h1 class="title">Angular Router</h1>
|
||||
<nav>
|
||||
<a routerLink="/crisis-center" routerLinkActive="active">Crisis Center</a>
|
||||
<a routerLink="/heroes" routerLinkActive="active">Heroes</a>
|
||||
<a routerLink="/superheroes" routerLinkActive="active">Heroes</a>
|
||||
<a routerLink="/admin" routerLinkActive="active">Admin</a>
|
||||
<a routerLink="/login" routerLinkActive="active">Login</a>
|
||||
<a [routerLink]="[{ outlets: { popup: ['compose'] } }]">Contact</a>
|
||||
|
@ -1,5 +1,6 @@
|
||||
// #docregion
|
||||
import { Injectable } from '@angular/core';
|
||||
import { Observable } from 'rxjs/Observable';
|
||||
import { CanDeactivate,
|
||||
ActivatedRouteSnapshot,
|
||||
RouterStateSnapshot } from '@angular/router';
|
||||
@ -13,7 +14,7 @@ export class CanDeactivateGuard implements CanDeactivate<CrisisDetailComponent>
|
||||
component: CrisisDetailComponent,
|
||||
route: ActivatedRouteSnapshot,
|
||||
state: RouterStateSnapshot
|
||||
): Promise<boolean> | boolean {
|
||||
): Observable<boolean> | boolean {
|
||||
// Get the Crisis Center ID
|
||||
console.log(route.paramMap.get('id'));
|
||||
|
||||
@ -25,7 +26,7 @@ export class CanDeactivateGuard implements CanDeactivate<CrisisDetailComponent>
|
||||
return true;
|
||||
}
|
||||
// Otherwise ask the user with the dialog service and return its
|
||||
// promise which resolves to true or false when the user decides
|
||||
// observable which resolves to true or false when the user decides
|
||||
return component.dialogService.confirm('Discard changes?');
|
||||
}
|
||||
}
|
||||
|
@ -1,18 +1,21 @@
|
||||
// #docregion
|
||||
import 'rxjs/add/operator/map';
|
||||
import 'rxjs/add/operator/take';
|
||||
import { Injectable } from '@angular/core';
|
||||
import { Observable } from 'rxjs/Observable';
|
||||
import { Router, Resolve, RouterStateSnapshot,
|
||||
ActivatedRouteSnapshot } from '@angular/router';
|
||||
|
||||
import { Crisis, CrisisService } from './crisis.service';
|
||||
import { Crisis, CrisisService } from './crisis.service';
|
||||
|
||||
@Injectable()
|
||||
export class CrisisDetailResolver implements Resolve<Crisis> {
|
||||
constructor(private cs: CrisisService, private router: Router) {}
|
||||
|
||||
resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Promise<Crisis> {
|
||||
resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<Crisis> {
|
||||
let id = route.paramMap.get('id');
|
||||
|
||||
return this.cs.getCrisis(id).then(crisis => {
|
||||
return this.cs.getCrisis(id).take(1).map(crisis => {
|
||||
if (crisis) {
|
||||
return crisis;
|
||||
} else { // id not found
|
||||
|
@ -1,8 +1,9 @@
|
||||
// #docplaster
|
||||
// #docregion
|
||||
import 'rxjs/add/operator/switchMap';
|
||||
import { Component, OnInit, HostBinding } from '@angular/core';
|
||||
import { Component, OnInit, HostBinding } from '@angular/core';
|
||||
import { ActivatedRoute, Router, ParamMap } from '@angular/router';
|
||||
import { Observable } from 'rxjs/Observable';
|
||||
|
||||
import { slideInDownAnimation } from '../animations';
|
||||
import { Crisis, CrisisService } from './crisis.service';
|
||||
@ -45,7 +46,8 @@ export class CrisisDetailComponent implements OnInit {
|
||||
// #docregion ngOnInit
|
||||
ngOnInit() {
|
||||
this.route.paramMap
|
||||
.switchMap((params: ParamMap) => this.service.getCrisis(params.get('id')))
|
||||
.switchMap((params: ParamMap) =>
|
||||
this.service.getCrisis(params.get('id')))
|
||||
.subscribe((crisis: Crisis) => {
|
||||
if (crisis) {
|
||||
this.editName = crisis.name;
|
||||
@ -66,13 +68,13 @@ export class CrisisDetailComponent implements OnInit {
|
||||
this.gotoCrises();
|
||||
}
|
||||
|
||||
canDeactivate(): Promise<boolean> | boolean {
|
||||
canDeactivate(): Observable<boolean> | boolean {
|
||||
// Allow synchronous navigation (`true`) if no crisis or the crisis is unchanged
|
||||
if (!this.crisis || this.crisis.name === this.editName) {
|
||||
return true;
|
||||
}
|
||||
// Otherwise ask the user with the dialog service and return its
|
||||
// promise which resolves to true or false when the user decides
|
||||
// observable which resolves to true or false when the user decides
|
||||
return this.dialogService.confirm('Discard changes?');
|
||||
}
|
||||
|
||||
|
@ -2,6 +2,7 @@
|
||||
// #docregion
|
||||
import { Component, OnInit, HostBinding } from '@angular/core';
|
||||
import { ActivatedRoute, Router } from '@angular/router';
|
||||
import { Observable } from 'rxjs/Observable';
|
||||
|
||||
import { slideInDownAnimation } from '../animations';
|
||||
import { Crisis } from './crisis.service';
|
||||
@ -62,13 +63,13 @@ export class CrisisDetailComponent implements OnInit {
|
||||
// #enddocregion cancel-save
|
||||
|
||||
// #docregion canDeactivate
|
||||
canDeactivate(): Promise<boolean> | boolean {
|
||||
canDeactivate(): Observable<boolean> | boolean {
|
||||
// Allow synchronous navigation (`true`) if no crisis or the crisis is unchanged
|
||||
if (!this.crisis || this.crisis.name === this.editName) {
|
||||
return true;
|
||||
}
|
||||
// Otherwise ask the user with the dialog service and return its
|
||||
// promise which resolves to true or false when the user decides
|
||||
// observable which resolves to true or false when the user decides
|
||||
return this.dialogService.confirm('Discard changes?');
|
||||
}
|
||||
// #enddocregion canDeactivate
|
||||
|
@ -1,7 +1,7 @@
|
||||
import 'rxjs/add/operator/do';
|
||||
|
||||
import 'rxjs/add/operator/switchMap';
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { ActivatedRoute, Router, ParamMap } from '@angular/router';
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { ActivatedRoute, ParamMap } from '@angular/router';
|
||||
|
||||
import { Crisis, CrisisService } from './crisis.service';
|
||||
import { Observable } from 'rxjs/Observable';
|
||||
@ -10,35 +10,34 @@ import { Observable } from 'rxjs/Observable';
|
||||
// #docregion relative-navigation-router-link
|
||||
template: `
|
||||
<ul class="items">
|
||||
<li *ngFor="let crisis of crises | async">
|
||||
<a [routerLink]="[crisis.id]"
|
||||
[class.selected]="isSelected(crisis)">
|
||||
<span class="badge">{{ crisis.id }}</span>
|
||||
{{ crisis.name }}
|
||||
<li *ngFor="let crisis of crises$ | async"
|
||||
[class.selected]="crisis.id === selectedId">
|
||||
<a [routerLink]="[crisis.id]">
|
||||
<span class="badge">{{ crisis.id }}</span>{{ crisis.name }}
|
||||
</a>
|
||||
</li>
|
||||
</ul>`
|
||||
</ul>
|
||||
|
||||
<router-outlet></router-outlet>
|
||||
`
|
||||
// #enddocregion relative-navigation-router-link
|
||||
})
|
||||
export class CrisisListComponent implements OnInit {
|
||||
crises: Observable<Crisis[]>;
|
||||
crises$: Observable<Crisis[]>;
|
||||
selectedId: number;
|
||||
|
||||
|
||||
constructor(
|
||||
private service: CrisisService,
|
||||
private route: ActivatedRoute,
|
||||
private router: Router
|
||||
private route: ActivatedRoute
|
||||
) {}
|
||||
|
||||
|
||||
ngOnInit() {
|
||||
this.crises = this.route.paramMap
|
||||
this.crises$ = this.route.paramMap
|
||||
.switchMap((params: ParamMap) => {
|
||||
this.selectedId = +params.get('id');
|
||||
return this.service.getCrises();
|
||||
});
|
||||
}
|
||||
|
||||
isSelected(crisis: Crisis) {
|
||||
return crisis.id === this.selectedId;
|
||||
}
|
||||
}
|
||||
|
@ -1,20 +1,19 @@
|
||||
// #docregion
|
||||
import 'rxjs/add/operator/switchMap';
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { ActivatedRoute, Router, ParamMap } from '@angular/router';
|
||||
|
||||
import { Observable } from 'rxjs/Observable';
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { ActivatedRoute, ParamMap } from '@angular/router';
|
||||
|
||||
import { Crisis, CrisisService } from './crisis.service';
|
||||
import { Observable } from 'rxjs/Observable';
|
||||
|
||||
@Component({
|
||||
template: `
|
||||
<ul class="items">
|
||||
<li *ngFor="let crisis of crises | async"
|
||||
(click)="onSelect(crisis)"
|
||||
[class.selected]="isSelected(crisis)">
|
||||
<span class="badge">{{ crisis.id }}</span>
|
||||
{{ crisis.name }}
|
||||
<li *ngFor="let crisis of crises$ | async"
|
||||
[class.selected]="crisis.id === selectedId">
|
||||
<a [routerLink]="[crisis.id]">
|
||||
<span class="badge">{{ crisis.id }}</span>{{ crisis.name }}
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
@ -22,35 +21,21 @@ import { Crisis, CrisisService } from './crisis.service';
|
||||
`
|
||||
})
|
||||
export class CrisisListComponent implements OnInit {
|
||||
crises: Observable<Crisis[]>;
|
||||
crises$: Observable<Crisis[]>;
|
||||
selectedId: number;
|
||||
|
||||
// #docregion ctor
|
||||
constructor(
|
||||
private service: CrisisService,
|
||||
private route: ActivatedRoute,
|
||||
private router: Router
|
||||
private route: ActivatedRoute
|
||||
) {}
|
||||
// #enddocregion ctor
|
||||
|
||||
isSelected(crisis: Crisis) {
|
||||
return crisis.id === this.selectedId;
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
this.crises = this.route.paramMap
|
||||
this.crises$ = this.route.paramMap
|
||||
.switchMap((params: ParamMap) => {
|
||||
this.selectedId = +params.get('id');
|
||||
return this.service.getCrises();
|
||||
});
|
||||
}
|
||||
|
||||
// #docregion onSelect
|
||||
onSelect(crisis: Crisis) {
|
||||
this.selectedId = crisis.id;
|
||||
|
||||
// Navigate with relative link
|
||||
this.router.navigate([crisis.id], { relativeTo: this.route });
|
||||
}
|
||||
// #enddocregion onSelect
|
||||
}
|
||||
|
@ -1,5 +1,9 @@
|
||||
// #docplaster
|
||||
// #docregion , mock-crises
|
||||
import 'rxjs/add/observable/of';
|
||||
import 'rxjs/add/operator/map';
|
||||
import { BehaviorSubject } from 'rxjs/BehaviorSubject';
|
||||
|
||||
export class Crisis {
|
||||
constructor(public id: number, public name: string) { }
|
||||
}
|
||||
@ -12,20 +16,18 @@ const CRISES = [
|
||||
];
|
||||
// #enddocregion mock-crises
|
||||
|
||||
let crisesPromise = Promise.resolve(CRISES);
|
||||
|
||||
import { Injectable } from '@angular/core';
|
||||
|
||||
@Injectable()
|
||||
export class CrisisService {
|
||||
|
||||
static nextCrisisId = 100;
|
||||
private crises$: BehaviorSubject<Crisis[]> = new BehaviorSubject<Crisis[]>(CRISES);
|
||||
|
||||
getCrises() { return crisesPromise; }
|
||||
getCrises() { return this.crises$; }
|
||||
|
||||
getCrisis(id: number | string) {
|
||||
return crisesPromise
|
||||
.then(crises => crises.find(crisis => crisis.id === +id));
|
||||
return this.getCrises()
|
||||
.map(crises => crises.find(crisis => crisis.id === +id));
|
||||
}
|
||||
|
||||
// #enddocregion
|
||||
@ -33,7 +35,8 @@ export class CrisisService {
|
||||
name = name.trim();
|
||||
if (name) {
|
||||
let crisis = new Crisis(CrisisService.nextCrisisId++, name);
|
||||
crisesPromise.then(crises => crises.push(crisis));
|
||||
CRISES.push(crisis);
|
||||
this.crises$.next(CRISES);
|
||||
}
|
||||
}
|
||||
// #docregion
|
||||
|
@ -1,5 +1,8 @@
|
||||
// #docregion
|
||||
import 'rxjs/add/observable/of';
|
||||
import { Injectable } from '@angular/core';
|
||||
import { Observable } from 'rxjs/Observable';
|
||||
|
||||
/**
|
||||
* Async modal dialog service
|
||||
* DialogService makes this app easier to test by faking this service.
|
||||
@ -9,11 +12,11 @@ import { Injectable } from '@angular/core';
|
||||
export class DialogService {
|
||||
/**
|
||||
* Ask user to confirm an action. `message` explains the action and choices.
|
||||
* Returns promise resolving to `true`=confirm or `false`=cancel
|
||||
* Returns observable resolving to `true`=confirm or `false`=cancel
|
||||
*/
|
||||
confirm(message?: string) {
|
||||
return new Promise<boolean>(resolve => {
|
||||
return resolve(window.confirm(message || 'Is it OK?'));
|
||||
});
|
||||
confirm(message?: string): Observable<boolean> {
|
||||
const confirmation = window.confirm(message || 'Is it OK?');
|
||||
|
||||
return Observable.of(confirmation);
|
||||
};
|
||||
}
|
||||
|
@ -4,6 +4,7 @@
|
||||
import 'rxjs/add/operator/switchMap';
|
||||
// #enddocregion rxjs-operator-import
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { Observable } from 'rxjs/Observable';
|
||||
// #docregion imports
|
||||
import { Router, ActivatedRoute, ParamMap } from '@angular/router';
|
||||
// #enddocregion imports
|
||||
@ -13,7 +14,7 @@ import { Hero, HeroService } from './hero.service';
|
||||
@Component({
|
||||
template: `
|
||||
<h2>HEROES</h2>
|
||||
<div *ngIf="hero">
|
||||
<div *ngIf="hero$ | async as hero">
|
||||
<h3>"{{ hero.name }}"</h3>
|
||||
<div>
|
||||
<label>Id: </label>{{ hero.id }}</div>
|
||||
@ -28,7 +29,7 @@ import { Hero, HeroService } from './hero.service';
|
||||
`
|
||||
})
|
||||
export class HeroDetailComponent implements OnInit {
|
||||
hero: Hero;
|
||||
hero$: Observable<Hero>;
|
||||
|
||||
// #docregion ctor
|
||||
constructor(
|
||||
@ -40,10 +41,9 @@ export class HeroDetailComponent implements OnInit {
|
||||
|
||||
// #docregion ngOnInit
|
||||
ngOnInit() {
|
||||
this.route.paramMap
|
||||
this.hero$ = this.route.paramMap
|
||||
.switchMap((params: ParamMap) =>
|
||||
this.service.getHero(params.get('id')))
|
||||
.subscribe((hero: Hero) => this.hero = hero);
|
||||
this.service.getHero(params.get('id')));
|
||||
}
|
||||
// #enddocregion ngOnInit
|
||||
|
||||
|
@ -2,13 +2,14 @@
|
||||
// #docregion
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { ActivatedRoute, Router } from '@angular/router';
|
||||
import { Observable } from 'rxjs/Observable';
|
||||
|
||||
import { Hero, HeroService } from './hero.service';
|
||||
|
||||
@Component({
|
||||
template: `
|
||||
<h2>HEROES</h2>
|
||||
<div *ngIf="hero">
|
||||
<div *ngIf="hero$ | async as hero">
|
||||
<h3>"{{ hero.name }}"</h3>
|
||||
<div>
|
||||
<label>Id: </label>{{ hero.id }}</div>
|
||||
@ -23,7 +24,7 @@ import { Hero, HeroService } from './hero.service';
|
||||
`
|
||||
})
|
||||
export class HeroDetailComponent implements OnInit {
|
||||
hero: Hero;
|
||||
hero$: Observable<Hero>;
|
||||
|
||||
constructor(
|
||||
private route: ActivatedRoute,
|
||||
@ -35,8 +36,7 @@ export class HeroDetailComponent implements OnInit {
|
||||
ngOnInit() {
|
||||
let id = this.route.snapshot.paramMap.get('id');
|
||||
|
||||
this.service.getHero(id)
|
||||
.then((hero: Hero) => this.hero = hero);
|
||||
this.hero$ = this.service.getHero(id);
|
||||
}
|
||||
// #enddocregion snapshot
|
||||
|
||||
|
@ -4,6 +4,7 @@
|
||||
import 'rxjs/add/operator/switchMap';
|
||||
// #enddocregion rxjs-operator-import
|
||||
import { Component, OnInit, HostBinding } from '@angular/core';
|
||||
import { Observable } from 'rxjs/Observable';
|
||||
import { Router, ActivatedRoute, ParamMap } from '@angular/router';
|
||||
|
||||
import { slideInDownAnimation } from '../animations';
|
||||
@ -13,7 +14,7 @@ import { Hero, HeroService } from './hero.service';
|
||||
@Component({
|
||||
template: `
|
||||
<h2>HEROES</h2>
|
||||
<div *ngIf="hero">
|
||||
<div *ngIf="hero$ | async as hero">
|
||||
<h3>"{{ hero.name }}"</h3>
|
||||
<div>
|
||||
<label>Id: </label>{{ hero.id }}</div>
|
||||
@ -22,7 +23,7 @@ import { Hero, HeroService } from './hero.service';
|
||||
<input [(ngModel)]="hero.name" placeholder="name"/>
|
||||
</div>
|
||||
<p>
|
||||
<button (click)="gotoHeroes()">Back</button>
|
||||
<button (click)="gotoHeroes(hero)">Back</button>
|
||||
</p>
|
||||
</div>
|
||||
`,
|
||||
@ -35,7 +36,7 @@ export class HeroDetailComponent implements OnInit {
|
||||
@HostBinding('style.position') position = 'absolute';
|
||||
// #enddocregion host-bindings
|
||||
|
||||
hero: Hero;
|
||||
hero$: Observable<Hero>;
|
||||
|
||||
// #docregion ctor
|
||||
constructor(
|
||||
@ -47,16 +48,15 @@ export class HeroDetailComponent implements OnInit {
|
||||
|
||||
// #docregion ngOnInit
|
||||
ngOnInit() {
|
||||
this.route.paramMap
|
||||
this.hero$ = this.route.paramMap
|
||||
.switchMap((params: ParamMap) =>
|
||||
this.service.getHero(params.get('id')))
|
||||
.subscribe((hero: Hero) => this.hero = hero);
|
||||
this.service.getHero(params.get('id')));
|
||||
}
|
||||
// #enddocregion ngOnInit
|
||||
|
||||
// #docregion gotoHeroes
|
||||
gotoHeroes() {
|
||||
let heroId = this.hero ? this.hero.id : null;
|
||||
gotoHeroes(hero: Hero) {
|
||||
let heroId = hero ? hero.id : null;
|
||||
// Pass along the hero id if available
|
||||
// so that the HeroList component can select that hero.
|
||||
// Include a junk 'foo' property for fun.
|
||||
|
@ -3,6 +3,7 @@
|
||||
// TODO SOMEDAY: Feature Componetized like HeroCenter
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { Router } from '@angular/router';
|
||||
import { Observable } from 'rxjs/Observable';
|
||||
|
||||
import { Hero, HeroService } from './hero.service';
|
||||
|
||||
@ -11,9 +12,12 @@ import { Hero, HeroService } from './hero.service';
|
||||
template: `
|
||||
<h2>HEROES</h2>
|
||||
<ul class="items">
|
||||
<li *ngFor="let hero of heroes | async"
|
||||
(click)="onSelect(hero)">
|
||||
<span class="badge">{{ hero.id }}</span> {{ hero.name }}
|
||||
<li *ngFor="let hero of heroes$ | async">
|
||||
// #docregion nav-to-detail
|
||||
<a [routerLink]="['/hero', hero.id]">
|
||||
<span class="badge">{{ hero.id }}</span>{{ hero.name }}
|
||||
</a>
|
||||
// #enddocregion nav-to-detail
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
@ -22,7 +26,7 @@ import { Hero, HeroService } from './hero.service';
|
||||
// #enddocregion template
|
||||
})
|
||||
export class HeroListComponent implements OnInit {
|
||||
heroes: Promise<Hero[]>;
|
||||
heroes$: Observable<Hero[]>;
|
||||
|
||||
// #docregion ctor
|
||||
constructor(
|
||||
@ -32,16 +36,8 @@ export class HeroListComponent implements OnInit {
|
||||
// #enddocregion ctor
|
||||
|
||||
ngOnInit() {
|
||||
this.heroes = this.service.getHeroes();
|
||||
this.heroes$ = this.service.getHeroes();
|
||||
}
|
||||
|
||||
// #docregion select
|
||||
onSelect(hero: Hero) {
|
||||
// #docregion nav-to-detail
|
||||
this.router.navigate(['/hero', hero.id]);
|
||||
// #enddocregion nav-to-detail
|
||||
}
|
||||
// #enddocregion select
|
||||
}
|
||||
// #enddocregion
|
||||
|
||||
|
@ -7,7 +7,7 @@ import { Observable } from 'rxjs/Observable';
|
||||
// #enddocregion rxjs-imports
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
// #docregion import-router
|
||||
import { Router, ActivatedRoute, ParamMap } from '@angular/router';
|
||||
import { ActivatedRoute, ParamMap } from '@angular/router';
|
||||
// #enddocregion import-router
|
||||
|
||||
import { Hero, HeroService } from './hero.service';
|
||||
@ -17,10 +17,11 @@ import { Hero, HeroService } from './hero.service';
|
||||
template: `
|
||||
<h2>HEROES</h2>
|
||||
<ul class="items">
|
||||
<li *ngFor="let hero of heroes | async"
|
||||
[class.selected]="isSelected(hero)"
|
||||
(click)="onSelect(hero)">
|
||||
<span class="badge">{{ hero.id }}</span> {{ hero.name }}
|
||||
<li *ngFor="let hero of heroes$ | async"
|
||||
[class.selected]="hero.id === selectedId">
|
||||
<a [routerLink]="['/hero', hero.id]">
|
||||
<span class="badge">{{ hero.id }}</span>{{ hero.name }}
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
@ -30,18 +31,17 @@ import { Hero, HeroService } from './hero.service';
|
||||
})
|
||||
// #docregion ctor
|
||||
export class HeroListComponent implements OnInit {
|
||||
heroes: Observable<Hero[]>;
|
||||
heroes$: Observable<Hero[]>;
|
||||
|
||||
private selectedId: number;
|
||||
|
||||
constructor(
|
||||
private service: HeroService,
|
||||
private route: ActivatedRoute,
|
||||
private router: Router
|
||||
private route: ActivatedRoute
|
||||
) {}
|
||||
|
||||
ngOnInit() {
|
||||
this.heroes = this.route.paramMap
|
||||
this.heroes$ = this.route.paramMap
|
||||
.switchMap((params: ParamMap) => {
|
||||
// (+) before `params.get()` turns the string into a number
|
||||
this.selectedId = +params.get('id');
|
||||
@ -49,16 +49,6 @@ export class HeroListComponent implements OnInit {
|
||||
});
|
||||
}
|
||||
// #enddocregion ctor
|
||||
|
||||
// #docregion isSelected
|
||||
isSelected(hero: Hero) { return hero.id === this.selectedId; }
|
||||
// #enddocregion isSelected
|
||||
|
||||
// #docregion select
|
||||
onSelect(hero: Hero) {
|
||||
this.router.navigate(['/hero', hero.id]);
|
||||
}
|
||||
// #enddocregion select
|
||||
// #docregion ctor
|
||||
}
|
||||
// #enddocregion
|
||||
|
@ -1,11 +1,14 @@
|
||||
// #docregion
|
||||
import 'rxjs/add/observable/of';
|
||||
import 'rxjs/add/operator/map';
|
||||
import { Injectable } from '@angular/core';
|
||||
import { Observable } from 'rxjs/Observable';
|
||||
|
||||
export class Hero {
|
||||
constructor(public id: number, public name: string) { }
|
||||
}
|
||||
|
||||
let HEROES = [
|
||||
const HEROES = [
|
||||
new Hero(11, 'Mr. Nice'),
|
||||
new Hero(12, 'Narco'),
|
||||
new Hero(13, 'Bombasto'),
|
||||
@ -14,15 +17,13 @@ let HEROES = [
|
||||
new Hero(16, 'RubberMan')
|
||||
];
|
||||
|
||||
let heroesPromise = Promise.resolve(HEROES);
|
||||
|
||||
@Injectable()
|
||||
export class HeroService {
|
||||
getHeroes() { return heroesPromise; }
|
||||
getHeroes() { return Observable.of(HEROES); }
|
||||
|
||||
getHero(id: number | string) {
|
||||
return heroesPromise
|
||||
return this.getHeroes()
|
||||
// (+) before `id` turns the string into a number
|
||||
.then(heroes => heroes.find(hero => hero.id === +id));
|
||||
.map(heroes => heroes.find(hero => hero.id === +id));
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,24 @@
|
||||
// #docregion
|
||||
import { NgModule } from '@angular/core';
|
||||
import { RouterModule, Routes } from '@angular/router';
|
||||
|
||||
import { HeroListComponent } from './hero-list.component';
|
||||
import { HeroDetailComponent } from './hero-detail.component';
|
||||
|
||||
const heroesRoutes: Routes = [
|
||||
{ path: 'heroes', component: HeroListComponent },
|
||||
// #docregion hero-detail-route
|
||||
{ path: 'hero/:id', component: HeroDetailComponent }
|
||||
// #enddocregion hero-detail-route
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
RouterModule.forChild(heroesRoutes)
|
||||
],
|
||||
exports: [
|
||||
RouterModule
|
||||
]
|
||||
})
|
||||
export class HeroRoutingModule { }
|
||||
// #enddocregion
|
@ -6,10 +6,10 @@ import { HeroListComponent } from './hero-list.component';
|
||||
import { HeroDetailComponent } from './hero-detail.component';
|
||||
|
||||
const heroesRoutes: Routes = [
|
||||
{ path: 'heroes', component: HeroListComponent },
|
||||
// #docregion hero-detail-route
|
||||
{ path: 'hero/:id', component: HeroDetailComponent }
|
||||
// #enddocregion hero-detail-route
|
||||
{ path: 'heroes', redirectTo: '/superheroes' },
|
||||
{ path: 'hero/:id', redirectTo: '/superhero/:id' },
|
||||
{ path: 'superheroes', component: HeroListComponent },
|
||||
{ path: 'superhero/:id', component: HeroDetailComponent }
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
|
Reference in New Issue
Block a user