docs(router): Added and organized more router dev guide content

Moved all heroes functionality into milestone 2
Crisis Center initial functionality is milestone 3
Admin feature module as milestone 4 including route guard examples
Updated milestone 5 to lazy load admin feature module
Added examples for CanLoad, CanActivateChildren guard, component-less routes
Added section on explanation of ActivatedRoute
Added section on animating route components
Added section on relative navigation
This commit is contained in:
Brandon Roberts 2016-08-26 23:19:27 -05:00 committed by Naomi Black
parent 4d46d7c1e4
commit c15a68e591
53 changed files with 1422 additions and 757 deletions

View File

@ -16,8 +16,8 @@ describe('Router', function () {
crisisHref: hrefEles.get(0), crisisHref: hrefEles.get(0),
crisisList: element.all(by.css('my-app > ng-component > ng-component li')), crisisList: element.all(by.css('my-app > ng-component > ng-component li')),
crisisDetail: element(by.css('my-app > ng-component > ng-component > div')), crisisDetail: element(by.css('my-app > ng-component > ng-component > ng-component > div')),
crisisDetailTitle: element(by.css('my-app > ng-component > ng-component > div > h3')), crisisDetailTitle: element(by.css('my-app > ng-component > ng-component > ng-component > div > h3')),
heroesHref: hrefEles.get(1), heroesHref: hrefEles.get(1),
heroesList: element.all(by.css('my-app > ng-component li')), heroesList: element.all(by.css('my-app > ng-component li')),
@ -34,7 +34,7 @@ describe('Router', function () {
expect(page.hrefs.count()).toEqual(4, 'should be 4 dashboard choices'); expect(page.hrefs.count()).toEqual(4, 'should be 4 dashboard choices');
expect(page.crisisHref.getText()).toEqual('Crisis Center'); expect(page.crisisHref.getText()).toEqual('Crisis Center');
expect(page.heroesHref.getText()).toEqual('Heroes'); expect(page.heroesHref.getText()).toEqual('Heroes');
expect(page.adminHref.getText()).toEqual('Crisis Admin'); expect(page.adminHref.getText()).toEqual('Admin');
expect(page.loginHref.getText()).toEqual('Login'); expect(page.loginHref.getText()).toEqual('Login');
}); });
@ -118,7 +118,6 @@ describe('Router', function () {
crisisText = text.substr(text.indexOf(' ')).trim(); crisisText = text.substr(text.indexOf(' ')).trim();
return crisisEle.click(); return crisisEle.click();
}).then(function () { }).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.crisisDetail.isPresent()).toBe(true, 'should be able to see crisis detail');
expect(page.crisisDetailTitle.getText()).toContain(crisisText); expect(page.crisisDetailTitle.getText()).toContain(crisisText);
let inputEle = page.crisisDetail.element(by.css('input')); let inputEle = page.crisisDetail.element(by.css('input'));

View File

@ -0,0 +1,9 @@
// #docregion
import { Component } from '@angular/core';
@Component({
template: `
<p>Dashboard</p>
`
})
export class AdminDashboardComponent { }

View File

@ -6,15 +6,14 @@ import 'rxjs/add/operator/map';
@Component({ @Component({
template: ` template: `
<h3>CRISIS ADMINISTRATION</h3> <p>Dashboard</p>
<p>Manage your crises here</p>
<p>Session ID: {{ sessionId | async }}</p> <p>Session ID: {{ sessionId | async }}</p>
<a id="anchor"></a> <a id="anchor"></a>
<p>Token: {{ token | async }}</p> <p>Token: {{ token | async }}</p>
` `
}) })
export class CrisisAdminComponent implements OnInit { export class AdminDashboardComponent implements OnInit {
sessionId: Observable<string>; sessionId: Observable<string>;
token: Observable<string>; token: Observable<string>;

View File

@ -0,0 +1,17 @@
// #docregion
import { Component } from '@angular/core';
@Component({
template: `
<h3>ADMIN</h3>
<nav>
<a routerLink="./" routerLinkActive="active"
[routerLinkActiveOptions]="{ exact: true }">Dashboard</a>
<a routerLink="./crises" routerLinkActive="active">Manage Crises</a>
<a routerLink="./heroes" routerLinkActive="active">Manage Heroes</a>
</nav>
<router-outlet></router-outlet>
`
})
export class AdminComponent {
}

View File

@ -0,0 +1,28 @@
// #docplaster
// #docregion
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { AdminComponent } from './admin.component';
import { AdminDashboardComponent } from './admin-dashboard.component';
import { ManageCrisesComponent } from './manage-crises.component';
import { ManageHeroesComponent } from './manage-heroes.component';
import { adminRouting } from './admin.routing';
@NgModule({
imports: [
CommonModule,
adminRouting
],
declarations: [
AdminComponent,
AdminDashboardComponent,
ManageCrisesComponent,
ManageHeroesComponent
]
})
// #docregion admin-module-export
export class AdminModule {}
// #enddocregion admin-module-export
// #enddocregion

View File

@ -0,0 +1,31 @@
// #docplaster
// #docregion
import { ModuleWithProviders } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { AdminComponent } from './admin.component';
import { AdminDashboardComponent } from './admin-dashboard.component';
import { ManageCrisesComponent } from './manage-crises.component';
import { ManageHeroesComponent } from './manage-heroes.component';
// #docregion admin-routes
const adminRoutes: Routes = [
{
path: 'admin',
component: AdminComponent,
children: [
{
path: '',
children: [
{ path: 'crises', component: ManageCrisesComponent },
{ path: 'heroes', component: ManageHeroesComponent },
{ path: '', component: AdminDashboardComponent }
]
}
]
}
];
export const adminRouting: ModuleWithProviders = RouterModule.forChild(adminRoutes);
// #enddocregion admin-routes
// #enddocregion

View File

@ -0,0 +1,37 @@
// #docplaster
// #docregion
import { ModuleWithProviders } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { AdminComponent } from './admin.component';
import { AdminDashboardComponent } from './admin-dashboard.component';
import { ManageCrisesComponent } from './manage-crises.component';
import { ManageHeroesComponent } from './manage-heroes.component';
// #docregion admin-route, can-activate-child
import { AuthGuard } from '../auth-guard.service';
const adminRoutes: Routes = [
{
path: 'admin',
component: AdminComponent,
canActivate: [AuthGuard],
children: [
{
path: '',
children: [
{ path: 'crises', component: ManageCrisesComponent },
{ path: 'heroes', component: ManageHeroesComponent },
{ path: '', component: AdminDashboardComponent }
],
// #enddocregion admin-route
// #docregion can-activate-child
canActivateChild: [AuthGuard]
// #docregion admin-route
}
]
}
];
export const adminRouting: ModuleWithProviders = RouterModule.forChild(adminRoutes);
// #enddocregion

View File

@ -0,0 +1,35 @@
// #docplaster
// #docregion
import { ModuleWithProviders } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { AdminComponent } from './admin.component';
import { AdminDashboardComponent } from './admin-dashboard.component';
import { ManageCrisesComponent } from './manage-crises.component';
import { ManageHeroesComponent } from './manage-heroes.component';
// #docregion admin-route
import { AuthGuard } from '../auth-guard.service';
// #docregion can-activate-child
const adminRoutes: Routes = [
{
path: 'admin',
component: AdminComponent,
canActivate: [AuthGuard],
children: [
{
path: '',
canActivateChild: [AuthGuard],
children: [
{ path: 'crises', component: ManageCrisesComponent },
{ path: 'heroes', component: ManageHeroesComponent },
{ path: '', component: AdminDashboardComponent }
]
}
]
}
];
export const adminRouting: ModuleWithProviders = RouterModule.forChild(adminRoutes);
// #enddocregion

View File

@ -0,0 +1,34 @@
// #docplaster
// #docregion
import { ModuleWithProviders } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { AdminComponent } from './admin.component';
import { AdminDashboardComponent } from './admin-dashboard.component';
import { ManageCrisesComponent } from './manage-crises.component';
import { ManageHeroesComponent } from './manage-heroes.component';
// #docregion admin-route
import { AuthGuard } from '../auth-guard.service';
const adminRoutes: Routes = [
{
path: '',
component: AdminComponent,
canActivate: [AuthGuard],
children: [
{
path: '',
canActivateChild: [AuthGuard],
children: [
{ path: 'crises', component: ManageCrisesComponent },
{ path: 'heroes', component: ManageHeroesComponent },
{ path: '', component: AdminDashboardComponent }
]
}
]
}
];
export const adminRouting: ModuleWithProviders = RouterModule.forChild(adminRoutes);
// #enddocregion

View File

@ -3,8 +3,7 @@ import { Component } from '@angular/core';
@Component({ @Component({
template: ` template: `
<h3>CRISIS ADMINISTRATION</h3>
<p>Manage your crises here</p> <p>Manage your crises here</p>
` `
}) })
export class CrisisAdminComponent { } export class ManageCrisesComponent { }

View File

@ -0,0 +1,9 @@
// #docregion
import { Component } from '@angular/core';
@Component({
template: `
<p>Manage your heroes here</p>
`
})
export class ManageHeroesComponent { }

View File

@ -6,7 +6,7 @@ import { Component } from '@angular/core';
selector: 'my-app', selector: 'my-app',
// #docregion template // #docregion template
template: ` template: `
<h1>Component Router</h1> <h1>Angular Router</h1>
<nav> <nav>
<a routerLink="/crisis-center" routerLinkActive="active">Crisis Center</a> <a routerLink="/crisis-center" routerLinkActive="active">Crisis Center</a>
<a routerLink="/heroes" routerLinkActive="active">Heroes</a> <a routerLink="/heroes" routerLinkActive="active">Heroes</a>

View File

@ -7,7 +7,7 @@ import { Component } from '@angular/core';
@Component({ @Component({
selector: 'my-app', selector: 'my-app',
template: ` template: `
<h1>Component Router</h1> <h1>Angular Router</h1>
<nav> <nav>
<a routerLink="/crisis-center" routerLinkActive="active">Crisis Center</a> <a routerLink="/crisis-center" routerLinkActive="active">Crisis Center</a>
<a routerLink="/heroes" routerLinkActive="active">Heroes</a> <a routerLink="/heroes" routerLinkActive="active">Heroes</a>

View File

@ -1,7 +1,7 @@
/* tslint:disable:no-unused-variable */ /* tslint:disable:no-unused-variable */
// #docplaster // #docplaster
import { Component } from '@angular/core'; import { Component } from '@angular/core';
import { Router } from '@angular/router'; import { Router } from '@angular/router';
@Component({ @Component({
selector: 'my-app', selector: 'my-app',
@ -36,7 +36,7 @@ import { Router } from '@angular/router';
*/ */
// #docregion template // #docregion template
template: ` template: `
<h1 class="title">Component Router</h1> <h1 class="title">Angular Router</h1>
<nav> <nav>
<a [routerLink]="['/crisis-center']">Crisis Center</a> <a [routerLink]="['/crisis-center']">Crisis Center</a>
<a [routerLink]="['/crisis-center/1', { foo: 'foo' }]">Dragon Crisis</a> <a [routerLink]="['/crisis-center/1', { foo: 'foo' }]">Dragon Crisis</a>

View File

@ -1,16 +1,15 @@
// #docregion // #docregion
import { Component } from '@angular/core'; import { Component } from '@angular/core';
@Component({ @Component({
selector: 'my-app', selector: 'my-app',
// #docregion template // #docregion template
template: ` template: `
<h1 class="title">Component Router</h1> <h1 class="title">Angular Router</h1>
<nav> <nav>
<a routerLink="/crisis-center" routerLinkActive="active" <a routerLink="/crisis-center" routerLinkActive="active">Crisis Center</a>
[routerLinkActiveOptions]="{ exact: true }">Crisis Center</a>
<a routerLink="/heroes" routerLinkActive="active">Heroes</a> <a routerLink="/heroes" routerLinkActive="active">Heroes</a>
<a routerLink="/crisis-center/admin" routerLinkActive="active">Crisis Admin</a> <a routerLink="/admin" routerLinkActive="active">Admin</a>
</nav> </nav>
<router-outlet></router-outlet> <router-outlet></router-outlet>
` `

View File

@ -1,17 +1,16 @@
// #docplaster // #docplaster
// #docregion // #docregion
import { Component } from '@angular/core'; import { Component } from '@angular/core';
@Component({ @Component({
selector: 'my-app', selector: 'my-app',
// #docregion template // #docregion template
template: ` template: `
<h1 class="title">Component Router</h1> <h1 class="title">Angular Router</h1>
<nav> <nav>
<a routerLink="/crisis-center" routerLinkActive="active" <a routerLink="/crisis-center" routerLinkActive="active">Crisis Center</a>
[routerLinkActiveOptions]="{ exact: true }">Crisis Center</a>
<a routerLink="/heroes" routerLinkActive="active">Heroes</a> <a routerLink="/heroes" routerLinkActive="active">Heroes</a>
<a routerLink="/crisis-center/admin" routerLinkActive="active">Crisis Admin</a> <a routerLink="/admin" routerLinkActive="active">Admin</a>
<a routerLink="/login" routerLinkActive="active">Login</a> <a routerLink="/login" routerLinkActive="active">Login</a>
</nav> </nav>
<router-outlet></router-outlet> <router-outlet></router-outlet>

View File

@ -4,11 +4,10 @@ import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser'; import { BrowserModule } from '@angular/platform-browser';
import { FormsModule } from '@angular/forms'; import { FormsModule } from '@angular/forms';
// #docregion router-basics // #docregion router-basics
import { AppComponent } from './app.component'; import { AppComponent } from './app.component';
import { routing, import { routing,
appRoutingProviders } from './app.routing'; appRoutingProviders } from './app.routing';
import { HeroListComponent } from './hero-list.component'; import { HeroListComponent } from './hero-list.component';
import { CrisisListComponent } from './crisis-list.component'; import { CrisisListComponent } from './crisis-list.component';

View File

@ -1,14 +1,14 @@
// #docplaster // #docplaster
// #docregion // #docregion
// #docregion hero-import
import { NgModule } from '@angular/core'; import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser'; import { BrowserModule } from '@angular/platform-browser';
import { FormsModule } from '@angular/forms'; import { FormsModule } from '@angular/forms';
import { AppComponent } from './app.component'; import { AppComponent } from './app.component';
import { routing, import { routing,
appRoutingProviders } from './app.routing'; appRoutingProviders } from './app.routing';
// #docregion hero-import
import { HeroesModule } from './heroes/heroes.module'; import { HeroesModule } from './heroes/heroes.module';
import { CrisisListComponent } from './crisis-list.component'; import { CrisisListComponent } from './crisis-list.component';

View File

@ -1,24 +1,34 @@
// #docplaster
// #docregion // #docregion
// #docregion crisis-center-module, admin-module
import { NgModule } from '@angular/core'; import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser'; import { CommonModule } from '@angular/common';
import { FormsModule } from '@angular/forms'; import { FormsModule } from '@angular/forms';
import { AppComponent } from './app.component'; import { AppComponent } from './app.component';
import { routing, import { routing,
appRoutingProviders } from './app.routing'; appRoutingProviders } from './app.routing';
import { HeroesModule } from './heroes/heroes.module'; import { HeroesModule } from './heroes/heroes.module';
// #docregion crisis-center-module
import { CrisisCenterModule } from './crisis-center/crisis-center.module'; import { CrisisCenterModule } from './crisis-center/crisis-center.module';
// #enddocregion crisis-center-module
// #docregion admin-module
import { AdminModule } from './admin/admin.module';
// #docregion crisis-center-module
import { DialogService } from './dialog.service'; import { DialogService } from './dialog.service';
@NgModule({ @NgModule({
imports: [ imports: [
BrowserModule, CommonModule,
FormsModule, FormsModule,
routing, routing,
HeroesModule, HeroesModule,
CrisisCenterModule CrisisCenterModule,
// #enddocregion crisis-center-module
AdminModule
// #docregion crisis-center-module
], ],
declarations: [ declarations: [
AppComponent AppComponent
@ -31,3 +41,4 @@ import { DialogService } from './dialog.service';
}) })
export class AppModule { export class AppModule {
} }
// #enddocregion

View File

@ -2,25 +2,30 @@
import { NgModule } from '@angular/core'; import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser'; import { BrowserModule } from '@angular/platform-browser';
import { FormsModule } from '@angular/forms'; import { FormsModule } from '@angular/forms';
import { Routes, RouterModule } from '@angular/router';
import { AppComponent } from './app.component'; import { AppComponent } from './app.component';
import { routing,
appRoutingProviders } from './app.routing';
const routes: Routes = [ import { HeroesModule } from './heroes/heroes.module';
import { CrisisCenterModule } from './crisis-center/crisis-center.module';
]; import { DialogService } from './dialog.service';
@NgModule({ @NgModule({
imports: [ imports: [
BrowserModule, BrowserModule,
FormsModule, FormsModule,
RouterModule.forRoot(routes, { useHash: true }) // .../#/crisis-center/ routing,
HeroesModule,
CrisisCenterModule
], ],
declarations: [ declarations: [
AppComponent AppComponent
], ],
providers: [ providers: [
appRoutingProviders,
DialogService
], ],
bootstrap: [ AppComponent ] bootstrap: [ AppComponent ]
}) })

View File

@ -0,0 +1,28 @@
// #docregion
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { FormsModule } from '@angular/forms';
import { Routes, RouterModule } from '@angular/router';
import { AppComponent } from './app.component';
const routes: Routes = [
];
@NgModule({
imports: [
BrowserModule,
FormsModule,
RouterModule.forRoot(routes, { useHash: true }) // .../#/crisis-center/
],
declarations: [
AppComponent
],
providers: [
],
bootstrap: [ AppComponent ]
})
export class AppModule {
}

View File

@ -3,22 +3,24 @@ import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser'; import { BrowserModule } from '@angular/platform-browser';
import { FormsModule } from '@angular/forms'; import { FormsModule } from '@angular/forms';
import { AppComponent } from './app.component'; import { AppComponent } from './app.component';
import { routing, import { routing,
appRoutingProviders } from './app.routing'; appRoutingProviders } from './app.routing';
import { HeroesModule } from './heroes/heroes.module'; import { HeroesModule } from './heroes/heroes.module';
import { CrisisCenterModule } from './crisis-center/crisis-center.module';
import { LoginComponent } from './login.component'; import { LoginComponent } from './login.component';
import { DialogService } from './dialog.service'; import { DialogService } from './dialog.service';
@NgModule({ @NgModule({
imports: [ imports: [
BrowserModule, BrowserModule,
FormsModule, FormsModule,
routing, routing,
HeroesModule HeroesModule,
CrisisCenterModule
], ],
declarations: [ declarations: [
AppComponent, AppComponent,

View File

@ -12,12 +12,16 @@ import { HeroListComponent } from './hero-list.component';
import { CrisisCenterComponent } from './crisis-center/crisis-center.component'; import { CrisisCenterComponent } from './crisis-center/crisis-center.component';
import { HeroDetailComponent } from './heroes/hero-detail.component'; import { HeroDetailComponent } from './heroes/hero-detail.component';
import { PageNotFoundComponent } from './not-found.component'; import { PageNotFoundComponent } from './not-found.component';
import { PageNotFoundComponent as HomeComponent } from './not-found.component';
// #enddocregion base-routes // #enddocregion base-routes
// #docregion // #docregion
// #docregion route-config // #docregion route-config
const appRoutes: Routes = [ const appRoutes: Routes = [
// #docregion route-defs // #docregion route-defs
// #docregion hero-detail-route
{ path: 'hero/:id', component: HeroDetailComponent },
// #enddocregion hero-detail-route
{ path: 'crisis-center', component: CrisisCenterComponent }, { path: 'crisis-center', component: CrisisCenterComponent },
{ {
path: 'heroes', path: 'heroes',
@ -26,10 +30,8 @@ const appRoutes: Routes = [
title: 'Heroes List' title: 'Heroes List'
} }
}, },
{ path: '', component: HomeComponent },
// #enddocregion route-defs // #enddocregion route-defs
// #docregion hero-detail-route
{ path: 'hero/:id', component: HeroDetailComponent },
// #enddocregion hero-detail-route
{ path: '**', component: PageNotFoundComponent } { path: '**', component: PageNotFoundComponent }
]; ];

View File

@ -3,10 +3,10 @@
import { ModuleWithProviders } from '@angular/core'; import { ModuleWithProviders } from '@angular/core';
import { Routes, RouterModule } from '@angular/router'; import { Routes, RouterModule } from '@angular/router';
import { CrisisListComponent } from './crisis-center/crisis-list.component'; import { CrisisCenterComponent } from './crisis-center/crisis-center.component';
const appRoutes: Routes = [ const appRoutes: Routes = [
{ path: 'crisis-center', component: CrisisListComponent } { path: 'crisis-center', component: CrisisCenterComponent }
]; ];
export const appRoutingProviders: any[] = [ export const appRoutingProviders: any[] = [

View File

@ -9,24 +9,9 @@ import { loginRoutes,
import { CanDeactivateGuard } from './can-deactivate-guard.service'; import { CanDeactivateGuard } from './can-deactivate-guard.service';
// #docregion lazy-load-crisis-center
const crisisCenterRoutes: Routes = [
{
path: '',
redirectTo: '/crisis-center',
pathMatch: 'full'
},
{
path: 'crisis-center',
loadChildren: 'app/crisis-center/crisis-center.module#CrisisCenterModule'
}
];
const appRoutes: Routes = [ const appRoutes: Routes = [
...loginRoutes, ...loginRoutes
...crisisCenterRoutes
]; ];
// #enddocregion lazy-load-crisis-center
export const appRoutingProviders: any[] = [ export const appRoutingProviders: any[] = [
authProviders, authProviders,
@ -34,14 +19,3 @@ export const appRoutingProviders: any[] = [
]; ];
export const routing: ModuleWithProviders = RouterModule.forRoot(appRoutes); export const routing: ModuleWithProviders = RouterModule.forRoot(appRoutes);
// #enddocregion
/* A link parameters array
// #docregion heroes-redirect
{
path: '',
redirectTo: '/heroes',
pathMatch: 'full'
},
// #enddocregion heroes-redirect
*/

View File

@ -1,32 +1,36 @@
// #docplaster
// #docregion // #docregion
import { ModuleWithProviders } from '@angular/core'; import { ModuleWithProviders } from '@angular/core';
// #docregion import-router // #docregion import-router
import { Routes, RouterModule } from '@angular/router'; import { Routes, RouterModule } from '@angular/router';
// #enddocregion import-router // #enddocregion import-router
import { loginRoutes, import { loginRoutes,
authProviders } from './login.routing'; authProviders } from './login.routing';
import { CanDeactivateGuard } from './can-deactivate-guard.service'; import { CanDeactivateGuard } from './can-deactivate-guard.service';
// #docregion can-load-guard
import { AuthGuard } from './auth-guard.service';
// #enddocregion can-load-guard
// #docregion lazy-load-crisis-center // #docregion lazy-load-admin, can-load-guard
const crisisCenterRoutes: Routes = [
const adminRoutes: Routes = [
{ {
path: '', path: 'admin',
redirectTo: '/heroes', loadChildren: 'app/admin/admin.module#AdminModule',
pathMatch: 'full' // #enddocregion lazy-load-admin
}, canLoad: [AuthGuard]
{ // #docregion lazy-load-admin
path: 'crisis-center',
loadChildren: 'app/crisis-center/crisis-center.module#CrisisCenterModule'
} }
]; ];
// #enddocregion can-load-guard
const appRoutes: Routes = [ const appRoutes: Routes = [
...loginRoutes, ...loginRoutes,
...crisisCenterRoutes ...adminRoutes
]; ];
// #enddocregion lazy-load-crisis-center // #enddocregion lazy-load-admin
export const appRoutingProviders: any[] = [ export const appRoutingProviders: any[] = [
authProviders, authProviders,

View File

@ -1,22 +1,37 @@
// #docregion // #docregion
import { Injectable } from '@angular/core'; import { Injectable } from '@angular/core';
import { CanActivate, Router, import {
ActivatedRouteSnapshot, CanActivate, Router,
RouterStateSnapshot } from '@angular/router'; ActivatedRouteSnapshot,
import { AuthService } from './auth.service'; RouterStateSnapshot
} from '@angular/router';
import { AuthService } from './auth.service';
@Injectable() @Injectable()
export class AuthGuard implements CanActivate { export class AuthGuard implements CanActivate {
constructor(private authService: AuthService, private router: Router) {} constructor(private authService: AuthService, private router: Router) {}
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) { canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean {
let url: string = state.url;
return this.checkLogin(url);
}
checkLogin(url: string): boolean {
if (this.authService.isLoggedIn) { return true; } if (this.authService.isLoggedIn) { return true; }
// Store the attempted URL for redirecting // Store the attempted URL for redirecting
this.authService.redirectUrl = state.url; this.authService.redirectUrl = url;
// Navigate to the login page // Navigate to the login page with extras
this.router.navigate(['/login']); this.router.navigate(['/login']);
return false; return false;
} }
} }
// #enddocregion
/*
// #docregion can-load-interface
export class AuthGuard implements CanActivate, CanLoad {
// #enddocregion can-load-interface
*/

View File

@ -0,0 +1,40 @@
// #docplaster
// #docregion
// #docregion can-activate-child
import { Injectable } from '@angular/core';
import {
CanActivate, Router,
ActivatedRouteSnapshot,
RouterStateSnapshot,
CanActivateChild
} from '@angular/router';
import { AuthService } from './auth.service';
@Injectable()
export class AuthGuard implements CanActivate, CanActivateChild {
constructor(private authService: AuthService, private router: Router) {}
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean {
let url: string = state.url;
return this.checkLogin(url);
}
canActivateChild(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean {
return this.canActivate(route, state);
}
// #enddocregion can-activate-child
checkLogin(url: string): boolean {
if (this.authService.isLoggedIn) { return true; }
// Store the attempted URL for redirecting
this.authService.redirectUrl = url;
// Navigate to the login page
this.router.navigate(['/login']);
return false;
}
// #docregion can-activate-child
}
// #enddocregion

View File

@ -0,0 +1,47 @@
// #docplaster
// #docregion
import { Injectable } from '@angular/core';
import {
CanActivate, Router,
ActivatedRouteSnapshot,
RouterStateSnapshot,
CanActivateChild,
NavigationExtras
} from '@angular/router';
import { AuthService } from './auth.service';
@Injectable()
export class AuthGuard implements CanActivate, CanActivateChild {
constructor(private authService: AuthService, private router: Router) {}
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean {
let url: string = state.url;
return this.checkLogin(url);
}
canActivateChild(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean {
return this.canActivate(route, state);
}
checkLogin(url: string): boolean {
if (this.authService.isLoggedIn) { return true; }
// Store the attempted URL for redirecting
this.authService.redirectUrl = url;
// Create a dummy session id
let sessionId = 123456789;
// Set our navigation extras object
// that contains our global query params and fragment
let navigationExtras: NavigationExtras = {
queryParams: { 'session_id': sessionId },
fragment: 'anchor'
};
// Navigate to the login page with extras
this.router.navigate(['/login'], navigationExtras);
return false;
}
}

View File

@ -1,20 +1,42 @@
// #docregion // #docplaster
import { Injectable } from '@angular/core'; // #docregion, admin-can-load
import { CanActivate, Router, import { Injectable } from '@angular/core';
ActivatedRouteSnapshot, import {
RouterStateSnapshot, CanActivate, Router,
NavigationExtras } from '@angular/router'; ActivatedRouteSnapshot,
import { AuthService } from './auth.service'; RouterStateSnapshot,
CanActivateChild,
NavigationExtras,
CanLoad, Route
} from '@angular/router';
import { AuthService } from './auth.service';
@Injectable() @Injectable()
export class AuthGuard implements CanActivate { export class AuthGuard implements CanActivate, CanActivateChild, CanLoad {
constructor(private authService: AuthService, private router: Router) {} constructor(private authService: AuthService, private router: Router) {}
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) { canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean {
let url: string = state.url;
return this.checkLogin(url);
}
canActivateChild(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean {
return this.canActivate(route, state);
}
canLoad(route: Route): boolean {
let url = `/${route.path}`;
return this.checkLogin(url);
}
// #enddocregion admin-can-load
checkLogin(url: string): boolean {
if (this.authService.isLoggedIn) { return true; } if (this.authService.isLoggedIn) { return true; }
// Store the attempted URL for redirecting // Store the attempted URL for redirecting
this.authService.redirectUrl = state.url; this.authService.redirectUrl = url;
// Create a dummy session id // Create a dummy session id
let sessionId = 123456789; let sessionId = 123456789;
@ -30,4 +52,5 @@ export class AuthGuard implements CanActivate {
this.router.navigate(['/login'], navigationExtras); this.router.navigate(['/login'], navigationExtras);
return false; return false;
} }
// #docregion admin-can-load
} }

View File

@ -13,11 +13,11 @@ export class AuthService {
// store the URL so we can redirect after logging in // store the URL so we can redirect after logging in
redirectUrl: string; redirectUrl: string;
login() { login(): Observable<boolean> {
return Observable.of(true).delay(1000).do(val => this.isLoggedIn = true); return Observable.of(true).delay(1000).do(val => this.isLoggedIn = true);
} }
logout() { logout(): void {
this.isLoggedIn = false; this.isLoggedIn = false;
} }
} }

View File

@ -3,7 +3,6 @@ import { Injectable } from '@angular/core';
import { CanDeactivate, import { CanDeactivate,
ActivatedRouteSnapshot, ActivatedRouteSnapshot,
RouterStateSnapshot } from '@angular/router'; RouterStateSnapshot } from '@angular/router';
import { Observable } from 'rxjs/Observable';
import { CrisisDetailComponent } from './crisis-center/crisis-detail.component'; import { CrisisDetailComponent } from './crisis-center/crisis-detail.component';
@ -14,7 +13,7 @@ export class CanDeactivateGuard implements CanDeactivate<CrisisDetailComponent>
component: CrisisDetailComponent, component: CrisisDetailComponent,
route: ActivatedRouteSnapshot, route: ActivatedRouteSnapshot,
state: RouterStateSnapshot state: RouterStateSnapshot
): Observable<boolean> | Promise<boolean> | boolean { ): Promise<boolean> | boolean {
// Get the Crisis Center ID // Get the Crisis Center ID
console.log(route.params['id']); console.log(route.params['id']);

View File

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

View File

@ -0,0 +1,13 @@
// #docregion
// #docplaster
import { Component } from '@angular/core';
// #docregion minus-imports
@Component({
template: `
<p>Welcome to the Crisis Center</p>
`
})
export class CrisisCenterHomeComponent { }
// #enddocregion minus-imports
// #enddocregion

View File

@ -1,3 +1,4 @@
// #docplaster
// #docregion // #docregion
import { NgModule } from '@angular/core'; import { NgModule } from '@angular/core';
import { FormsModule } from '@angular/forms'; import { FormsModule } from '@angular/forms';
@ -6,7 +7,8 @@ import { CommonModule } from '@angular/common';
import { CrisisService } from './crisis.service'; import { CrisisService } from './crisis.service';
import { CrisisCenterComponent } from './crisis-center.component'; import { CrisisCenterComponent } from './crisis-center.component';
import { CrisisListComponent } from './crisis-list.component'; import { CrisisListComponent } from './crisis-list.component';
import { CrisisCenterHomeComponent } from './crisis-center-home.component';
import { CrisisDetailComponent } from './crisis-detail.component'; import { CrisisDetailComponent } from './crisis-detail.component';
import { crisisCenterRouting } from './crisis-center.routing'; import { crisisCenterRouting } from './crisis-center.routing';
@ -20,13 +22,15 @@ import { crisisCenterRouting } from './crisis-center.routing';
declarations: [ declarations: [
CrisisCenterComponent, CrisisCenterComponent,
CrisisListComponent, CrisisListComponent,
CrisisCenterHomeComponent,
CrisisDetailComponent CrisisDetailComponent
], ],
// #docregion providers
// #docregion providers
providers: [ providers: [
CrisisService CrisisService
] ]
// #enddocregion providers // #enddocregion providers
}) })
export class CrisisCenterModule {} export class CrisisCenterModule {}
// #enddocregion // #enddocregion

View File

@ -9,10 +9,10 @@ import { CrisisService } from './crisis.service';
import { CrisisDetailResolve } from './crisis-detail-resolve.service'; import { CrisisDetailResolve } from './crisis-detail-resolve.service';
// #enddocregion crisis-detail-resolve // #enddocregion crisis-detail-resolve
import { CrisisCenterComponent } from './crisis-center.component'; import { CrisisCenterComponent } from './crisis-center.component';
import { CrisisListComponent } from './crisis-list.component'; import { CrisisListComponent } from './crisis-list.component';
import { CrisisDetailComponent } from './crisis-detail.component'; import { CrisisCenterHomeComponent } from './crisis-center-home.component';
import { CrisisAdminComponent } from './crisis-admin.component'; import { CrisisDetailComponent } from './crisis-detail.component';
import { crisisCenterRouting } from './crisis-center.routing'; import { crisisCenterRouting } from './crisis-center.routing';
@ -25,8 +25,8 @@ import { crisisCenterRouting } from './crisis-center.routing';
declarations: [ declarations: [
CrisisCenterComponent, CrisisCenterComponent,
CrisisListComponent, CrisisListComponent,
CrisisDetailComponent, CrisisCenterHomeComponent,
CrisisAdminComponent CrisisDetailComponent
], ],
// #docregion crisis-detail-resolve // #docregion crisis-detail-resolve

View File

@ -1,10 +1,12 @@
// #docplaster
// #docregion // #docregion
import { ModuleWithProviders } from '@angular/core'; import { ModuleWithProviders } from '@angular/core';
import { Routes, RouterModule } from '@angular/router'; import { Routes, RouterModule } from '@angular/router';
import { CrisisDetailComponent } from './crisis-detail.component'; import { CrisisCenterHomeComponent } from './crisis-center-home.component';
import { CrisisListComponent } from './crisis-list.component'; import { CrisisListComponent } from './crisis-list.component';
import { CrisisCenterComponent } from './crisis-center.component'; import { CrisisCenterComponent } from './crisis-center.component';
import { CrisisDetailComponent } from './crisis-detail.component';
// #docregion routes // #docregion routes
const crisisCenterRoutes: Routes = [ const crisisCenterRoutes: Routes = [
@ -12,11 +14,24 @@ const crisisCenterRoutes: Routes = [
path: 'crisis-center', path: 'crisis-center',
component: CrisisCenterComponent, component: CrisisCenterComponent,
children: [ children: [
{ path: ':id', component: CrisisDetailComponent }, {
{ path: '', component: CrisisListComponent } path: '',
component: CrisisListComponent,
children: [
{
path: ':id',
component: CrisisDetailComponent
},
{
path: '',
component: CrisisCenterHomeComponent
}
]
}
] ]
} }
]; ];
export const crisisCenterRouting: ModuleWithProviders = RouterModule.forChild(crisisCenterRoutes); export const crisisCenterRouting: ModuleWithProviders = RouterModule.forChild(crisisCenterRoutes);
// #enddocregion routes // #docregion routes
// #enddocregion

View File

@ -1,29 +1,65 @@
// #docregion // #docplaster
// #docregion routes
import { ModuleWithProviders } from '@angular/core'; import { ModuleWithProviders } from '@angular/core';
import { Routes, RouterModule } from '@angular/router'; import { Routes, RouterModule } from '@angular/router';
import { CrisisDetailComponent } from './crisis-detail.component'; import { CrisisCenterHomeComponent } from './crisis-center-home.component';
import { CrisisListComponent } from './crisis-list.component'; import { CrisisListComponent } from './crisis-list.component';
import { CrisisCenterComponent } from './crisis-center.component'; import { CrisisCenterComponent } from './crisis-center.component';
import { CrisisDetailComponent } from './crisis-detail.component';
// #enddocregion routes
// #docregion can-deactivate-guard
import { CanDeactivateGuard } from '../can-deactivate-guard.service';
// #enddocregion can-deactivate-guard
// #docregion crisis-detail-resolve
import { CrisisDetailResolve } from './crisis-detail-resolve.service';
// #enddocregion crisis-detail-resolve
// #docregion routes // #docregion routes
const crisisCenterRoutes: Routes = [ const crisisCenterRoutes: Routes = [
// #docregion redirect // #enddocregion routes
// #docregion redirect, routes
{ {
path: '', path: '',
redirectTo: '/crisis-center', redirectTo: '/crisis-center',
pathMatch: 'full' pathMatch: 'full'
}, },
// #enddocregion redirect // #enddocregion redirect, routes
// #docregion routes
{ {
path: 'crisis-center', path: 'crisis-center',
component: CrisisCenterComponent, component: CrisisCenterComponent,
children: [ children: [
{ path: ':id', component: CrisisDetailComponent }, {
{ path: '', component: CrisisListComponent } path: '',
component: CrisisListComponent,
children: [
{
path: ':id',
component: CrisisDetailComponent,
// #enddocregion routes
// #docregion can-deactivate-guard
canDeactivate: [CanDeactivateGuard],
// #enddocregion can-deactivate-guard
// #docregion crisis-detail-resolve
resolve: {
crisis: CrisisDetailResolve
}
// #enddocregion crisis-detail-resolve
// #docregion routes
},
{
path: '',
component: CrisisCenterHomeComponent
}
]
}
] ]
} }
// #docregion routes
]; ];
export const crisisCenterRouting: ModuleWithProviders = RouterModule.forChild(crisisCenterRoutes); export const crisisCenterRouting: ModuleWithProviders = RouterModule.forChild(crisisCenterRoutes);
// #enddocregion routes // #enddocregion

View File

@ -3,11 +3,12 @@
import { ModuleWithProviders } from '@angular/core'; import { ModuleWithProviders } from '@angular/core';
import { Routes, RouterModule } from '@angular/router'; import { Routes, RouterModule } from '@angular/router';
import { CrisisDetailComponent } from './crisis-detail.component'; import { CrisisCenterHomeComponent } from './crisis-center-home.component';
import { CrisisListComponent } from './crisis-list.component'; import { CrisisListComponent } from './crisis-list.component';
import { CrisisCenterComponent } from './crisis-center.component'; import { CrisisCenterComponent } from './crisis-center.component';
import { CrisisAdminComponent } from './crisis-admin.component'; import { CrisisDetailComponent } from './crisis-detail.component';
// #docregion can-deactivate-guard
import { CanDeactivateGuard } from '../can-deactivate-guard.service'; import { CanDeactivateGuard } from '../can-deactivate-guard.service';
const crisisCenterRoutes: Routes = [ const crisisCenterRoutes: Routes = [
@ -20,20 +21,20 @@ const crisisCenterRoutes: Routes = [
path: 'crisis-center', path: 'crisis-center',
component: CrisisCenterComponent, component: CrisisCenterComponent,
children: [ children: [
// #docregion admin-route-no-guard
{
path: 'admin',
component: CrisisAdminComponent
},
// #enddocregion admin-route-no-guard
{
path: ':id',
component: CrisisDetailComponent,
canDeactivate: [CanDeactivateGuard]
},
{ {
path: '', path: '',
component: CrisisListComponent component: CrisisListComponent,
children: [
{
path: ':id',
component: CrisisDetailComponent,
canDeactivate: [CanDeactivateGuard]
},
{
path: '',
component: CrisisCenterHomeComponent
}
]
} }
] ]
} }
@ -41,15 +42,3 @@ const crisisCenterRoutes: Routes = [
export const crisisCenterRouting: ModuleWithProviders = RouterModule.forChild(crisisCenterRoutes); export const crisisCenterRouting: ModuleWithProviders = RouterModule.forChild(crisisCenterRoutes);
// #enddocregion // #enddocregion
/*
// #docregion auth-guard
import { AuthGuard } from '../auth.guard';
{
path: 'admin',
component: CrisisAdminComponent,
canActivate: [AuthGuard]
}
// #enddocregion auth-guard
*/

View File

@ -1,57 +0,0 @@
// #docplaster
// #docregion
import { ModuleWithProviders } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { CrisisDetailComponent } from './crisis-detail.component';
import { CrisisListComponent } from './crisis-list.component';
import { CrisisCenterComponent } from './crisis-center.component';
import { CrisisAdminComponent } from './crisis-admin.component';
import { CanDeactivateGuard } from '../can-deactivate-guard.service';
import { AuthGuard } from '../auth-guard.service';
const crisisCenterRoutes: Routes = [
{
path: '',
redirectTo: '/crisis-center',
pathMatch: 'full'
},
{
path: 'crisis-center',
component: CrisisCenterComponent,
children: [
{
path: 'admin',
component: CrisisAdminComponent,
canActivate: [AuthGuard]
},
{
path: ':id',
component: CrisisDetailComponent,
canDeactivate: [CanDeactivateGuard]
},
// #docregion default-route
{
path: '',
component: CrisisListComponent
}
// #enddocregion default-route
]
}
];
export const crisisCenterRouting: ModuleWithProviders = RouterModule.forChild(crisisCenterRoutes);
// #enddocregion
/*
// #docregion auth-guard
import { AuthGuard } from '../auth.guard';
{
path: 'admin',
component: CrisisAdminComponent,
canActivate: [AuthGuard]
}
// #enddocregion auth-guard
*/

View File

@ -1,53 +0,0 @@
// #docplaster
// #docregion
import { ModuleWithProviders } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { CrisisCenterComponent } from './crisis-center.component';
import { CrisisDetailComponent } from './crisis-detail.component';
import { CrisisListComponent } from './crisis-list.component';
import { CrisisAdminComponent } from './crisis-admin.component';
import { CanDeactivateGuard } from '../can-deactivate-guard.service';
import { AuthGuard } from '../auth-guard.service';
// #docregion crisis-detail-resolve
import { CrisisDetailResolve } from './crisis-detail-resolve.service';
// #enddocregion crisis-detail-resolve
const crisisCenterRoutes: Routes = [
{
path: '',
redirectTo: '/crisis-center',
pathMatch: 'full'
},
{
path: 'crisis-center',
component: CrisisCenterComponent,
children: [
// #docregion admin-route
{
path: 'admin',
component: CrisisAdminComponent,
canActivate: [AuthGuard]
},
// #enddocregion admin-route
// #docregion crisis-detail-resolve
{
path: ':id',
component: CrisisDetailComponent,
canDeactivate: [CanDeactivateGuard],
resolve: {
crisis: CrisisDetailResolve
}
},
// #enddocregion crisis-detail-resolve
{
path: '',
component: CrisisListComponent
}
]
}
];
export const crisisCenterRouting: ModuleWithProviders = RouterModule.forChild(crisisCenterRoutes);

View File

@ -3,49 +3,49 @@
import { ModuleWithProviders } from '@angular/core'; import { ModuleWithProviders } from '@angular/core';
import { Routes, RouterModule } from '@angular/router'; import { Routes, RouterModule } from '@angular/router';
import { CrisisCenterComponent } from './crisis-center.component'; import { CrisisCenterHomeComponent } from './crisis-center-home.component';
import { CrisisDetailComponent } from './crisis-detail.component'; import { CrisisListComponent } from './crisis-list.component';
import { CrisisListComponent } from './crisis-list.component'; import { CrisisCenterComponent } from './crisis-center.component';
import { CrisisAdminComponent } from './crisis-admin.component'; import { CrisisDetailComponent } from './crisis-detail.component';
import { CanDeactivateGuard } from '../can-deactivate-guard.service'; import { CanDeactivateGuard } from '../can-deactivate-guard.service';
import { AuthGuard } from '../auth-guard.service';
// #docregion crisis-detail-resolve // #docregion crisis-detail-resolve
import { CrisisDetailResolve } from './crisis-detail-resolve.service'; import { CrisisDetailResolve } from './crisis-detail-resolve.service';
// #enddocregion crisis-detail-resolve
// #docregion lazy-load-crisis-center
const crisisCenterRoutes: Routes = [ const crisisCenterRoutes: Routes = [
// #docregion redirect
{ {
path: '', path: '',
redirectTo: '/crisis-center',
pathMatch: 'full'
},
// #enddocregion redirect
{
path: 'crisis-center',
component: CrisisCenterComponent, component: CrisisCenterComponent,
children: [ children: [
// #docregion admin-route
{
path: 'admin',
component: CrisisAdminComponent,
canActivate: [AuthGuard]
},
// #enddocregion admin-route
// #docregion crisis-detail-resolve
{
path: ':id',
component: CrisisDetailComponent,
canDeactivate: [CanDeactivateGuard],
resolve: {
crisis: CrisisDetailResolve
}
// #enddocregion crisis-detail-resolve
},
{ {
path: '', path: '',
component: CrisisListComponent component: CrisisListComponent,
children: [
{
path: ':id',
component: CrisisDetailComponent,
canDeactivate: [CanDeactivateGuard],
resolve: {
crisis: CrisisDetailResolve
}
},
{
path: '',
component: CrisisCenterHomeComponent
}
]
} }
] ]
} }
]; ];
export const crisisCenterRouting: ModuleWithProviders = RouterModule.forChild(crisisCenterRoutes); export const crisisCenterRouting: ModuleWithProviders = RouterModule.forChild(crisisCenterRoutes);
// #enddocregion lazy-load-crisis-center
// #enddocregion // #enddocregion

View File

@ -2,7 +2,6 @@
import { Injectable } from '@angular/core'; import { Injectable } from '@angular/core';
import { Router, Resolve, import { Router, Resolve,
ActivatedRouteSnapshot } from '@angular/router'; ActivatedRouteSnapshot } from '@angular/router';
import { Observable } from 'rxjs/Observable';
import { Crisis, CrisisService } from './crisis.service'; import { Crisis, CrisisService } from './crisis.service';
@ -10,7 +9,7 @@ import { Crisis, CrisisService } from './crisis.service';
export class CrisisDetailResolve implements Resolve<Crisis> { export class CrisisDetailResolve implements Resolve<Crisis> {
constructor(private cs: CrisisService, private router: Router) {} constructor(private cs: CrisisService, private router: Router) {}
resolve(route: ActivatedRouteSnapshot): Observable<any> | Promise<any> | any { resolve(route: ActivatedRouteSnapshot): Promise<Crisis>|boolean {
let id = +route.params['id']; let id = +route.params['id'];
return this.cs.getCrisis(id).then(crisis => { return this.cs.getCrisis(id).then(crisis => {

View File

@ -1,12 +1,12 @@
// #docplaster // #docplaster
// #docregion // #docregion
import { Component, OnInit, OnDestroy } from '@angular/core'; import { Component, OnInit,
import { ActivatedRoute, Router } from '@angular/router'; HostBinding, trigger, transition,
animate, style, state } from '@angular/core';
import { ActivatedRoute, Router, Params } from '@angular/router';
import { Crisis, CrisisService } from './crisis.service'; import { Crisis, CrisisService } from './crisis.service';
import { DialogService } from '../dialog.service'; import { DialogService } from '../dialog.service';
import { Observable } from 'rxjs/Observable';
import { Subscription } from 'rxjs/Subscription';
@Component({ @Component({
// #docregion template // #docregion template
@ -26,16 +26,47 @@ import { Subscription } from 'rxjs/Subscription';
</div> </div>
`, `,
// #enddocregion template // #enddocregion template
styles: ['input {width: 20em}'] styles: ['input {width: 20em}'],
animations: [
trigger('routeAnimation', [
state('*',
style({
opacity: 1,
transform: 'translateX(0)'
})
),
transition('void => *', [
style({
opacity: 0,
transform: 'translateX(-100%)'
}),
animate('0.2s ease-in')
]),
transition('* => void', [
animate('0.5s ease-out', style({
opacity: 0,
transform: 'translateY(100%)'
}))
])
])
]
}) })
// #docregion cancel-save // #docregion cancel-save
export class CrisisDetailComponent implements OnInit, OnDestroy { export class CrisisDetailComponent implements OnInit {
@HostBinding('@routeAnimation') get routeAnimation() {
return true;
}
@HostBinding('style.display') get display() {
return 'block';
}
@HostBinding('style.position') get position() {
return 'absolute';
}
crisis: Crisis; crisis: Crisis;
editName: string; editName: string;
// #enddocregion ngOnDestroy
private sub: Subscription;
// #enddocregion ngOnDestroy
// #enddocregion cancel-save // #enddocregion cancel-save
constructor( constructor(
@ -47,9 +78,7 @@ export class CrisisDetailComponent implements OnInit, OnDestroy {
// #docregion ngOnInit // #docregion ngOnInit
ngOnInit() { ngOnInit() {
this.sub = this.route this.route.params.forEach((params: Params) => {
.params
.subscribe(params => {
let id = +params['id']; let id = +params['id'];
this.service.getCrisis(id) this.service.getCrisis(id)
.then(crisis => { .then(crisis => {
@ -64,14 +93,6 @@ export class CrisisDetailComponent implements OnInit, OnDestroy {
} }
// #enddocregion ngOnInit // #enddocregion ngOnInit
// #enddocregion ngOnDestroy
ngOnDestroy() {
if (this.sub) {
this.sub.unsubscribe();
}
}
// #enddocregion ngOnDestroy
// #docregion cancel-save // #docregion cancel-save
cancel() { cancel() {
this.gotoCrises(); this.gotoCrises();
@ -84,7 +105,7 @@ export class CrisisDetailComponent implements OnInit, OnDestroy {
// #enddocregion cancel-save // #enddocregion cancel-save
// #docregion cancel-save-only // #docregion cancel-save-only
canDeactivate(): Observable<boolean> | Promise<boolean> | boolean { canDeactivate(): Promise<boolean> | boolean {
// 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;
@ -95,15 +116,16 @@ export class CrisisDetailComponent implements OnInit, OnDestroy {
} }
// #enddocregion cancel-save-only // #enddocregion cancel-save-only
// #docregion gotoCrises // #docregion gotoCrises, relative-navigation
gotoCrises() { gotoCrises() {
let crisisId = this.crisis ? this.crisis.id : null; let crisisId = this.crisis ? this.crisis.id : null;
// Pass along the hero id if available // Pass along the crisis id if available
// so that the CrisisListComponent can select that hero. // so that the CrisisListComponent can select that crisis.
// Add a totally useless `foo` parameter for kicks. // Add a totally useless `foo` parameter for kicks.
this.router.navigate(['/crisis-center', { id: crisisId, foo: 'foo' }]); // Relative navigation back to the crises
this.router.navigate(['../', { id: crisisId, foo: 'foo' }], { relativeTo: this.route });
} }
// #enddocregion gotoCrises // #enddocregion gotoCrises, relative-navigation
// #docregion cancel-save // #docregion cancel-save
} }
// #enddocregion cancel-save // #enddocregion cancel-save

View File

@ -1,11 +1,12 @@
// #docplaster // #docplaster
// #docregion // #docregion
import { Component, OnInit } from '@angular/core'; import { Component, OnInit, HostBinding,
trigger, transition,
animate, style, state } from '@angular/core';
import { Router, ActivatedRoute } from '@angular/router'; import { Router, ActivatedRoute } from '@angular/router';
import { Crisis } from './crisis.service'; import { Crisis } from './crisis.service';
import { DialogService } from '../dialog.service'; import { DialogService } from '../dialog.service';
import { Observable } from 'rxjs/Observable';
@Component({ @Component({
template: ` template: `
@ -23,10 +24,45 @@ import { Observable } from 'rxjs/Observable';
</p> </p>
</div> </div>
`, `,
styles: ['input {width: 20em}'] styles: ['input {width: 20em}'],
// #enddocregion template
animations: [
trigger('routeAnimation', [
state('*',
style({
opacity: 1,
transform: 'translateX(0)'
})
),
transition('void => *', [
style({
opacity: 0,
transform: 'translateX(-100%)'
}),
animate('0.2s ease-in')
]),
transition('* => void', [
animate('0.5s ease-out', style({
opacity: 0,
transform: 'translateY(100%)'
}))
])
])
]
}) })
export class CrisisDetailComponent implements OnInit { export class CrisisDetailComponent implements OnInit {
@HostBinding('@routeAnimation') get routeAnimation() {
return true;
}
@HostBinding('style.display') get display() {
return 'block';
}
@HostBinding('style.position') get position() {
return 'absolute';
}
crisis: Crisis; crisis: Crisis;
editName: string; editName: string;
@ -34,7 +70,7 @@ export class CrisisDetailComponent implements OnInit {
private route: ActivatedRoute, private route: ActivatedRoute,
private router: Router, private router: Router,
public dialogService: DialogService public dialogService: DialogService
) { } ) { }
// #docregion crisis-detail-resolve // #docregion crisis-detail-resolve
ngOnInit() { ngOnInit() {
@ -54,7 +90,7 @@ export class CrisisDetailComponent implements OnInit {
this.gotoCrises(); this.gotoCrises();
} }
canDeactivate(): Observable<boolean> | Promise<boolean> | boolean { canDeactivate(): Promise<boolean> | boolean {
// 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;
@ -67,12 +103,12 @@ export class CrisisDetailComponent implements OnInit {
// #docregion gotoCrises // #docregion gotoCrises
gotoCrises() { gotoCrises() {
let crisisId = this.crisis ? this.crisis.id : null; let crisisId = this.crisis ? this.crisis.id : null;
// Pass along the hero id if available // Pass along the crisis id if available
// so that the CrisisListComponent can select that hero. // so that the CrisisListComponent can select that crisis.
// Add a totally useless `foo` parameter for kicks. // Add a totally useless `foo` parameter for kicks.
// #docregion gotoCrises-navigate // #docregion gotoCrises-navigate
// Absolute link // Relative navigation back to the crises
this.router.navigate(['/crisis-center', { id: crisisId, foo: 'foo' }]); this.router.navigate(['../', { id: crisisId, foo: 'foo' }], { relativeTo: this.route });
// #enddocregion gotoCrises-navigate // #enddocregion gotoCrises-navigate
} }
// #enddocregion gotoCrises // #enddocregion gotoCrises

View File

@ -23,10 +23,12 @@ export class CrisisListComponent implements OnInit, OnDestroy {
selectedId: number; selectedId: number;
private sub: Subscription; private sub: Subscription;
// #docregion relative-navigation-ctor
constructor( constructor(
private service: CrisisService, private service: CrisisService,
private route: ActivatedRoute, private route: ActivatedRoute,
private router: Router) {} private router: Router) {}
// #enddocregion relative-navigation-ctor
ngOnInit() { ngOnInit() {
this.sub = this.route this.sub = this.route
@ -45,7 +47,14 @@ export class CrisisListComponent implements OnInit, OnDestroy {
// #docregion select // #docregion select
onSelect(crisis: Crisis) { onSelect(crisis: Crisis) {
// Absolute link // Absolute link
this.router.navigate(['/crisis-center', crisis.id]); this.router.navigate([crisis.id]);
} }
// #enddocregion select // #enddocregion select
} }
// #enddocregion
/*
// #docregion relative-navigation-router-link
<a [routerLink]="[crisis.id]">{{ crisis.name }}</a>
// #enddocregion relative-navigation-router-link
*/

View File

@ -1,10 +1,9 @@
// #docplaster // #docplaster
// #docregion // #docregion
import { Component, OnInit, OnDestroy } from '@angular/core'; import { Component, OnInit } from '@angular/core';
import { ActivatedRoute, Router } from '@angular/router'; import { ActivatedRoute, Router, Params } from '@angular/router';
import { Crisis, CrisisService } from './crisis.service'; import { Crisis, CrisisService } from './crisis.service';
import { Subscription } from 'rxjs/Subscription';
@Component({ @Component({
template: ` template: `
@ -15,38 +14,38 @@ import { Subscription } from 'rxjs/Subscription';
<span class="badge">{{crisis.id}}</span> {{crisis.name}} <span class="badge">{{crisis.id}}</span> {{crisis.name}}
</li> </li>
</ul> </ul>
<router-outlet></router-outlet>
` `
}) })
export class CrisisListComponent implements OnInit, OnDestroy { export class CrisisListComponent implements OnInit {
crises: Crisis[]; crises: Crisis[];
private selectedId: number; public selectedId: number;
private sub: Subscription;
constructor( constructor(
private service: CrisisService, private service: CrisisService,
private route: ActivatedRoute, private route: ActivatedRoute,
private router: Router) { } private router: Router
) { }
isSelected(crisis: Crisis) { return crisis.id === this.selectedId; } isSelected(crisis: Crisis) {
return crisis.id === this.selectedId;
}
ngOnInit() { ngOnInit() {
this.sub = this.route this.route.params.forEach((params: Params) => {
.params this.selectedId = params['id'];
.subscribe(params => { this.service.getCrises()
this.selectedId = +params['id']; .then(crises => this.crises = crises);
this.service.getCrises() });
.then(crises => this.crises = crises);
});
}
ngOnDestroy() {
if (this.sub) {
this.sub.unsubscribe();
}
} }
// #docregion relative-navigation
onSelect(crisis: Crisis) { onSelect(crisis: Crisis) {
// Navigate with Absolute link this.selectedId = crisis.id;
this.router.navigate(['/crisis-center', crisis.id]);
// Navigate with relative link
this.router.navigate([crisis.id], { relativeTo: this.route });
} }
// #enddocregion relative-navigation
} }

View File

@ -1,10 +1,11 @@
// #docplaster // #docplaster
// #docregion // #docregion
import { Component, OnInit, OnDestroy } from '@angular/core'; import { Component, OnInit } from '@angular/core';
import { Router, ActivatedRoute } from '@angular/router'; // #docregion imports
import { Router, ActivatedRoute, Params } from '@angular/router';
// #enddocregion imports
import { Hero, HeroService } from './hero.service'; import { Hero, HeroService } from './hero.service';
import { Subscription } from 'rxjs/Subscription';
@Component({ @Component({
template: ` template: `
@ -23,34 +24,26 @@ import { Subscription } from 'rxjs/Subscription';
</div> </div>
` `
}) })
export class HeroDetailComponent implements OnInit, OnDestroy { export class HeroDetailComponent implements OnInit {
hero: Hero; hero: Hero;
// #docregion ngOnInit
private sub: Subscription;
// #enddocregion ngOnInit
// #docregion ctor // #docregion ctor
constructor( constructor(
private route: ActivatedRoute, private route: ActivatedRoute,
private router: Router, private router: Router,
private service: HeroService) {} private service: HeroService
) {}
// #enddocregion ctor // #enddocregion ctor
// #docregion ngOnInit // #docregion ngOnInit
ngOnInit() { ngOnInit() {
this.sub = this.route.params.subscribe(params => { this.route.params.forEach((params: Params) => {
let id = +params['id']; // (+) converts string 'id' to a number let id = +params['id']; // (+) converts string 'id' to a number
this.service.getHero(id).then(hero => this.hero = hero); this.service.getHero(id).then(hero => this.hero = hero);
}); });
} }
// #enddocregion ngOnInit // #enddocregion ngOnInit
// #docregion ngOnDestroy
ngOnDestroy() {
this.sub.unsubscribe();
}
// #enddocregion ngOnDestroy
// #docregion gotoHeroes // #docregion gotoHeroes
gotoHeroes() { this.router.navigate(['/heroes']); } gotoHeroes() { this.router.navigate(['/heroes']); }
// #enddocregion gotoHeroes // #enddocregion gotoHeroes

View File

@ -1,11 +1,15 @@
// #docplaster // #docplaster
// #docregion // #docregion
import { Component, OnInit, OnDestroy } from '@angular/core'; // #docregion route-animation-imports
import { Router, ActivatedRoute } from '@angular/router'; import { Component, OnInit, HostBinding,
trigger, transition, animate,
style, state } from '@angular/core';
// #enddocregion route-animation-imports
import { Router, ActivatedRoute, Params } from '@angular/router';
import { Hero, HeroService } from './hero.service'; import { Hero, HeroService } from './hero.service';
import { Subscription } from 'rxjs/Subscription';
// #docregion route-animation
@Component({ @Component({
template: ` template: `
<h2>HEROES</h2> <h2>HEROES</h2>
@ -21,15 +25,48 @@ import { Subscription } from 'rxjs/Subscription';
<button (click)="gotoHeroes()">Back</button> <button (click)="gotoHeroes()">Back</button>
</p> </p>
</div> </div>
` `,
animations: [
trigger('routeAnimation', [
state('*',
style({
opacity: 1,
transform: 'translateX(0)'
})
),
transition('void => *', [
style({
opacity: 0,
transform: 'translateX(-100%)'
}),
animate('0.2s ease-in')
]),
transition('* => void', [
animate('0.5s ease-out', style({
opacity: 0,
transform: 'translateY(100%)'
}))
])
])
]
}) })
export class HeroDetailComponent implements OnInit, OnDestroy { // #docregion route-animation-host-binding
export class HeroDetailComponent implements OnInit {
// #enddocregion route-animation
@HostBinding('@routeAnimation') get routeAnimation() {
return true;
}
@HostBinding('style.display') get display() {
return 'block';
}
@HostBinding('style.position') get position() {
return 'absolute';
}
hero: Hero; hero: Hero;
// #docregion ngOnInit
private sub: Subscription;
// #enddocregion ngOnInit
// #docregion ctor // #docregion ctor
constructor( constructor(
private route: ActivatedRoute, private route: ActivatedRoute,
@ -39,19 +76,13 @@ export class HeroDetailComponent implements OnInit, OnDestroy {
// #docregion ngOnInit // #docregion ngOnInit
ngOnInit() { ngOnInit() {
this.sub = this.route.params.subscribe(params => { this.route.params.forEach((params: Params) => {
let id = +params['id']; // (+) converts string 'id' to a number let id = +params['id']; // (+) converts string 'id' to a number
this.service.getHero(id).then(hero => this.hero = hero); this.service.getHero(id).then(hero => this.hero = hero);
}); });
} }
// #enddocregion ngOnInit // #enddocregion ngOnInit
// #docregion ngOnDestroy
ngOnDestroy() {
this.sub.unsubscribe();
}
// #enddocregion ngOnDestroy
// #docregion gotoHeroes-navigate // #docregion gotoHeroes-navigate
gotoHeroes() { gotoHeroes() {
let heroId = this.hero ? this.hero.id : null; let heroId = this.hero ? this.hero.id : null;
@ -60,4 +91,6 @@ export class HeroDetailComponent implements OnInit, OnDestroy {
this.router.navigate(['/heroes', { id: heroId, foo: 'foo' }]); this.router.navigate(['/heroes', { id: heroId, foo: 'foo' }]);
} }
// #enddocregion gotoHeroes-navigate // #enddocregion gotoHeroes-navigate
// #docregion route-animation-host-binding
} }
// #enddocregion route-animation-host-binding

View File

@ -1,13 +1,12 @@
// #docplaster // #docplaster
// #docregion // #docregion
// TODO SOMEDAY: Feature Componetized like CrisisCenter // TODO SOMEDAY: Feature Componetized like CrisisCenter
import { Component, OnInit, OnDestroy } from '@angular/core'; import { Component, OnInit } from '@angular/core';
// #docregion import-router // #docregion import-router
import { Router, ActivatedRoute } from '@angular/router'; import { Router, ActivatedRoute, Params } from '@angular/router';
// #enddocregion import-router // #enddocregion import-router
import { Hero, HeroService } from './hero.service'; import { Hero, HeroService } from './hero.service';
import { Subscription } from 'rxjs/Subscription';
@Component({ @Component({
// #docregion template // #docregion template
@ -23,32 +22,26 @@ import { Subscription } from 'rxjs/Subscription';
` `
// #enddocregion template // #enddocregion template
}) })
export class HeroListComponent implements OnInit, OnDestroy { export class HeroListComponent implements OnInit {
heroes: Hero[]; heroes: Hero[];
// #docregion ctor // #docregion ctor
private selectedId: number; private selectedId: number;
private sub: Subscription;
constructor( constructor(
private service: HeroService, private service: HeroService,
private route: ActivatedRoute, private route: ActivatedRoute,
private router: Router) {} private router: Router
) {}
// #enddocregion ctor // #enddocregion ctor
ngOnInit() { ngOnInit() {
this.sub = this.route this.route.params.forEach((params: Params) => {
.params
.subscribe(params => {
this.selectedId = +params['id']; this.selectedId = +params['id'];
this.service.getHeroes() this.service.getHeroes()
.then(heroes => this.heroes = heroes); .then(heroes => this.heroes = heroes);
}); });
} }
ngOnDestroy() {
this.sub.unsubscribe();
}
// #enddocregion ctor // #enddocregion ctor
// #docregion isSelected // #docregion isSelected

View File

@ -32,7 +32,7 @@ export class LoginComponent {
if (this.authService.isLoggedIn) { if (this.authService.isLoggedIn) {
// Get the redirect URL from our auth service // Get the redirect URL from our auth service
// If no redirect has been set, use the default // If no redirect has been set, use the default
let redirect = this.authService.redirectUrl ? this.authService.redirectUrl : '/crisis-center/admin'; let redirect = this.authService.redirectUrl ? this.authService.redirectUrl : '/admin';
// #docregion preserve // #docregion preserve
// Set our navigation extras object // Set our navigation extras object

View File

@ -122,7 +122,7 @@
"router": { "router": {
"title": "Routing & Navigation", "title": "Routing & Navigation",
"intro": "Discover the basics of screen navigation with the Angular 2 Component Router." "intro": "Discover the basics of screen navigation with the Angular 2 Router."
}, },
"security": { "security": {

File diff suppressed because it is too large Load Diff