docs(router): Updated routing examples to use routing modules (#2478)
Simplified routing in tutorial example Updated ngmodule guide and ngmodule faq with routing module prose
This commit is contained in:
parent
3a78f6d8c6
commit
ff118810ff
|
@ -1,5 +1,5 @@
|
|||
// #docregion
|
||||
import { ModuleWithProviders } from '@angular/core';
|
||||
import { NgModule } from '@angular/core';
|
||||
import { Routes, RouterModule } from '@angular/router';
|
||||
|
||||
import { MovieListComponent } from './movie-list.component';
|
||||
|
@ -9,4 +9,8 @@ const routes: Routes = [
|
|||
{ path: 'movies', component: MovieListComponent }
|
||||
];
|
||||
|
||||
export const routing: ModuleWithProviders = RouterModule.forRoot(routes);
|
||||
@NgModule({
|
||||
imports: [RouterModule.forRoot(routes)],
|
||||
exports: [RouterModule]
|
||||
})
|
||||
export class AppRoutingModule {}
|
|
@ -5,13 +5,13 @@ import { FormsModule } from '@angular/forms';
|
|||
|
||||
import { AppComponent } from './app.component';
|
||||
import { MovieListComponent } from './movie-list.component';
|
||||
import { routing } from './app.routing';
|
||||
import { AppRoutingModule } from './app-routing.module';
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
BrowserModule,
|
||||
FormsModule,
|
||||
routing
|
||||
AppRoutingModule
|
||||
],
|
||||
declarations: [
|
||||
AppComponent,
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
import { NgModule } from '@angular/core';
|
||||
import { Routes, RouterModule } from '@angular/router';
|
||||
|
||||
const routes: Routes = [];
|
||||
|
||||
@NgModule({
|
||||
imports: [RouterModule.forRoot(routes)],
|
||||
providers: [],
|
||||
exports: [RouterModule]
|
||||
})
|
||||
export class AppRoutingModule {}
|
|
@ -3,7 +3,7 @@ import { BrowserModule } from '@angular/platform-browser';
|
|||
import { FormsModule } from '@angular/forms';
|
||||
import { HttpModule } from '@angular/http';
|
||||
|
||||
/* import { routing } from './app.routing';*/
|
||||
// import { AppRoutingModule } from './app-routing.module';
|
||||
import { LocationStrategy,
|
||||
HashLocationStrategy } from '@angular/common';
|
||||
import { NgModule } from '@angular/core';
|
||||
|
@ -56,7 +56,7 @@ const c_components = [
|
|||
FormsModule,
|
||||
HttpModule,
|
||||
InMemoryWebApiModule.forRoot(HeroData)
|
||||
// routing TODO: add routes
|
||||
// AppRoutingModule TODO: add routes
|
||||
],
|
||||
declarations: [
|
||||
declarations,
|
||||
|
|
|
@ -1,10 +0,0 @@
|
|||
import { ModuleWithProviders } from '@angular/core';
|
||||
import { Routes, RouterModule } from '@angular/router';
|
||||
|
||||
const routes: Routes = [];
|
||||
|
||||
export const routing: ModuleWithProviders = RouterModule.forRoot(routes);
|
||||
|
||||
export const appRoutingProviders: any[] = [
|
||||
|
||||
];
|
|
@ -1,4 +1,4 @@
|
|||
import { ModuleWithProviders } from '@angular/core';
|
||||
import { NgModule } from '@angular/core';
|
||||
import { Routes, RouterModule } from '@angular/router';
|
||||
|
||||
export const routes: Routes = [
|
||||
|
@ -7,4 +7,8 @@ export const routes: Routes = [
|
|||
{ path: 'heroes', loadChildren: 'app/hero/hero.module.3#HeroModule' }
|
||||
];
|
||||
|
||||
export const routing: ModuleWithProviders = RouterModule.forRoot(routes);
|
||||
@NgModule({
|
||||
imports: [RouterModule.forRoot(routes)],
|
||||
exports: [RouterModule]
|
||||
})
|
||||
export class AppRoutingModule {}
|
|
@ -1,5 +1,5 @@
|
|||
// #docregion
|
||||
import { ModuleWithProviders } from '@angular/core';
|
||||
import { NgModule } from '@angular/core';
|
||||
import { Routes, RouterModule } from '@angular/router';
|
||||
|
||||
export const routes: Routes = [
|
||||
|
@ -11,5 +11,9 @@ export const routes: Routes = [
|
|||
];
|
||||
|
||||
// #docregion forRoot
|
||||
export const routing: ModuleWithProviders = RouterModule.forRoot(routes);
|
||||
@NgModule({
|
||||
imports: [RouterModule.forRoot(routes)],
|
||||
exports: [RouterModule]
|
||||
})
|
||||
export class AppRoutingModule {}
|
||||
// #enddocregion forRoot
|
|
@ -11,14 +11,16 @@ import { UserService } from './user.service';
|
|||
|
||||
/* Feature Modules */
|
||||
import { ContactModule } from './contact/contact.module.3';
|
||||
import { routing } from './app.routing.3';
|
||||
|
||||
/* Routing Module */
|
||||
import { AppRoutingModule } from './app-routing.module.3';
|
||||
|
||||
@NgModule({
|
||||
// #docregion imports
|
||||
imports: [
|
||||
BrowserModule,
|
||||
ContactModule,
|
||||
routing
|
||||
AppRoutingModule
|
||||
],
|
||||
// #enddocregion imports
|
||||
providers: [ UserService ],
|
||||
|
|
|
@ -8,9 +8,11 @@ import { BrowserModule } from '@angular/platform-browser';
|
|||
import { AppComponent } from './app.component';
|
||||
|
||||
/* Feature Modules */
|
||||
import { ContactModule } from './contact/contact.module';
|
||||
import { CoreModule } from './core/core.module';
|
||||
import { routing } from './app.routing';
|
||||
import { ContactModule } from './contact/contact.module';
|
||||
import { CoreModule } from './core/core.module';
|
||||
|
||||
/* Routing Module */
|
||||
import { AppRoutingModule } from './app-routing.module';
|
||||
|
||||
@NgModule({
|
||||
// #docregion import-for-root
|
||||
|
@ -29,7 +31,7 @@ import { routing } from './app.routing';
|
|||
// #docregion
|
||||
CoreModule.forRoot({userName: 'Miss Marple'}),
|
||||
// #docregion v4
|
||||
routing
|
||||
AppRoutingModule
|
||||
],
|
||||
// #enddocregion import-for-root
|
||||
declarations: [ AppComponent ],
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
import { NgModule } from '@angular/core';
|
||||
import { RouterModule } from '@angular/router';
|
||||
|
||||
import { ContactComponent } from './contact.component.3';
|
||||
|
||||
@NgModule({
|
||||
imports: [RouterModule.forChild([
|
||||
{ path: 'contact', component: ContactComponent}
|
||||
])],
|
||||
exports: [RouterModule]
|
||||
})
|
||||
export class ContactRoutingModule {}
|
|
@ -0,0 +1,14 @@
|
|||
import { NgModule } from '@angular/core';
|
||||
import { RouterModule } from '@angular/router';
|
||||
|
||||
import { ContactComponent } from './contact.component';
|
||||
|
||||
// #docregion routing
|
||||
@NgModule({
|
||||
imports: [RouterModule.forChild([
|
||||
{ path: 'contact', component: ContactComponent }
|
||||
])],
|
||||
exports: [RouterModule]
|
||||
})
|
||||
export class ContactRoutingModule {}
|
||||
// #enddocregion
|
|
@ -9,11 +9,11 @@ import { ContactComponent } from './contact.component.3';
|
|||
import { ContactService } from './contact.service';
|
||||
import { HighlightDirective } from './highlight.directive';
|
||||
|
||||
import { routing } from './contact.routing.3';
|
||||
import { ContactRoutingModule } from './contact-routing.module.3';
|
||||
|
||||
// #docregion class
|
||||
@NgModule({
|
||||
imports: [ CommonModule, FormsModule, routing ],
|
||||
imports: [ CommonModule, FormsModule, ContactRoutingModule ],
|
||||
declarations: [ ContactComponent, HighlightDirective, AwesomePipe ],
|
||||
providers: [ ContactService ]
|
||||
})
|
||||
|
|
|
@ -2,13 +2,13 @@
|
|||
import { NgModule } from '@angular/core';
|
||||
import { SharedModule } from '../shared/shared.module';
|
||||
|
||||
import { ContactComponent } from './contact.component';
|
||||
import { ContactService } from './contact.service';
|
||||
import { routing } from './contact.routing';
|
||||
import { ContactComponent } from './contact.component';
|
||||
import { ContactService } from './contact.service';
|
||||
import { ContactRoutingModule } from './contact-routing.module';
|
||||
|
||||
// #docregion class
|
||||
@NgModule({
|
||||
imports: [ SharedModule, routing ],
|
||||
imports: [ SharedModule, ContactRoutingModule ],
|
||||
declarations: [ ContactComponent ],
|
||||
providers: [ ContactService ]
|
||||
})
|
||||
|
|
|
@ -1,8 +0,0 @@
|
|||
import { ModuleWithProviders } from '@angular/core';
|
||||
import { RouterModule } from '@angular/router';
|
||||
|
||||
import { ContactComponent } from './contact.component.3';
|
||||
|
||||
export const routing: ModuleWithProviders = RouterModule.forChild([
|
||||
{ path: 'contact', component: ContactComponent}
|
||||
]);
|
|
@ -1,10 +0,0 @@
|
|||
import { ModuleWithProviders } from '@angular/core';
|
||||
import { RouterModule } from '@angular/router';
|
||||
|
||||
import { ContactComponent } from './contact.component';
|
||||
|
||||
// #docregion routing
|
||||
export const routing: ModuleWithProviders = RouterModule.forChild([
|
||||
{ path: 'contact', component: ContactComponent}
|
||||
]);
|
||||
// #enddocregion
|
|
@ -1,4 +1,4 @@
|
|||
import { ModuleWithProviders } from '@angular/core';
|
||||
import { NgModule } from '@angular/core';
|
||||
import { Routes,
|
||||
RouterModule } from '@angular/router';
|
||||
|
||||
|
@ -11,4 +11,8 @@ const routes: Routes = [
|
|||
{ path: ':id', component: CrisisDetailComponent }
|
||||
];
|
||||
|
||||
export const routing: ModuleWithProviders = RouterModule.forChild(routes);
|
||||
@NgModule({
|
||||
imports: [RouterModule.forChild(routes)],
|
||||
exports: [RouterModule]
|
||||
})
|
||||
export class CrisisRoutingModule {}
|
|
@ -3,11 +3,11 @@ import { CommonModule } from '@angular/common';
|
|||
|
||||
import { CrisisListComponent } from './crisis-list.component';
|
||||
import { CrisisDetailComponent } from './crisis-detail.component';
|
||||
import { CrisisService } from './crisis.service';
|
||||
import { routing } from './crisis.routing';
|
||||
import { CrisisService } from './crisis.service';
|
||||
import { CrisisRoutingModule } from './crisis-routing.module';
|
||||
|
||||
@NgModule({
|
||||
imports: [ CommonModule, routing ],
|
||||
imports: [ CommonModule, CrisisRoutingModule ],
|
||||
declarations: [ CrisisDetailComponent, CrisisListComponent ],
|
||||
providers: [ CrisisService ]
|
||||
})
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { ModuleWithProviders } from '@angular/core';
|
||||
import { NgModule } from '@angular/core';
|
||||
import { Routes,
|
||||
RouterModule } from '@angular/router';
|
||||
|
||||
|
@ -16,4 +16,8 @@ const routes: Routes = [
|
|||
}
|
||||
];
|
||||
|
||||
export const routing: ModuleWithProviders = RouterModule.forChild(routes);
|
||||
@NgModule({
|
||||
imports: [RouterModule.forChild(routes)],
|
||||
exports: [RouterModule]
|
||||
})
|
||||
export class HeroRoutingModule {}
|
|
@ -1,4 +1,4 @@
|
|||
import { ModuleWithProviders } from '@angular/core';
|
||||
import { NgModule } from '@angular/core';
|
||||
import { Routes,
|
||||
RouterModule } from '@angular/router';
|
||||
|
||||
|
@ -16,4 +16,8 @@ const routes: Routes = [
|
|||
}
|
||||
];
|
||||
|
||||
export const routing: ModuleWithProviders = RouterModule.forChild(routes);
|
||||
@NgModule({
|
||||
imports: [RouterModule.forChild(routes)],
|
||||
exports: [RouterModule]
|
||||
})
|
||||
export class HeroRoutingModule {}
|
|
@ -6,11 +6,11 @@ import { HeroComponent } from './hero.component.3';
|
|||
import { HeroDetailComponent } from './hero-detail.component';
|
||||
import { HeroListComponent } from './hero-list.component';
|
||||
import { HighlightDirective } from './highlight.directive';
|
||||
import { routing } from './hero.routing.3';
|
||||
import { HeroRoutingModule } from './hero-routing.module.3';
|
||||
|
||||
// #docregion class
|
||||
@NgModule({
|
||||
imports: [ CommonModule, FormsModule, routing ],
|
||||
imports: [ CommonModule, FormsModule, HeroRoutingModule ],
|
||||
declarations: [
|
||||
HeroComponent, HeroDetailComponent, HeroListComponent,
|
||||
HighlightDirective
|
||||
|
|
|
@ -5,10 +5,10 @@ import { SharedModule } from '../shared/shared.module';
|
|||
import { HeroComponent } from './hero.component';
|
||||
import { HeroDetailComponent } from './hero-detail.component';
|
||||
import { HeroListComponent } from './hero-list.component';
|
||||
import { routing } from './hero.routing';
|
||||
import { HeroRoutingModule } from './hero-routing.module';
|
||||
|
||||
@NgModule({
|
||||
imports: [ SharedModule, routing ],
|
||||
imports: [ SharedModule, HeroRoutingModule ],
|
||||
declarations: [
|
||||
HeroComponent, HeroDetailComponent, HeroListComponent,
|
||||
]
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
"files": [
|
||||
"app/app.component.ts",
|
||||
"app/app.module.ts",
|
||||
"app/app.routing.ts",
|
||||
"app/app-routing.module.ts",
|
||||
"app/main.ts",
|
||||
|
||||
"app/contact/contact.component.css",
|
||||
|
@ -12,7 +12,7 @@
|
|||
|
||||
"app/contact/contact.component.ts",
|
||||
"app/contact/contact.module.ts",
|
||||
"app/contact/contact.routing.ts",
|
||||
"app/contact/contact-routing.module.ts",
|
||||
|
||||
"app/crisis/*.ts",
|
||||
|
||||
|
@ -22,7 +22,7 @@
|
|||
|
||||
"app/hero/hero.component.ts",
|
||||
"app/hero/hero.module.ts",
|
||||
"app/hero/hero.routing.ts",
|
||||
"app/hero/hero-routing.module.ts",
|
||||
|
||||
"app/core/*.css",
|
||||
"app/core/*.html",
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
"files": [
|
||||
"app/app.component.3.ts",
|
||||
"app/app.module.3.ts",
|
||||
"app/app.routing.3.ts",
|
||||
"app/app-routing.module.3.ts",
|
||||
"app/main.3.ts",
|
||||
|
||||
"app/highlight.directive.ts",
|
||||
|
@ -18,7 +18,7 @@
|
|||
"app/contact/awesome.pipe.ts",
|
||||
"app/contact/contact.component.3.ts",
|
||||
"app/contact/contact.module.3.ts",
|
||||
"app/contact/contact.routing.3.ts",
|
||||
"app/contact/contact-routing.module.3.ts",
|
||||
"app/contact/highlight.directive.ts",
|
||||
|
||||
"app/crisis/*.ts",
|
||||
|
@ -29,7 +29,7 @@
|
|||
|
||||
"app/hero/hero.component.3.ts",
|
||||
"app/hero/hero.module.3.ts",
|
||||
"app/hero/hero.routing.3.ts",
|
||||
"app/hero/hero-routing.module.3.ts",
|
||||
"app/hero/highlight.directive.ts",
|
||||
|
||||
"styles.css",
|
||||
|
|
|
@ -0,0 +1,37 @@
|
|||
// #docplaster
|
||||
// #docregion
|
||||
import { NgModule } from '@angular/core';
|
||||
import { 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
|
||||
@NgModule({
|
||||
imports: [
|
||||
RouterModule.forChild([
|
||||
{
|
||||
path: 'admin',
|
||||
component: AdminComponent,
|
||||
children: [
|
||||
{
|
||||
path: '',
|
||||
children: [
|
||||
{ path: 'crises', component: ManageCrisesComponent },
|
||||
{ path: 'heroes', component: ManageHeroesComponent },
|
||||
{ path: '', component: AdminDashboardComponent }
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
])
|
||||
],
|
||||
exports: [
|
||||
RouterModule
|
||||
]
|
||||
})
|
||||
export class AdminRoutingModule {}
|
||||
// #enddocregion admin-routes
|
||||
// #enddocregion
|
|
@ -0,0 +1,43 @@
|
|||
// #docplaster
|
||||
// #docregion
|
||||
import { NgModule } from '@angular/core';
|
||||
import { 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';
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
RouterModule.forChild([
|
||||
{
|
||||
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
|
||||
}
|
||||
]
|
||||
}
|
||||
])
|
||||
],
|
||||
exports: [
|
||||
RouterModule
|
||||
]
|
||||
})
|
||||
export class AdminRoutingModule {}
|
||||
// #enddocregion
|
|
@ -0,0 +1,41 @@
|
|||
// #docplaster
|
||||
// #docregion
|
||||
import { NgModule } from '@angular/core';
|
||||
import { 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
|
||||
@NgModule({
|
||||
imports: [
|
||||
RouterModule.forChild([
|
||||
{
|
||||
path: 'admin',
|
||||
component: AdminComponent,
|
||||
canActivate: [AuthGuard],
|
||||
children: [
|
||||
{
|
||||
path: '',
|
||||
canActivateChild: [AuthGuard],
|
||||
children: [
|
||||
{ path: 'crises', component: ManageCrisesComponent },
|
||||
{ path: 'heroes', component: ManageHeroesComponent },
|
||||
{ path: '', component: AdminDashboardComponent }
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
])
|
||||
],
|
||||
exports: [
|
||||
RouterModule
|
||||
]
|
||||
})
|
||||
export class AdminRoutingModule {}
|
||||
// #enddocregion
|
|
@ -0,0 +1,40 @@
|
|||
// #docplaster
|
||||
// #docregion
|
||||
import { NgModule } from '@angular/core';
|
||||
import { 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';
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
RouterModule.forChild([
|
||||
{
|
||||
path: '',
|
||||
component: AdminComponent,
|
||||
canActivate: [AuthGuard],
|
||||
children: [
|
||||
{
|
||||
path: '',
|
||||
canActivateChild: [AuthGuard],
|
||||
children: [
|
||||
{ path: 'crises', component: ManageCrisesComponent },
|
||||
{ path: 'heroes', component: ManageHeroesComponent },
|
||||
{ path: '', component: AdminDashboardComponent }
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
])
|
||||
],
|
||||
exports: [
|
||||
RouterModule
|
||||
]
|
||||
})
|
||||
export class AdminRoutingModule {}
|
||||
// #enddocregion
|
|
@ -8,12 +8,12 @@ import { AdminDashboardComponent } from './admin-dashboard.component';
|
|||
import { ManageCrisesComponent } from './manage-crises.component';
|
||||
import { ManageHeroesComponent } from './manage-heroes.component';
|
||||
|
||||
import { adminRouting } from './admin.routing';
|
||||
import { AdminRoutingModule } from './admin-routing.module';
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
CommonModule,
|
||||
adminRouting
|
||||
AdminRoutingModule
|
||||
],
|
||||
declarations: [
|
||||
AdminComponent,
|
||||
|
|
|
@ -1,31 +0,0 @@
|
|||
// #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
|
|
@ -1,37 +0,0 @@
|
|||
// #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
|
|
@ -1,35 +0,0 @@
|
|||
// #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
|
|
@ -1,34 +0,0 @@
|
|||
// #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
|
|
@ -0,0 +1,20 @@
|
|||
// #docplaster
|
||||
// #docregion
|
||||
import { NgModule } from '@angular/core';
|
||||
import { RouterModule } from '@angular/router';
|
||||
|
||||
import { CrisisListComponent } from './crisis-list.component';
|
||||
import { HeroListComponent } from './hero-list.component';
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
RouterModule.forRoot([
|
||||
{ path: 'crisis-center', component: CrisisListComponent },
|
||||
{ path: 'heroes', component: HeroListComponent }
|
||||
])
|
||||
],
|
||||
exports: [
|
||||
RouterModule
|
||||
]
|
||||
})
|
||||
export class AppRoutingModule {}
|
|
@ -0,0 +1,18 @@
|
|||
// #docplaster
|
||||
// #docregion
|
||||
import { NgModule } from '@angular/core';
|
||||
import { RouterModule } from '@angular/router';
|
||||
|
||||
import { CrisisListComponent } from './crisis-list.component';
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
RouterModule.forRoot([
|
||||
{ path: 'crisis-center', component: CrisisListComponent },
|
||||
])
|
||||
],
|
||||
exports: [
|
||||
RouterModule
|
||||
]
|
||||
})
|
||||
export class AppRoutingModule {}
|
|
@ -0,0 +1,16 @@
|
|||
// #docplaster
|
||||
// #docregion
|
||||
import { NgModule } from '@angular/core';
|
||||
import { RouterModule } from '@angular/router';
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
RouterModule.forRoot([
|
||||
|
||||
])
|
||||
],
|
||||
exports: [
|
||||
RouterModule
|
||||
]
|
||||
})
|
||||
export class AppRoutingModule {}
|
|
@ -0,0 +1,21 @@
|
|||
// #docplaster
|
||||
// #docregion
|
||||
import { NgModule } from '@angular/core';
|
||||
import { RouterModule } from '@angular/router';
|
||||
|
||||
import { CanDeactivateGuard } from './can-deactivate-guard.service';
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
RouterModule.forRoot([
|
||||
|
||||
])
|
||||
],
|
||||
exports: [
|
||||
RouterModule
|
||||
],
|
||||
providers: [
|
||||
CanDeactivateGuard
|
||||
]
|
||||
})
|
||||
export class AppRoutingModule {}
|
|
@ -0,0 +1,33 @@
|
|||
// #docplaster
|
||||
// #docregion
|
||||
import { NgModule } from '@angular/core';
|
||||
// #docregion import-router
|
||||
import { RouterModule } from '@angular/router';
|
||||
// #enddocregion import-router
|
||||
|
||||
import { CanDeactivateGuard } from './can-deactivate-guard.service';
|
||||
// #docregion can-load-guard
|
||||
import { AuthGuard } from './auth-guard.service';
|
||||
// #enddocregion can-load-guard
|
||||
|
||||
// #docregion lazy-load-admin, can-load-guard
|
||||
@NgModule({
|
||||
imports: [
|
||||
RouterModule.forRoot([
|
||||
{
|
||||
path: 'admin',
|
||||
loadChildren: 'app/admin/admin.module#AdminModule',
|
||||
// #enddocregion lazy-load-admin
|
||||
canLoad: [AuthGuard]
|
||||
// #docregion lazy-load-admin
|
||||
}
|
||||
])
|
||||
],
|
||||
exports: [
|
||||
RouterModule
|
||||
],
|
||||
providers: [
|
||||
CanDeactivateGuard
|
||||
]
|
||||
})
|
||||
export class AppRoutingModule {}
|
|
@ -0,0 +1,51 @@
|
|||
// #docplaster
|
||||
// #docregion
|
||||
// #docregion router-basics
|
||||
import { NgModule } from '@angular/core';
|
||||
import { BrowserModule } from '@angular/platform-browser';
|
||||
import { FormsModule } from '@angular/forms';
|
||||
import { RouterModule } from '@angular/router';
|
||||
|
||||
import { AppComponent } from './app.component';
|
||||
import { HeroListComponent } from './hero-list.component';
|
||||
import { CrisisListComponent } from './crisis-list.component';
|
||||
import { PageNotFoundComponent } from './not-found.component';
|
||||
import { PageNotFoundComponent as HeroDetailComponent } from './not-found.component';
|
||||
import { PageNotFoundComponent as HomeComponent } from './not-found.component';
|
||||
|
||||
// #docregion route-config
|
||||
@NgModule({
|
||||
imports: [
|
||||
BrowserModule,
|
||||
FormsModule,
|
||||
RouterModule.forRoot([
|
||||
// #docregion route-defs
|
||||
// #docregion hero-detail-route
|
||||
{ path: 'hero/:id', component: HeroDetailComponent },
|
||||
// #enddocregion hero-detail-route
|
||||
{ path: 'crisis-center', component: CrisisListComponent },
|
||||
{
|
||||
path: 'heroes',
|
||||
component: HeroListComponent,
|
||||
data: {
|
||||
title: 'Heroes List'
|
||||
}
|
||||
},
|
||||
{ path: '', component: HomeComponent },
|
||||
// #enddocregion route-defs
|
||||
{ path: '**', component: PageNotFoundComponent }
|
||||
])
|
||||
],
|
||||
declarations: [
|
||||
AppComponent,
|
||||
HeroListComponent,
|
||||
HeroDetailComponent,
|
||||
CrisisListComponent,
|
||||
PageNotFoundComponent
|
||||
],
|
||||
bootstrap: [ AppComponent ]
|
||||
})
|
||||
// #enddocregion router-basics
|
||||
export class AppModule {
|
||||
}
|
||||
// #enddocregion
|
|
@ -3,29 +3,31 @@
|
|||
import { NgModule } from '@angular/core';
|
||||
import { BrowserModule } from '@angular/platform-browser';
|
||||
import { FormsModule } from '@angular/forms';
|
||||
// #docregion import-router, route-config
|
||||
import { RouterModule } from '@angular/router';
|
||||
// #enddocregion import-router, route-config
|
||||
|
||||
// #docregion router-basics
|
||||
import { AppComponent } from './app.component';
|
||||
import { routing,
|
||||
appRoutingProviders } from './app.routing';
|
||||
|
||||
import { HeroListComponent } from './hero-list.component';
|
||||
import { CrisisListComponent } from './crisis-list.component';
|
||||
import { HeroListComponent } from './hero-list.component';
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
BrowserModule,
|
||||
FormsModule,
|
||||
routing
|
||||
// #docregion route-config
|
||||
RouterModule.forRoot([
|
||||
{ path: 'crisis-center', component: CrisisListComponent },
|
||||
{ path: 'heroes', component: HeroListComponent }
|
||||
])
|
||||
// #enddocregion route-config
|
||||
],
|
||||
declarations: [
|
||||
AppComponent,
|
||||
HeroListComponent,
|
||||
CrisisListComponent
|
||||
],
|
||||
providers: [
|
||||
appRoutingProviders
|
||||
],
|
||||
bootstrap: [ AppComponent ]
|
||||
})
|
||||
// #enddocregion router-basics
|
||||
|
|
|
@ -5,28 +5,23 @@ import { NgModule } from '@angular/core';
|
|||
import { BrowserModule } from '@angular/platform-browser';
|
||||
import { FormsModule } from '@angular/forms';
|
||||
|
||||
import { AppComponent } from './app.component';
|
||||
import { routing,
|
||||
appRoutingProviders } from './app.routing';
|
||||
|
||||
import { HeroesModule } from './heroes/heroes.module';
|
||||
import { AppComponent } from './app.component';
|
||||
import { AppRoutingModule } from './app-routing.module';
|
||||
|
||||
import { CrisisListComponent } from './crisis-list.component';
|
||||
import { HeroListComponent } from './hero-list.component';
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
BrowserModule,
|
||||
FormsModule,
|
||||
routing,
|
||||
HeroesModule
|
||||
AppRoutingModule
|
||||
],
|
||||
declarations: [
|
||||
AppComponent,
|
||||
HeroListComponent,
|
||||
CrisisListComponent
|
||||
],
|
||||
providers: [
|
||||
appRoutingProviders
|
||||
],
|
||||
bootstrap: [ AppComponent ]
|
||||
})
|
||||
// #enddocregion hero-import
|
||||
|
|
|
@ -1,44 +1,31 @@
|
|||
// #docplaster
|
||||
// #docregion
|
||||
// #docregion crisis-center-module, admin-module
|
||||
// #docregion hero-import
|
||||
import { NgModule } from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { BrowserModule } from '@angular/platform-browser';
|
||||
import { FormsModule } from '@angular/forms';
|
||||
|
||||
import { AppComponent } from './app.component';
|
||||
import { routing,
|
||||
appRoutingProviders } from './app.routing';
|
||||
import { AppComponent } from './app.component';
|
||||
import { AppRoutingModule } from './app-routing.module';
|
||||
|
||||
import { HeroesModule } from './heroes/heroes.module';
|
||||
// #docregion 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 { HeroesModule } from './heroes/heroes.module';
|
||||
|
||||
import { DialogService } from './dialog.service';
|
||||
import { CrisisListComponent } from './crisis-list.component';
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
CommonModule,
|
||||
BrowserModule,
|
||||
FormsModule,
|
||||
routing,
|
||||
HeroesModule,
|
||||
CrisisCenterModule,
|
||||
// #enddocregion crisis-center-module
|
||||
AdminModule
|
||||
// #docregion crisis-center-module
|
||||
AppRoutingModule
|
||||
],
|
||||
declarations: [
|
||||
AppComponent
|
||||
],
|
||||
providers: [
|
||||
appRoutingProviders,
|
||||
DialogService
|
||||
AppComponent,
|
||||
CrisisListComponent
|
||||
],
|
||||
bootstrap: [ AppComponent ]
|
||||
})
|
||||
// #enddocregion hero-import
|
||||
export class AppModule {
|
||||
}
|
||||
// #enddocregion
|
||||
|
|
|
@ -1,33 +1,42 @@
|
|||
// #docplaster
|
||||
// #docregion
|
||||
// #docregion crisis-center-module, admin-module
|
||||
import { NgModule } from '@angular/core';
|
||||
import { BrowserModule } from '@angular/platform-browser';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { FormsModule } from '@angular/forms';
|
||||
|
||||
import { AppComponent } from './app.component';
|
||||
import { routing,
|
||||
appRoutingProviders } from './app.routing';
|
||||
import { AppComponent } from './app.component';
|
||||
import { AppRoutingModule } from './app-routing.module';
|
||||
|
||||
import { HeroesModule } from './heroes/heroes.module';
|
||||
import { CrisisCenterModule } from './crisis-center/crisis-center.module';
|
||||
import { HeroesModule } from './heroes/heroes.module';
|
||||
// #docregion 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({
|
||||
imports: [
|
||||
BrowserModule,
|
||||
CommonModule,
|
||||
FormsModule,
|
||||
routing,
|
||||
HeroesModule,
|
||||
CrisisCenterModule
|
||||
CrisisCenterModule,
|
||||
// #enddocregion crisis-center-module
|
||||
AdminModule,
|
||||
// #docregion crisis-center-module
|
||||
AppRoutingModule
|
||||
],
|
||||
declarations: [
|
||||
AppComponent
|
||||
],
|
||||
providers: [
|
||||
appRoutingProviders,
|
||||
DialogService
|
||||
],
|
||||
bootstrap: [ AppComponent ]
|
||||
})
|
||||
export class AppModule {
|
||||
}
|
||||
// #enddocregion
|
||||
|
|
|
@ -1,26 +1,31 @@
|
|||
// #docregion
|
||||
import { NgModule } from '@angular/core';
|
||||
import { BrowserModule } from '@angular/platform-browser';
|
||||
import { FormsModule } from '@angular/forms';
|
||||
import { Routes, RouterModule } from '@angular/router';
|
||||
import { NgModule } from '@angular/core';
|
||||
import { BrowserModule } from '@angular/platform-browser';
|
||||
import { FormsModule } from '@angular/forms';
|
||||
|
||||
import { AppComponent } from './app.component';
|
||||
import { AppComponent } from './app.component';
|
||||
import { AppRoutingModule } from './app-routing.module';
|
||||
|
||||
const routes: Routes = [
|
||||
import { HeroesModule } from './heroes/heroes.module';
|
||||
import { CrisisCenterModule } from './crisis-center/crisis-center.module';
|
||||
import { AdminModule } from './admin/admin.module';
|
||||
|
||||
];
|
||||
import { DialogService } from './dialog.service';
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
BrowserModule,
|
||||
FormsModule,
|
||||
RouterModule.forRoot(routes, { useHash: true }) // .../#/crisis-center/
|
||||
HeroesModule,
|
||||
CrisisCenterModule,
|
||||
AdminModule,
|
||||
AppRoutingModule
|
||||
],
|
||||
declarations: [
|
||||
AppComponent
|
||||
],
|
||||
providers: [
|
||||
|
||||
DialogService
|
||||
],
|
||||
bootstrap: [ AppComponent ]
|
||||
})
|
||||
|
|
|
@ -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 {
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
// #docregion
|
||||
import { NgModule } from '@angular/core';
|
||||
import { BrowserModule } from '@angular/platform-browser';
|
||||
import { FormsModule } from '@angular/forms';
|
||||
|
||||
import { AppComponent } from './app.component';
|
||||
import { AppRoutingModule } from './app-routing.module';
|
||||
|
||||
import { HeroesModule } from './heroes/heroes.module';
|
||||
import { CrisisCenterModule } from './crisis-center/crisis-center.module';
|
||||
import { LoginRoutingModule } from './login-routing.module';
|
||||
import { DialogService } from './dialog.service';
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
BrowserModule,
|
||||
FormsModule,
|
||||
HeroesModule,
|
||||
CrisisCenterModule,
|
||||
LoginRoutingModule,
|
||||
AppRoutingModule
|
||||
],
|
||||
declarations: [
|
||||
AppComponent
|
||||
],
|
||||
providers: [
|
||||
DialogService
|
||||
],
|
||||
bootstrap: [ AppComponent ]
|
||||
})
|
||||
export class AppModule {
|
||||
}
|
|
@ -4,8 +4,8 @@ import { BrowserModule } from '@angular/platform-browser';
|
|||
import { FormsModule } from '@angular/forms';
|
||||
|
||||
import { AppComponent } from './app.component';
|
||||
import { routing,
|
||||
appRoutingProviders } from './app.routing';
|
||||
import { AppRoutingModule } from './app-routing.module';
|
||||
import { LoginRoutingModule } from './login-routing.module';
|
||||
|
||||
import { HeroesModule } from './heroes/heroes.module';
|
||||
import { CrisisCenterModule } from './crisis-center/crisis-center.module';
|
||||
|
@ -18,16 +18,16 @@ import { DialogService } from './dialog.service';
|
|||
imports: [
|
||||
BrowserModule,
|
||||
FormsModule,
|
||||
routing,
|
||||
HeroesModule,
|
||||
CrisisCenterModule
|
||||
CrisisCenterModule,
|
||||
LoginRoutingModule,
|
||||
AppRoutingModule
|
||||
],
|
||||
declarations: [
|
||||
AppComponent,
|
||||
LoginComponent
|
||||
],
|
||||
providers: [
|
||||
appRoutingProviders,
|
||||
DialogService
|
||||
],
|
||||
bootstrap: [ AppComponent ]
|
||||
|
|
|
@ -1,16 +1,16 @@
|
|||
// #docregion
|
||||
import { ModuleWithProviders } from '@angular/core';
|
||||
import { Routes, RouterModule } from '@angular/router';
|
||||
|
||||
import { loginRoutes,
|
||||
authProviders } from './login.routing';
|
||||
|
||||
const appRoutes: Routes = [
|
||||
...loginRoutes
|
||||
];
|
||||
|
||||
export const appRoutingProviders: any[] = [
|
||||
authProviders
|
||||
];
|
||||
|
||||
export const routing: ModuleWithProviders = RouterModule.forRoot(appRoutes);
|
||||
// // #docregion
|
||||
// import { ModuleWithProviders } from '@angular/core';
|
||||
// import { Routes, RouterModule } from '@angular/router';
|
||||
//
|
||||
// import { loginRoutes,
|
||||
// authProviders } from './login.routing';
|
||||
//
|
||||
// const appRoutes: Routes = [
|
||||
// ...loginRoutes
|
||||
// ];
|
||||
//
|
||||
// export const appRoutingProviders: any[] = [
|
||||
// authProviders
|
||||
// ];
|
||||
//
|
||||
// export const routing: ModuleWithProviders = RouterModule.forRoot(appRoutes);
|
||||
|
|
|
@ -1,21 +1,21 @@
|
|||
// #docregion
|
||||
import { ModuleWithProviders } from '@angular/core';
|
||||
// #docregion import-router
|
||||
import { Routes, RouterModule } from '@angular/router';
|
||||
// #enddocregion import-router
|
||||
|
||||
import { loginRoutes,
|
||||
authProviders } from './login.routing';
|
||||
|
||||
import { CanDeactivateGuard } from './can-deactivate-guard.service';
|
||||
|
||||
const appRoutes: Routes = [
|
||||
...loginRoutes
|
||||
];
|
||||
|
||||
export const appRoutingProviders: any[] = [
|
||||
authProviders,
|
||||
CanDeactivateGuard
|
||||
];
|
||||
|
||||
export const routing: ModuleWithProviders = RouterModule.forRoot(appRoutes);
|
||||
// // #docregion
|
||||
// import { ModuleWithProviders } from '@angular/core';
|
||||
// // #docregion import-router
|
||||
// import { Routes, RouterModule } from '@angular/router';
|
||||
// // #enddocregion import-router
|
||||
//
|
||||
// import { loginRoutes,
|
||||
// authProviders } from './login.routing';
|
||||
//
|
||||
// import { CanDeactivateGuard } from './can-deactivate-guard.service';
|
||||
//
|
||||
// const appRoutes: Routes = [
|
||||
// ...loginRoutes
|
||||
// ];
|
||||
//
|
||||
// export const appRoutingProviders: any[] = [
|
||||
// authProviders,
|
||||
// CanDeactivateGuard
|
||||
// ];
|
||||
//
|
||||
// export const routing: ModuleWithProviders = RouterModule.forRoot(appRoutes);
|
||||
|
|
|
@ -1,40 +0,0 @@
|
|||
// #docplaster
|
||||
// #docregion
|
||||
import { ModuleWithProviders } from '@angular/core';
|
||||
// #docregion import-router
|
||||
import { Routes, RouterModule } from '@angular/router';
|
||||
// #enddocregion import-router
|
||||
|
||||
import { loginRoutes,
|
||||
authProviders } from './login.routing';
|
||||
|
||||
import { CanDeactivateGuard } from './can-deactivate-guard.service';
|
||||
// #docregion can-load-guard
|
||||
import { AuthGuard } from './auth-guard.service';
|
||||
// #enddocregion can-load-guard
|
||||
|
||||
// #docregion lazy-load-admin, can-load-guard
|
||||
|
||||
const adminRoutes: Routes = [
|
||||
{
|
||||
path: 'admin',
|
||||
loadChildren: 'app/admin/admin.module#AdminModule',
|
||||
// #enddocregion lazy-load-admin
|
||||
canLoad: [AuthGuard]
|
||||
// #docregion lazy-load-admin
|
||||
}
|
||||
];
|
||||
// #enddocregion can-load-guard
|
||||
|
||||
const appRoutes: Routes = [
|
||||
...loginRoutes,
|
||||
...adminRoutes
|
||||
];
|
||||
// #enddocregion lazy-load-admin
|
||||
|
||||
export const appRoutingProviders: any[] = [
|
||||
authProviders,
|
||||
CanDeactivateGuard
|
||||
];
|
||||
|
||||
export const routing: ModuleWithProviders = RouterModule.forRoot(appRoutes);
|
|
@ -0,0 +1,42 @@
|
|||
// #docplaster
|
||||
// #docregion
|
||||
import { NgModule } from '@angular/core';
|
||||
import { RouterModule } from '@angular/router';
|
||||
|
||||
import { CrisisCenterHomeComponent } from './crisis-center-home.component';
|
||||
import { CrisisListComponent } from './crisis-list.component';
|
||||
import { CrisisCenterComponent } from './crisis-center.component';
|
||||
import { CrisisDetailComponent } from './crisis-detail.component';
|
||||
|
||||
// #docregion routes
|
||||
@NgModule({
|
||||
imports: [
|
||||
RouterModule.forChild([
|
||||
{
|
||||
path: 'crisis-center',
|
||||
component: CrisisCenterComponent,
|
||||
children: [
|
||||
{
|
||||
path: '',
|
||||
component: CrisisListComponent,
|
||||
children: [
|
||||
{
|
||||
path: ':id',
|
||||
component: CrisisDetailComponent
|
||||
},
|
||||
{
|
||||
path: '',
|
||||
component: CrisisCenterHomeComponent
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
])
|
||||
],
|
||||
exports: [
|
||||
RouterModule
|
||||
]
|
||||
})
|
||||
export class CrisisCenterRoutingModule { }
|
||||
// #enddocregion
|
|
@ -0,0 +1,71 @@
|
|||
// #docplaster
|
||||
// #docregion routes
|
||||
import { NgModule } from '@angular/core';
|
||||
import { RouterModule } from '@angular/router';
|
||||
|
||||
import { CrisisCenterHomeComponent } from './crisis-center-home.component';
|
||||
import { CrisisListComponent } from './crisis-list.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
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
RouterModule.forChild([
|
||||
// #enddocregion routes
|
||||
// #docregion redirect, routes
|
||||
{
|
||||
path: '',
|
||||
redirectTo: '/crisis-center',
|
||||
pathMatch: 'full'
|
||||
},
|
||||
// #enddocregion redirect, routes
|
||||
// #docregion routes
|
||||
{
|
||||
path: 'crisis-center',
|
||||
component: CrisisCenterComponent,
|
||||
children: [
|
||||
{
|
||||
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
|
||||
])
|
||||
],
|
||||
exports: [
|
||||
RouterModule
|
||||
]
|
||||
})
|
||||
export class CrisisCenterRoutingModule { }
|
||||
// #enddocregion
|
|
@ -0,0 +1,50 @@
|
|||
// #docplaster
|
||||
// #docregion
|
||||
import { NgModule } from '@angular/core';
|
||||
import { RouterModule } from '@angular/router';
|
||||
|
||||
import { CrisisCenterHomeComponent } from './crisis-center-home.component';
|
||||
import { CrisisListComponent } from './crisis-list.component';
|
||||
import { CrisisCenterComponent } from './crisis-center.component';
|
||||
import { CrisisDetailComponent } from './crisis-detail.component';
|
||||
|
||||
// #docregion can-deactivate-guard
|
||||
import { CanDeactivateGuard } from '../can-deactivate-guard.service';
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
RouterModule.forChild([
|
||||
{
|
||||
path: '',
|
||||
redirectTo: '/crisis-center',
|
||||
pathMatch: 'full'
|
||||
},
|
||||
{
|
||||
path: 'crisis-center',
|
||||
component: CrisisCenterComponent,
|
||||
children: [
|
||||
{
|
||||
path: '',
|
||||
component: CrisisListComponent,
|
||||
children: [
|
||||
{
|
||||
path: ':id',
|
||||
component: CrisisDetailComponent,
|
||||
canDeactivate: [CanDeactivateGuard]
|
||||
},
|
||||
{
|
||||
path: '',
|
||||
component: CrisisCenterHomeComponent
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
])
|
||||
],
|
||||
exports: [
|
||||
RouterModule
|
||||
]
|
||||
})
|
||||
export class CrisisCenterRoutingModule { }
|
||||
// #enddocregion
|
|
@ -0,0 +1,60 @@
|
|||
// #docplaster
|
||||
// #docregion
|
||||
import { NgModule } from '@angular/core';
|
||||
import { RouterModule } from '@angular/router';
|
||||
|
||||
import { CrisisCenterHomeComponent } from './crisis-center-home.component';
|
||||
import { CrisisListComponent } from './crisis-list.component';
|
||||
import { CrisisCenterComponent } from './crisis-center.component';
|
||||
import { CrisisDetailComponent } from './crisis-detail.component';
|
||||
|
||||
import { CanDeactivateGuard } from '../can-deactivate-guard.service';
|
||||
|
||||
// #docregion crisis-detail-resolve
|
||||
import { CrisisDetailResolve } from './crisis-detail-resolve.service';
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
RouterModule.forChild([
|
||||
// #docregion redirect
|
||||
{
|
||||
path: '',
|
||||
redirectTo: '/crisis-center',
|
||||
pathMatch: 'full'
|
||||
},
|
||||
// #enddocregion redirect
|
||||
{
|
||||
path: 'crisis-center',
|
||||
component: CrisisCenterComponent,
|
||||
children: [
|
||||
{
|
||||
path: '',
|
||||
component: CrisisListComponent,
|
||||
children: [
|
||||
{
|
||||
path: ':id',
|
||||
component: CrisisDetailComponent,
|
||||
canDeactivate: [CanDeactivateGuard],
|
||||
resolve: {
|
||||
crisis: CrisisDetailResolve
|
||||
}
|
||||
},
|
||||
{
|
||||
path: '',
|
||||
component: CrisisCenterHomeComponent
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
])
|
||||
],
|
||||
exports: [
|
||||
RouterModule
|
||||
],
|
||||
providers: [
|
||||
CrisisDetailResolve
|
||||
]
|
||||
})
|
||||
export class CrisisCenterRoutingModule { }
|
||||
// #enddocregion
|
|
@ -6,18 +6,18 @@ import { CommonModule } from '@angular/common';
|
|||
|
||||
import { CrisisService } from './crisis.service';
|
||||
|
||||
import { CrisisCenterComponent } from './crisis-center.component';
|
||||
import { CrisisListComponent } from './crisis-list.component';
|
||||
import { CrisisCenterHomeComponent } from './crisis-center-home.component';
|
||||
import { CrisisDetailComponent } from './crisis-detail.component';
|
||||
import { CrisisCenterComponent } from './crisis-center.component';
|
||||
import { CrisisListComponent } from './crisis-list.component';
|
||||
import { CrisisCenterHomeComponent } from './crisis-center-home.component';
|
||||
import { CrisisDetailComponent } from './crisis-detail.component';
|
||||
|
||||
import { crisisCenterRouting } from './crisis-center.routing';
|
||||
import { CrisisCenterRoutingModule } from './crisis-center-routing.module';
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
CommonModule,
|
||||
FormsModule,
|
||||
crisisCenterRouting
|
||||
CrisisCenterRoutingModule
|
||||
],
|
||||
declarations: [
|
||||
CrisisCenterComponent,
|
||||
|
|
|
@ -5,22 +5,19 @@ import { FormsModule } from '@angular/forms';
|
|||
import { CommonModule } from '@angular/common';
|
||||
|
||||
import { CrisisService } from './crisis.service';
|
||||
// #docregion crisis-detail-resolve
|
||||
import { CrisisDetailResolve } from './crisis-detail-resolve.service';
|
||||
// #enddocregion crisis-detail-resolve
|
||||
|
||||
import { CrisisCenterComponent } from './crisis-center.component';
|
||||
import { CrisisListComponent } from './crisis-list.component';
|
||||
import { CrisisCenterHomeComponent } from './crisis-center-home.component';
|
||||
import { CrisisDetailComponent } from './crisis-detail.component';
|
||||
|
||||
import { crisisCenterRouting } from './crisis-center.routing';
|
||||
import { CrisisCenterRoutingModule } from './crisis-center-routing.module';
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
CommonModule,
|
||||
FormsModule,
|
||||
crisisCenterRouting
|
||||
CrisisCenterRoutingModule
|
||||
],
|
||||
declarations: [
|
||||
CrisisCenterComponent,
|
||||
|
@ -28,11 +25,8 @@ import { crisisCenterRouting } from './crisis-center.routing';
|
|||
CrisisCenterHomeComponent,
|
||||
CrisisDetailComponent
|
||||
],
|
||||
// #docregion crisis-detail-resolve
|
||||
|
||||
providers: [
|
||||
CrisisService,
|
||||
CrisisDetailResolve
|
||||
CrisisService
|
||||
]
|
||||
// #enddocregion crisis-detail-resolve
|
||||
})
|
||||
|
|
|
@ -1,37 +0,0 @@
|
|||
// #docplaster
|
||||
// #docregion
|
||||
import { ModuleWithProviders } from '@angular/core';
|
||||
import { Routes, RouterModule } from '@angular/router';
|
||||
|
||||
import { CrisisCenterHomeComponent } from './crisis-center-home.component';
|
||||
import { CrisisListComponent } from './crisis-list.component';
|
||||
import { CrisisCenterComponent } from './crisis-center.component';
|
||||
import { CrisisDetailComponent } from './crisis-detail.component';
|
||||
|
||||
// #docregion routes
|
||||
const crisisCenterRoutes: Routes = [
|
||||
{
|
||||
path: 'crisis-center',
|
||||
component: CrisisCenterComponent,
|
||||
children: [
|
||||
{
|
||||
path: '',
|
||||
component: CrisisListComponent,
|
||||
children: [
|
||||
{
|
||||
path: ':id',
|
||||
component: CrisisDetailComponent
|
||||
},
|
||||
{
|
||||
path: '',
|
||||
component: CrisisCenterHomeComponent
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
];
|
||||
|
||||
export const crisisCenterRouting: ModuleWithProviders = RouterModule.forChild(crisisCenterRoutes);
|
||||
// #docregion routes
|
||||
// #enddocregion
|
|
@ -1,65 +0,0 @@
|
|||
// #docplaster
|
||||
// #docregion routes
|
||||
import { ModuleWithProviders } from '@angular/core';
|
||||
import { Routes, RouterModule } from '@angular/router';
|
||||
|
||||
import { CrisisCenterHomeComponent } from './crisis-center-home.component';
|
||||
import { CrisisListComponent } from './crisis-list.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
|
||||
|
||||
const crisisCenterRoutes: Routes = [
|
||||
// #enddocregion routes
|
||||
// #docregion redirect, routes
|
||||
{
|
||||
path: '',
|
||||
redirectTo: '/crisis-center',
|
||||
pathMatch: 'full'
|
||||
},
|
||||
// #enddocregion redirect, routes
|
||||
// #docregion routes
|
||||
{
|
||||
path: 'crisis-center',
|
||||
component: CrisisCenterComponent,
|
||||
children: [
|
||||
{
|
||||
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);
|
||||
// #enddocregion
|
|
@ -1,44 +0,0 @@
|
|||
// #docplaster
|
||||
// #docregion
|
||||
import { ModuleWithProviders } from '@angular/core';
|
||||
import { Routes, RouterModule } from '@angular/router';
|
||||
|
||||
import { CrisisCenterHomeComponent } from './crisis-center-home.component';
|
||||
import { CrisisListComponent } from './crisis-list.component';
|
||||
import { CrisisCenterComponent } from './crisis-center.component';
|
||||
import { CrisisDetailComponent } from './crisis-detail.component';
|
||||
|
||||
// #docregion can-deactivate-guard
|
||||
import { CanDeactivateGuard } from '../can-deactivate-guard.service';
|
||||
|
||||
const crisisCenterRoutes: Routes = [
|
||||
{
|
||||
path: '',
|
||||
redirectTo: '/crisis-center',
|
||||
pathMatch: 'full'
|
||||
},
|
||||
{
|
||||
path: 'crisis-center',
|
||||
component: CrisisCenterComponent,
|
||||
children: [
|
||||
{
|
||||
path: '',
|
||||
component: CrisisListComponent,
|
||||
children: [
|
||||
{
|
||||
path: ':id',
|
||||
component: CrisisDetailComponent,
|
||||
canDeactivate: [CanDeactivateGuard]
|
||||
},
|
||||
{
|
||||
path: '',
|
||||
component: CrisisCenterHomeComponent
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
];
|
||||
|
||||
export const crisisCenterRouting: ModuleWithProviders = RouterModule.forChild(crisisCenterRoutes);
|
||||
// #enddocregion
|
|
@ -1,51 +0,0 @@
|
|||
// #docplaster
|
||||
// #docregion
|
||||
import { ModuleWithProviders } from '@angular/core';
|
||||
import { Routes, RouterModule } from '@angular/router';
|
||||
|
||||
import { CrisisCenterHomeComponent } from './crisis-center-home.component';
|
||||
import { CrisisListComponent } from './crisis-list.component';
|
||||
import { CrisisCenterComponent } from './crisis-center.component';
|
||||
import { CrisisDetailComponent } from './crisis-detail.component';
|
||||
|
||||
import { CanDeactivateGuard } from '../can-deactivate-guard.service';
|
||||
|
||||
// #docregion crisis-detail-resolve
|
||||
import { CrisisDetailResolve } from './crisis-detail-resolve.service';
|
||||
|
||||
const crisisCenterRoutes: Routes = [
|
||||
// #docregion redirect
|
||||
{
|
||||
path: '',
|
||||
redirectTo: '/crisis-center',
|
||||
pathMatch: 'full'
|
||||
},
|
||||
// #enddocregion redirect
|
||||
{
|
||||
path: 'crisis-center',
|
||||
component: CrisisCenterComponent,
|
||||
children: [
|
||||
{
|
||||
path: '',
|
||||
component: CrisisListComponent,
|
||||
children: [
|
||||
{
|
||||
path: ':id',
|
||||
component: CrisisDetailComponent,
|
||||
canDeactivate: [CanDeactivateGuard],
|
||||
resolve: {
|
||||
crisis: CrisisDetailResolve
|
||||
}
|
||||
},
|
||||
{
|
||||
path: '',
|
||||
component: CrisisCenterHomeComponent
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
];
|
||||
|
||||
export const crisisCenterRouting: ModuleWithProviders = RouterModule.forChild(crisisCenterRoutes);
|
||||
// #enddocregion
|
|
@ -0,0 +1,22 @@
|
|||
// #docregion
|
||||
import { NgModule } from '@angular/core';
|
||||
import { RouterModule } from '@angular/router';
|
||||
|
||||
import { HeroListComponent } from './hero-list.component';
|
||||
import { HeroDetailComponent } from './hero-detail.component';
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
RouterModule.forChild([
|
||||
{ path: 'heroes', component: HeroListComponent },
|
||||
// #docregion hero-detail-route
|
||||
{ path: 'hero/:id', component: HeroDetailComponent }
|
||||
// #enddocregion hero-detail-route
|
||||
])
|
||||
],
|
||||
exports: [
|
||||
RouterModule
|
||||
]
|
||||
})
|
||||
export class HeroRoutingModule { }
|
||||
// #enddocregion
|
|
@ -9,13 +9,13 @@ import { HeroDetailComponent } from './hero-detail.component';
|
|||
import { HeroService } from './hero.service';
|
||||
|
||||
// #docregion heroes-routes
|
||||
import { heroesRouting } from './heroes.routing';
|
||||
import { HeroRoutingModule } from './heroes-routing.module';
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
CommonModule,
|
||||
FormsModule,
|
||||
heroesRouting
|
||||
HeroRoutingModule
|
||||
],
|
||||
declarations: [
|
||||
HeroListComponent,
|
||||
|
|
|
@ -1,16 +0,0 @@
|
|||
// #docregion
|
||||
import { ModuleWithProviders } from '@angular/core';
|
||||
import { Routes, RouterModule } 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
|
||||
];
|
||||
|
||||
export const heroesRouting: ModuleWithProviders = RouterModule.forChild(heroesRoutes);
|
||||
// #enddocregion
|
|
@ -0,0 +1,22 @@
|
|||
// #docregion
|
||||
import { NgModule } from '@angular/core';
|
||||
import { RouterModule } from '@angular/router';
|
||||
import { AuthGuard } from './auth-guard.service';
|
||||
import { AuthService } from './auth.service';
|
||||
import { LoginComponent } from './login.component';
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
RouterModule.forChild([
|
||||
{ path: 'login', component: LoginComponent }
|
||||
])
|
||||
],
|
||||
exports: [
|
||||
RouterModule
|
||||
],
|
||||
providers: [
|
||||
AuthGuard,
|
||||
AuthService
|
||||
]
|
||||
})
|
||||
export class LoginRoutingModule {}
|
|
@ -1,14 +0,0 @@
|
|||
// #docregion
|
||||
import { Routes } from '@angular/router';
|
||||
import { AuthGuard } from './auth-guard.service';
|
||||
import { AuthService } from './auth.service';
|
||||
import { LoginComponent } from './login.component';
|
||||
|
||||
export const loginRoutes: Routes = [
|
||||
{ path: 'login', component: LoginComponent }
|
||||
];
|
||||
|
||||
export const authProviders = [
|
||||
AuthGuard,
|
||||
AuthService
|
||||
];
|
|
@ -1,3 +1,4 @@
|
|||
import { NgModule } from '@angular/core';
|
||||
import { RouterModule, Routes } from '@angular/router';
|
||||
|
||||
import { HeroListComponent } from './hero-list.component';
|
||||
|
@ -9,4 +10,9 @@ const routes: Routes = [
|
|||
];
|
||||
|
||||
export const routedComponents = [HeroDetailComponent, HeroListComponent];
|
||||
export const routing = RouterModule.forChild(routes);
|
||||
|
||||
@NgModule({
|
||||
imports: [RouterModule.forChild(routes)],
|
||||
exports: [RouterModule]
|
||||
})
|
||||
export class HeroRoutingModule {}
|
|
@ -1,9 +1,9 @@
|
|||
import { NgModule } from '@angular/core';
|
||||
import { SharedModule } from '../shared/shared.module';
|
||||
import { routedComponents, routing } from './hero.routing';
|
||||
import { routedComponents, HeroRoutingModule } from './hero-routing.module';
|
||||
|
||||
@NgModule({
|
||||
imports: [ SharedModule, routing ],
|
||||
imports: [ SharedModule, HeroRoutingModule ],
|
||||
declarations: [ routedComponents ]
|
||||
})
|
||||
export class HeroModule { }
|
||||
|
|
|
@ -0,0 +1,48 @@
|
|||
// #docplaster
|
||||
// #docregion
|
||||
import { NgModule } from '@angular/core';
|
||||
import { BrowserModule } from '@angular/platform-browser';
|
||||
import { FormsModule } from '@angular/forms';
|
||||
import { RouterModule } from '@angular/router';
|
||||
|
||||
import { AppComponent } from './app.component';
|
||||
import { HeroDetailComponent } from './hero-detail.component';
|
||||
import { HeroesComponent } from './heroes.component';
|
||||
import { HeroService } from './hero.service';
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
BrowserModule,
|
||||
FormsModule,
|
||||
RouterModule.forRoot([
|
||||
{
|
||||
path: 'heroes',
|
||||
component: HeroesComponent
|
||||
}
|
||||
])
|
||||
],
|
||||
declarations: [
|
||||
AppComponent,
|
||||
HeroDetailComponent,
|
||||
HeroesComponent
|
||||
],
|
||||
providers: [
|
||||
HeroService
|
||||
],
|
||||
bootstrap: [ AppComponent ]
|
||||
})
|
||||
export class AppModule {
|
||||
}
|
||||
// #enddocregion
|
||||
/*
|
||||
// #docregion heroes, routing
|
||||
import { RouterModule } from '@angular/router';
|
||||
|
||||
RouterModule.forRoot([
|
||||
{
|
||||
path: 'heroes',
|
||||
component: HeroesComponent
|
||||
}
|
||||
])
|
||||
// #enddocregion heroes, routing
|
||||
*/
|
|
@ -0,0 +1,59 @@
|
|||
// #docregion
|
||||
import { NgModule } from '@angular/core';
|
||||
import { BrowserModule } from '@angular/platform-browser';
|
||||
import { FormsModule } from '@angular/forms';
|
||||
import { RouterModule } from '@angular/router';
|
||||
|
||||
import { AppComponent } from './app.component';
|
||||
import { HeroDetailComponent } from './hero-detail.component';
|
||||
import { DashboardComponent } from './dashboard.component';
|
||||
import { HeroesComponent } from './heroes.component';
|
||||
import { HeroService } from './hero.service';
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
BrowserModule,
|
||||
FormsModule,
|
||||
RouterModule.forRoot([
|
||||
// #docregion redirect
|
||||
{
|
||||
path: '',
|
||||
redirectTo: '/dashboard',
|
||||
pathMatch: 'full'
|
||||
},
|
||||
// #enddocregion redirect
|
||||
// #docregion dashboard
|
||||
{
|
||||
path: 'dashboard',
|
||||
component: DashboardComponent
|
||||
},
|
||||
// #enddocregion dashboard
|
||||
// #docregion hero-detail
|
||||
{
|
||||
path: 'detail/:id',
|
||||
component: HeroDetailComponent
|
||||
},
|
||||
// #enddocregion hero-detail
|
||||
// #docregion heroes
|
||||
// #docregion heroes, routing
|
||||
{
|
||||
path: 'heroes',
|
||||
component: HeroesComponent
|
||||
}
|
||||
// #enddocregion heroes, routing
|
||||
])
|
||||
],
|
||||
declarations: [
|
||||
AppComponent,
|
||||
DashboardComponent,
|
||||
HeroDetailComponent,
|
||||
HeroesComponent
|
||||
],
|
||||
providers: [
|
||||
HeroService
|
||||
],
|
||||
bootstrap: [ AppComponent ]
|
||||
})
|
||||
export class AppModule {
|
||||
}
|
||||
// #enddocregion
|
|
@ -3,21 +3,37 @@
|
|||
import { NgModule } from '@angular/core';
|
||||
import { BrowserModule } from '@angular/platform-browser';
|
||||
import { FormsModule } from '@angular/forms';
|
||||
import { RouterModule } from '@angular/router';
|
||||
|
||||
import { AppComponent } from './app.component';
|
||||
import { DashboardComponent } from './dashboard.component';
|
||||
import { HeroDetailComponent } from './hero-detail.component';
|
||||
import { HeroesComponent } from './heroes.component';
|
||||
import { HeroService } from './hero.service';
|
||||
// #docregion routing
|
||||
import { routing } from './app.routing';
|
||||
// #docregion routing
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
BrowserModule,
|
||||
FormsModule,
|
||||
routing
|
||||
RouterModule.forRoot([
|
||||
{
|
||||
path: '',
|
||||
redirectTo: '/dashboard',
|
||||
pathMatch: 'full'
|
||||
},
|
||||
{
|
||||
path: 'dashboard',
|
||||
component: DashboardComponent
|
||||
},
|
||||
{
|
||||
path: 'detail/:id',
|
||||
component: HeroDetailComponent
|
||||
},
|
||||
{
|
||||
path: 'heroes',
|
||||
component: HeroesComponent
|
||||
}
|
||||
])
|
||||
],
|
||||
// #enddocregion routing
|
||||
// #docregion dashboard, hero-detail
|
||||
|
|
|
@ -1,17 +0,0 @@
|
|||
// #docregion , heroes, routing
|
||||
import { ModuleWithProviders } from '@angular/core';
|
||||
import { Routes, RouterModule } from '@angular/router';
|
||||
|
||||
import { HeroesComponent } from './heroes.component';
|
||||
|
||||
const appRoutes: Routes = [
|
||||
{
|
||||
path: 'heroes',
|
||||
component: HeroesComponent
|
||||
}
|
||||
];
|
||||
// #enddocregion heroes, routing
|
||||
|
||||
// #docregion routing-export
|
||||
export const routing: ModuleWithProviders = RouterModule.forRoot(appRoutes);
|
||||
// #enddocregion routing-export
|
|
@ -1,43 +0,0 @@
|
|||
// #docplaster
|
||||
// #docregion , heroes
|
||||
import { ModuleWithProviders } from '@angular/core';
|
||||
import { Routes, RouterModule } from '@angular/router';
|
||||
|
||||
// #enddocregion heroes
|
||||
import { DashboardComponent } from './dashboard.component';
|
||||
// #docregion heroes
|
||||
import { HeroesComponent } from './heroes.component';
|
||||
// #enddocregion heroes
|
||||
import { HeroDetailComponent } from './hero-detail.component';
|
||||
// #docregion heroes
|
||||
|
||||
const appRoutes: Routes = [
|
||||
// #enddocregion heroes
|
||||
// #docregion redirect
|
||||
{
|
||||
path: '',
|
||||
redirectTo: '/dashboard',
|
||||
pathMatch: 'full'
|
||||
},
|
||||
// #enddocregion redirect
|
||||
// #docregion dashboard
|
||||
{
|
||||
path: 'dashboard',
|
||||
component: DashboardComponent
|
||||
},
|
||||
// #enddocregion dashboard
|
||||
// #docregion hero-detail
|
||||
{
|
||||
path: 'detail/:id',
|
||||
component: HeroDetailComponent
|
||||
},
|
||||
// #enddocregion hero-detail
|
||||
// #docregion heroes
|
||||
{
|
||||
path: 'heroes',
|
||||
component: HeroesComponent
|
||||
}
|
||||
];
|
||||
// #enddocregion heroes
|
||||
|
||||
export const routing: ModuleWithProviders = RouterModule.forRoot(appRoutes);
|
|
@ -9,6 +9,7 @@ import { NgModule } from '@angular/core';
|
|||
import { BrowserModule } from '@angular/platform-browser';
|
||||
import { FormsModule } from '@angular/forms';
|
||||
import { HttpModule } from '@angular/http';
|
||||
import { RouterModule } from '@angular/router';
|
||||
|
||||
// #enddocregion v1
|
||||
// Imports for loading & configuring the in-memory web api
|
||||
|
@ -24,7 +25,6 @@ import { HeroService } from './hero.service';
|
|||
// #enddocregion v1, v2
|
||||
import { HeroSearchComponent } from './hero-search.component';
|
||||
// #docregion v1, v2
|
||||
import { routing } from './app.routing';
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
|
@ -36,7 +36,25 @@ import { routing } from './app.routing';
|
|||
InMemoryWebApiModule.forRoot(InMemoryDataService),
|
||||
// #enddocregion in-mem-web-api
|
||||
// #docregion v1
|
||||
routing
|
||||
RouterModule.forRoot([
|
||||
{
|
||||
path: '',
|
||||
redirectTo: '/dashboard',
|
||||
pathMatch: 'full'
|
||||
},
|
||||
{
|
||||
path: 'dashboard',
|
||||
component: DashboardComponent
|
||||
},
|
||||
{
|
||||
path: 'detail/:id',
|
||||
component: HeroDetailComponent
|
||||
},
|
||||
{
|
||||
path: 'heroes',
|
||||
component: HeroesComponent
|
||||
}
|
||||
])
|
||||
],
|
||||
// #docregion search
|
||||
declarations: [
|
||||
|
|
|
@ -1,29 +0,0 @@
|
|||
// #docregion
|
||||
import { ModuleWithProviders } from '@angular/core';
|
||||
import { Routes, RouterModule } from '@angular/router';
|
||||
|
||||
import { DashboardComponent } from './dashboard.component';
|
||||
import { HeroesComponent } from './heroes.component';
|
||||
import { HeroDetailComponent } from './hero-detail.component';
|
||||
|
||||
const appRoutes: Routes = [
|
||||
{
|
||||
path: '',
|
||||
redirectTo: '/dashboard',
|
||||
pathMatch: 'full'
|
||||
},
|
||||
{
|
||||
path: 'dashboard',
|
||||
component: DashboardComponent
|
||||
},
|
||||
{
|
||||
path: 'detail/:id',
|
||||
component: HeroDetailComponent
|
||||
},
|
||||
{
|
||||
path: 'heroes',
|
||||
component: HeroesComponent
|
||||
}
|
||||
];
|
||||
|
||||
export const routing: ModuleWithProviders = RouterModule.forRoot(appRoutes);
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
block includes
|
||||
include ../_util-fns
|
||||
- var _appRoutingTsVsAppComp = 'app.routing.ts'
|
||||
- var _appRoutingTsVsAppComp = 'app-routing.module.ts'
|
||||
- var _declsVsDirectives = 'declarations'
|
||||
- var _RoutesVsAtRouteConfig = 'Routes'
|
||||
- var _RouterModuleVsRouterDirectives = 'RouterModule'
|
||||
|
@ -202,7 +202,7 @@ block router-config-intro
|
|||
|
||||
Let's define our first route as a route to the heroes component:
|
||||
|
||||
- var _file = _docsFor == 'dart' ? 'app.component.ts' : 'app.routing.ts'
|
||||
- var _file = _docsFor == 'dart' ? 'app.component.ts' : 'app-routing.module.ts'
|
||||
+makeExcerpt('app/' + _file + ' (heroes route)', 'heroes')
|
||||
|
||||
- var _are = _docsFor == 'dart' ? 'takes' : 'are'
|
||||
|
@ -227,7 +227,7 @@ block router-config-intro
|
|||
We'll export a `routing` constant initialized using the `RouterModule.forRoot` method applied to our !{_array} of routes.
|
||||
This method returns a **configured router module** that we'll add to our root NgModule, `AppModule`.
|
||||
|
||||
+makeExcerpt('app/app.routing.1.ts (excerpt)', 'routing-export')
|
||||
+makeExcerpt('app/app-routing.module.1.ts (excerpt)', 'routing-export')
|
||||
|
||||
.l-sub-section
|
||||
:marked
|
||||
|
@ -237,9 +237,9 @@ block router-config-intro
|
|||
:marked
|
||||
### Make the router available
|
||||
|
||||
We've setup initial routes in the `app.routing.ts` file. Now we'll add it to our root NgModule.
|
||||
We've setup initial routes in the `app-routing.module.ts` file. Now we'll add it to our root NgModule.
|
||||
|
||||
Import the `routing` constant from `app.routing.ts` and add it the `imports` !{_array} of `AppModule`.
|
||||
Import the `routing` constant from `app-routing.module.ts` and add it the `imports` !{_array} of `AppModule`.
|
||||
|
||||
+makeExcerpt('app/app.module.ts', 'routing')
|
||||
|
||||
|
@ -319,7 +319,7 @@ block routerLink
|
|||
Import the dashboard component and
|
||||
add the following route definition to the `!{_RoutesVsAtRouteConfig}` !{_array} of definitions.
|
||||
|
||||
- var _file = _docsFor == 'dart' ? 'lib/app_component.dart' : 'app/app.routing.ts'
|
||||
- var _file = _docsFor == 'dart' ? 'lib/app_component.dart' : 'app/app-routing.module.ts'
|
||||
+makeExcerpt(_file + ' (Dashboard route)', 'dashboard')
|
||||
|
||||
+ifDocsFor('ts|js')
|
||||
|
@ -340,7 +340,7 @@ block redirect-vs-use-as-default
|
|||
We can use a redirect route to make this happen. Add the following
|
||||
to our array of route definitions:
|
||||
|
||||
+makeExcerpt('app/app.routing.ts','redirect')
|
||||
+makeExcerpt('app/app-routing.module.ts','redirect')
|
||||
|
||||
.l-sub-section
|
||||
:marked
|
||||
|
@ -472,7 +472,7 @@ code-example(format='').
|
|||
|
||||
Here's the *route definition* we'll use.
|
||||
|
||||
- var _file = _docsFor == 'dart' ? 'app/app.component.ts' : 'app/app.routing.ts'
|
||||
- var _file = _docsFor == 'dart' ? 'app/app.component.ts' : 'app/app-routing.module.ts'
|
||||
+makeExcerpt(_file + ' (hero detail)','hero-detail')
|
||||
|
||||
:marked
|
||||
|
@ -639,7 +639,7 @@ block extract-id
|
|||
token in the parameterized hero detail route definition we added to
|
||||
`!{_appRoutingTsVsAppComp}` earlier in the chapter:
|
||||
|
||||
- var _file = _docsFor == 'dart' ? 'app/app.component.ts' : 'app/app.routing.ts'
|
||||
- var _file = _docsFor == 'dart' ? 'app/app.component.ts' : 'app/app-routing.module.ts'
|
||||
+makeExcerpt(_file + ' (hero detail)', 'hero-detail')
|
||||
|
||||
:marked
|
||||
|
@ -868,7 +868,7 @@ block file-tree-end
|
|||
.file app.component.css
|
||||
.file app.component.ts
|
||||
.file app.module.ts
|
||||
.file app.routing.ts
|
||||
.file app-routing.module.ts
|
||||
.file dashboard.component.css
|
||||
.file dashboard.component.html
|
||||
.file dashboard.component.ts
|
||||
|
|
|
@ -539,7 +539,7 @@ block filetree
|
|||
.file app.component.ts
|
||||
.file app.component.css
|
||||
.file app.module.ts
|
||||
.file app.routing.ts
|
||||
.file app-routing.module.ts
|
||||
.file dashboard.component.css
|
||||
.file dashboard.component.html
|
||||
.file dashboard.component.ts
|
||||
|
|
|
@ -27,7 +27,7 @@ block includes
|
|||
* [Should I import _BrowserModule_ or _CommonModule_?](#q-browser-vs-common-module)
|
||||
* [What if I import the same module twice?](#q-reimport)
|
||||
|
||||
Exports
|
||||
Exports
|
||||
* [What should I export?](#q-what-to-export)
|
||||
* [What should I *not* export?](#q-what-not-to-export)
|
||||
* [Can I re-export imported classes and modules?](#q-re-export)
|
||||
|
@ -41,7 +41,7 @@ block includes
|
|||
* [Should I add app-wide providers to the root _AppModule_ or the root _AppComponent_?](#q-root-component-or-module)
|
||||
* [Should I add other providers to a module or a component?](#q-component-or-module)
|
||||
* [Why is it bad if _SharedModule_ provides a service to a lazy loaded module?](#q-why-bad)
|
||||
* [Why does lazy loading create a child injector?](#q-why-child-injector)
|
||||
* [Why does lazy loading create a child injector?](#q-why-child-injector)
|
||||
* [How can I tell if a module or service was previously loaded?](#q-is-it-loaded)
|
||||
|
||||
Entry Components
|
||||
|
@ -54,7 +54,7 @@ block includes
|
|||
* [What kinds of modules should I have and how should I use them?](#q-module-recommendations)
|
||||
* [What's the difference between Angular and JavaScript Modules?](#q-ng-vs-js-modules)
|
||||
* [What is a "template reference"?](#q-template-reference)
|
||||
* [How does Angular find components, directives, and pipes in a template?](#q-template-reference)
|
||||
* [How does Angular find components, directives, and pipes in a template?](#q-template-reference)
|
||||
* [What is the Angular Compiler?](#q-angular-compiler)
|
||||
* [Can you summarize the _NgModule_ API?](#q-ngmodule-api)
|
||||
|
||||
|
@ -76,9 +76,9 @@ a#q-declarable
|
|||
.l-main-section
|
||||
:marked
|
||||
### What is a _declarable_?
|
||||
|
||||
|
||||
_Declarables_ are the class types — components, directives, and pipes —
|
||||
that you can add to a module's `declarations` list.
|
||||
that you can add to a module's `declarations` list.
|
||||
They're the _only_ classes that you can add to `declarations`.
|
||||
|
||||
.l-hr
|
||||
|
@ -90,17 +90,17 @@ a#q-what-not-to-declare
|
|||
|
||||
Only [declarable](#q-declarable) classes can be added to a module's `declarations` list.
|
||||
|
||||
Do *not* declare
|
||||
Do *not* declare
|
||||
* a class that is already declared in another module, whether an app module, @angular module, or 3rd party module
|
||||
|
||||
* an array of directives imported from another module.
|
||||
* an array of directives imported from another module.
|
||||
For example, do not declare FORMS_DIRECTIVES from `@angular/forms`.
|
||||
|
||||
* module classes
|
||||
|
||||
|
||||
* service classes
|
||||
|
||||
* non-Angular classes and objects such as
|
||||
* non-Angular classes and objects such as
|
||||
strings, numbers, functions, entity models, configurations, business logic, and helper classes.
|
||||
|
||||
.l-hr
|
||||
|
@ -112,8 +112,8 @@ a#q-why-multiple-mentions
|
|||
|
||||
We often see `AppComponent` listed in both `declarations` and `bootstrap`.
|
||||
We might see `HeroComponent` listed in `declarations`, `exports`, and `entryComponents`.
|
||||
|
||||
That _feels_ redundant but these properties have different functions
|
||||
|
||||
That _feels_ redundant but these properties have different functions
|
||||
and we can't infer that membership in one list implies membership in another list.
|
||||
|
||||
* `AppComponent` could be declared in this module but not bootstrapped.
|
||||
|
@ -128,12 +128,12 @@ a#q-why-cant-bind-to
|
|||
:marked
|
||||
### What does "_Can't bind to 'x' since it isn't a known property of 'y'_" mean?
|
||||
|
||||
This error usually means either that you neglected to declare the directive "x"
|
||||
This error usually means either that you neglected to declare the directive "x"
|
||||
or you haven't imported the module to which "x" belongs.
|
||||
|
||||
For example, if "x" is `ngModel`, you probably haven't imported the `FormsModule` from `@angular/forms`.
|
||||
|
||||
Perhaps you declared "x" in an application sub-module but forgot to export it?
|
||||
Perhaps you declared "x" in an application sub-module but forgot to export it?
|
||||
The "x" class won't be visible to other modules until you add it to the `exports` list.
|
||||
|
||||
.l-hr
|
||||
|
@ -143,14 +143,14 @@ a#q-what-to-import
|
|||
:marked
|
||||
### What should I import?
|
||||
|
||||
Import modules whose public (exported) [declarable classes](#q-declarable)
|
||||
Import modules whose public (exported) [declarable classes](#q-declarable)
|
||||
you need to reference in this module's component templates.
|
||||
|
||||
This invariably means importing `CommonModule` from `@angular/common` for access to
|
||||
the Angular directives such as `NgIf` and `NgFor`.
|
||||
the Angular directives such as `NgIf` and `NgFor`.
|
||||
You can import it directly or from another module that [re-exports](#q-reexport) it.
|
||||
|
||||
Import `FormsModule` from `@angular/forms`
|
||||
Import `FormsModule` from `@angular/forms`
|
||||
if your components have `[(ngModel)]` two-way binding expressions.
|
||||
|
||||
Import _shared_ and _feature_ modules when this module's components incorporate their
|
||||
|
@ -167,16 +167,16 @@ a#q-browser-vs-common-module
|
|||
|
||||
The **root application module** (`AppModule`) of almost every browser application
|
||||
should import `BrowserModule` from `@angular/platform-browser`.
|
||||
|
||||
|
||||
`BrowserModule` provides services that are essential to launch and run a browser app.
|
||||
|
||||
`BrowserModule` also re-exports `CommonModule` from `@angular/common`
|
||||
which means that component in the `AppModule` module also have access to
|
||||
the Angular directives every app needs such as `NgIf` and `NgFor`.
|
||||
|
||||
|
||||
_Do not import_ `BrowserModule` in any other module.
|
||||
*Feature modules* and *lazy loaded modules* should import `CommonModule` instead.
|
||||
They need the common directives. They don't need to re-install the app-wide providers.
|
||||
They need the common directives. They don't need to re-install the app-wide providers.
|
||||
.l-sub-section
|
||||
:marked
|
||||
`BrowserModule` throws an error if you try to lazy load a module that imports it.
|
||||
|
@ -184,14 +184,14 @@ a#q-browser-vs-common-module
|
|||
Importing `CommonModule` also frees feature modules for use on _any_ target platform, not just browsers,
|
||||
a fact of some interest to authors of cross-platform libraries.
|
||||
|
||||
.l-hr
|
||||
.l-hr
|
||||
a#q-reimport
|
||||
.l-main-section
|
||||
:marked
|
||||
### What if I import the same module twice?
|
||||
|
||||
That's not a problem. When three modules all import Module 'A',
|
||||
Angular evaluates Module 'A' once, the first time it encounters it, and does not do so again.
|
||||
|
||||
That's not a problem. When three modules all import Module 'A',
|
||||
Angular evaluates Module 'A' once, the first time it encounters it, and does not do so again.
|
||||
|
||||
That's true at whatever level `A` appears in a hierarchy of imported modules.
|
||||
When Module 'B' imports Module 'A', Module 'C' imports 'B', and Module 'D' imports `[C, B, A]`,
|
||||
|
@ -200,7 +200,7 @@ a#q-reimport
|
|||
|
||||
Angular does not like modules with circular references so don't let Module 'A' import Module 'B' which imports Module 'A'.
|
||||
|
||||
.l-hr
|
||||
.l-hr
|
||||
a#q-what-to-export
|
||||
.l-main-section
|
||||
:marked
|
||||
|
@ -211,11 +211,11 @@ a#q-what-to-export
|
|||
If you don't export a class, it stays _private_, visible only to other component
|
||||
declared in this module.
|
||||
|
||||
You _can_ export any declarable class — components, directives, and pipes —
|
||||
You _can_ export any declarable class — components, directives, and pipes —
|
||||
whether it is declared in this module or in an imported module.
|
||||
|
||||
You _can_ re-export entire imported modules which effectively re-exports all of their exported classes.
|
||||
A module can even export a module that it doesn't import.
|
||||
A module can even export a module that it doesn't import.
|
||||
|
||||
.l-hr
|
||||
|
||||
|
@ -230,12 +230,12 @@ a#q-what-not-to-export
|
|||
If you don't want another module to see it, don't export it.
|
||||
|
||||
* Non-declarable objects such as services, functions, configurations, entity models, etc.
|
||||
|
||||
|
||||
* Components that are only loaded dynamically by the router or by bootstrapping.
|
||||
Such [entry components](#q-entry-component-defined) can never be selected in another component's template.
|
||||
There's no harm in exporting them but no benefit either.
|
||||
There's no harm in exporting them but no benefit either.
|
||||
|
||||
* Pure service modules that don't have public (exported) declarations.
|
||||
* Pure service modules that don't have public (exported) declarations.
|
||||
For example, there is no point in re-exporting `HttpModule` because it doesn't export anything.
|
||||
It's only purpose is to add http service providers to the application as a whole.
|
||||
|
||||
|
@ -274,10 +274,10 @@ a#q-for-root
|
|||
### What is the _forRoot_ method?
|
||||
|
||||
The `forRoot` static method is a convention that makes it easy for developers to configure the module's provider(s).
|
||||
|
||||
The `RouterModule.forRoot` method is a good example.
|
||||
Apps pass a `Routes` object to `RouterModule.forRoot` in order to configure the app-wide `Router` service with routes.
|
||||
`RouterModule.forRoot` returns a [ModuleWithProviders](../api/core/index/ModuleWithProviders-interface.html).
|
||||
|
||||
The `RouterModule.forRoot` method is a good example.
|
||||
Apps pass a `Routes` object to `RouterModule.forRoot` in order to configure the app-wide `Router` service with routes.
|
||||
`RouterModule.forRoot` returns a [ModuleWithProviders](../api/core/index/ModuleWithProviders-interface.html).
|
||||
We add that result to the `imports` list of the root `AppModule`.
|
||||
|
||||
.alert.is-important
|
||||
|
@ -290,7 +290,7 @@ a#q-for-root
|
|||
|
||||
**_forRoot_** and **_forChild_** are conventional names for methods that
|
||||
configure services in root and feature modules respectively.
|
||||
|
||||
|
||||
Angular doesn't recognize these names but Angular developers do.
|
||||
Follow this convention when you write similar modules with configurable service providers.
|
||||
|
||||
|
@ -310,16 +310,16 @@ a#q-module-provider-visibility
|
|||
|
||||
This makes the provider visible to every class in the application that knows the provider's lookup token.
|
||||
|
||||
This is by design.
|
||||
This is by design.
|
||||
Extensibility through module imports is a primary goal of the Angular module system.
|
||||
Merging module providers into the application injector
|
||||
makes it easy for a module library to enrich the entire application with new services.
|
||||
By adding the `HttpModule` once, every application component can make http requests.
|
||||
|
||||
However, this can feel like an unwelcome surprise if you are expecting the module's services
|
||||
By adding the `HttpModule` once, every application component can make http requests.
|
||||
|
||||
However, this can feel like an unwelcome surprise if you are expecting the module's services
|
||||
to be visible only to the components declared by that feature module.
|
||||
If the `HeroModule` provides the `HeroService` and the root `AppModule` imports `HeroModule`,
|
||||
any class that knows the `HeroService` _type_ can inject that service,
|
||||
If the `HeroModule` provides the `HeroService` and the root `AppModule` imports `HeroModule`,
|
||||
any class that knows the `HeroService` _type_ can inject that service,
|
||||
not just the classes declared in the `HeroModule`.
|
||||
|
||||
.l-hr
|
||||
|
@ -328,8 +328,8 @@ a#q-lazy-loaded-module-provider-visibility
|
|||
.l-main-section
|
||||
:marked
|
||||
### Why is a service provided in a lazy loaded module visible only to that module?
|
||||
|
||||
Unlike providers of the modules loaded at launch,
|
||||
|
||||
Unlike providers of the modules loaded at launch,
|
||||
providers of lazy loaded modules are *module-scoped*.
|
||||
|
||||
When the Angular router lazy-loads a module, it creates a new execution context.
|
||||
|
@ -346,11 +346,11 @@ a#q-module-provider-duplicates
|
|||
.l-main-section
|
||||
:marked
|
||||
### What if two modules provide the _same_ service?
|
||||
|
||||
When two imported modules, loaded at the same time, list a provider with the same token,
|
||||
|
||||
When two imported modules, loaded at the same time, list a provider with the same token,
|
||||
the second module's provider "wins". That's because both providers are added to the same injector.
|
||||
|
||||
When Angular looks to inject a service for that token,
|
||||
When Angular looks to inject a service for that token,
|
||||
it creates and delivers the instance created by the second provider.
|
||||
|
||||
_Every_ class that injects this service gets the instance created by the second provider.
|
||||
|
@ -373,7 +373,7 @@ a#q-component-scoped-providers
|
|||
When a module is loaded at application launch,
|
||||
its `@NgModule.providers` have ***application-wide scope***.
|
||||
They are available for injection throughout the application.
|
||||
|
||||
|
||||
Imported providers are easily replaced by providers from another imported module.
|
||||
Such replacement may be by design. It could be unintentional and have adverse consequences.
|
||||
|
||||
|
@ -385,7 +385,7 @@ a#q-component-scoped-providers
|
|||
:marked
|
||||
Suppose a module requires a customized `HttpBackend` that adds a special header for all Http requests.
|
||||
If another module elsewhere in the application also customizes `HttpBackend`
|
||||
or merely imports the `HttpModule`, it could override this module's `HttpBackend` provider,
|
||||
or merely imports the `HttpModule`, it could override this module's `HttpBackend` provider,
|
||||
losing the special header. The server will reject http requests from this module.
|
||||
|
||||
.alert.is-important
|
||||
|
@ -395,25 +395,25 @@ a#q-component-scoped-providers
|
|||
:marked
|
||||
If you must guard against this kind of "provider corruption", *don't rely on a launch-time module's `providers`.*
|
||||
|
||||
Load the module lazily if you can.
|
||||
Load the module lazily if you can.
|
||||
Angular gives a [lazy-loaded module](#q-lazy-loaded-module-provider-visibility) its own child injector.
|
||||
The module's providers are visible only within the component tree created with this injector.
|
||||
|
||||
If you must load the module eagerly, when the application starts,
|
||||
***provide the service in a component instead.***
|
||||
|
||||
|
||||
Continuing with the same example, suppose the components of a module truly require a private, custom `HttpBackend`.
|
||||
|
||||
Create a "top component" that acts as the root for all of the module's components.
|
||||
Create a "top component" that acts as the root for all of the module's components.
|
||||
Add the custom `HttpBackend` provider to the top component's `providers` list rather than the module's `providers`.
|
||||
Recall that Angular creates a child injector for each component instance and populates the injector
|
||||
with the component's own providers.
|
||||
|
||||
|
||||
When a child of this component _asks_ for the `HttpBackend` service,
|
||||
Angular provides the local `HttpBackend` service,
|
||||
Angular provides the local `HttpBackend` service,
|
||||
not the version provided in the application root injector.
|
||||
Child components will make proper http requests no matter what other modules do to `HttpBackend`.
|
||||
|
||||
|
||||
Be sure to create module components as children of this module's top component.
|
||||
|
||||
You can embed the child components in the top component's template.
|
||||
|
@ -441,22 +441,22 @@ a#q-root-component-or-module
|
|||
|
||||
#### **_Discussion_:**
|
||||
Angular registers all startup module providers with the application root injector.
|
||||
The services created from root injector providers are available to the entire application.
|
||||
The services created from root injector providers are available to the entire application.
|
||||
They are _application-scoped_.
|
||||
|
||||
|
||||
Certain services (e.g., the `Router`) only work when registered in the application root injector.
|
||||
|
||||
By contrast, Angular registers `AppComponent` providers with the `AppComponent`'s own injector.
|
||||
`AppComponent`services are available only to that component and its component tree.
|
||||
`AppComponent`services are available only to that component and its component tree.
|
||||
They are _component-scoped_.
|
||||
|
||||
The `AppComponent`'s injector is a _child_ of the root injector, one down in the injector hierarchy.
|
||||
That is _almost_ the entire application for apps that don't use the router.
|
||||
But "almost" isn't good enough for routed applications.
|
||||
|
||||
`AppComponent` services don't exist at the root level where routing operates.
|
||||
`AppComponent` services don't exist at the root level where routing operates.
|
||||
Lazy loaded modules can't reach them.
|
||||
In the Angular Module Chapter sample applications, if we had registered `UserService` in the `AppComponent`,
|
||||
In the Angular Module Chapter sample applications, if we had registered `UserService` in the `AppComponent`,
|
||||
the `HeroComponent` couldn't inject it.
|
||||
The application would fail the moment a user navigated to "Heroes".
|
||||
|
||||
|
@ -469,17 +469,17 @@ a#q-component-or-module
|
|||
|
||||
In general, prefer registering feature-specific providers in modules (`@NgModule.providers`)
|
||||
to registering in components (`@Component.providers`).
|
||||
|
||||
|
||||
Register a provider with a component when you _must_ limit the scope of a service instance
|
||||
to that component and its component tree.
|
||||
to that component and its component tree.
|
||||
Apply the same reasoning to registering a provider with a directive.
|
||||
|
||||
For example, a hero editing component that needs a private copy of a caching hero service should register
|
||||
the `HeroService` with the `HeroEditorComponent`.
|
||||
Then each new instance of the `HeroEditorComponent` gets its own cached service instance.
|
||||
the `HeroService` with the `HeroEditorComponent`.
|
||||
Then each new instance of the `HeroEditorComponent` gets its own cached service instance.
|
||||
The changes that editor makes to heroes in its service do not touch the hero instances elsewhere in the application.
|
||||
|
||||
[Always register _application-wide_ services with the root `AppModule`](q-root-component-or-module),
|
||||
[Always register _application-wide_ services with the root `AppModule`](q-root-component-or-module),
|
||||
not the root `AppComponent`.
|
||||
|
||||
.l-hr
|
||||
|
@ -488,7 +488,7 @@ a#q-why-bad
|
|||
:marked
|
||||
### Why is it bad if _SharedModule_ provides a service to a lazy loaded module?
|
||||
|
||||
This question arose in the [Angular Module](../guide/ngmodule.html#no-shared-module-providers) chapter
|
||||
This question arose in the [Angular Module](../guide/ngmodule.html#no-shared-module-providers) chapter
|
||||
when we discussed the importance of keeping providers out of the `SharedModule`.
|
||||
|
||||
Suppose we had listed the `UserService` in the module's `providers` (which we did not).
|
||||
|
@ -496,16 +496,16 @@ a#q-why-bad
|
|||
|
||||
When the app starts, Angular eagerly loads the `AppModule` and the `ContactModule`.
|
||||
|
||||
Both instances of the imported `SharedModule` would provide the `UserService`.
|
||||
Both instances of the imported `SharedModule` would provide the `UserService`.
|
||||
Angular registers one of them in the root app injector (see [above](#q-reimport)).
|
||||
Then some component injects `UserService`, Angular finds it in the app root injector,
|
||||
and delivers the app-wide singleton `UserService`. No problem.
|
||||
and delivers the app-wide singleton `UserService`. No problem.
|
||||
|
||||
Now consider the `HeroModule` _which is lazy loaded!_
|
||||
|
||||
When the router lazy loads the `HeroModule`, it creates a child injector and registers the `UserService`
|
||||
provider with that child injector. The child injector is _not_ the root injector.
|
||||
|
||||
|
||||
When Angular creates a lazy `HeroComponent`, it must inject a `UserService`.
|
||||
This time it finds a `UserService` provider in the lazy module's _child injector_
|
||||
and creates a _new_ instance of the `UserService`.
|
||||
|
@ -527,27 +527,27 @@ a#q-why-child-injector
|
|||
.l-main-section
|
||||
:marked
|
||||
### Why does lazy loading create a child injector?
|
||||
|
||||
|
||||
Angular adds `@NgModule.providers` to the application root injector ... unless the module is lazy loaded.
|
||||
Then it creates a _child injector_ and adds the module's providers to the child injector.
|
||||
|
||||
This means that a module behaves differently depending on whether it is loaded during application start
|
||||
or lazy loaded later. Neglecting that difference can lead to [adverse consequences](#q-why-bad).
|
||||
|
||||
Why doesn't Angular add lazy loaded providers to the app root injector as it does for eagerly loaded modules?
|
||||
Why doesn't Angular add lazy loaded providers to the app root injector as it does for eagerly loaded modules?
|
||||
Why the inconsistency?
|
||||
|
||||
|
||||
The answer is grounded in a fundamental characteristic of the Angular dependency injection system.
|
||||
An injector can add providers _until it is first used_.
|
||||
An injector can add providers _until it is first used_.
|
||||
Once an injector starts creating and delivering services, its provider list is frozen. No new providers allowed.
|
||||
|
||||
When an applications starts, Angular first configures the root injector with the providers of all eagerly loaded modules
|
||||
_before_ creating its first component and injecting any of the provided services.
|
||||
_before_ creating its first component and injecting any of the provided services.
|
||||
Once the application begins, the app root injector is closed to new providers.
|
||||
|
||||
Time passes. Application logic triggers lazy loading of a module.
|
||||
Angular must add the lazy loaded module's providers to an injector _somewhere_.
|
||||
It can't added them to the app root injector because that injector is closed to new providers.
|
||||
Angular must add the lazy loaded module's providers to an injector _somewhere_.
|
||||
It can't added them to the app root injector because that injector is closed to new providers.
|
||||
So Angular creates a new child injector for the lazy loaded module context.
|
||||
|
||||
.l-hr
|
||||
|
@ -558,14 +558,14 @@ a#q-is-it-loaded
|
|||
### How can I tell if a module or service was previously loaded?
|
||||
|
||||
Some modules and its services should only be loaded once by the root `AppModule`.
|
||||
Importing the module a second time by lazy loading a module could [produce errant behavior](#q-why-bad)
|
||||
Importing the module a second time by lazy loading a module could [produce errant behavior](#q-why-bad)
|
||||
that may be difficult to detect and diagnose.
|
||||
|
||||
We can guard against that danger by writing a constructor that attempts to inject the module or service
|
||||
from the root app injector. If the injection succeeds, the class has been loaded a second time.
|
||||
We can throw an error or take other remedial action.
|
||||
|
||||
Certain Angular modules (such as `BrowserModule`) implements such a guard
|
||||
Certain Angular modules (such as `BrowserModule`) implements such a guard
|
||||
as does this Angular Module chapter sample's `CoreModule` constructor.
|
||||
+makeExample('ngmodule/ts/app/core/core.module.ts', 'ctor', 'app/core/core.module.ts (Constructor)')(format='.')
|
||||
:marked
|
||||
|
@ -578,32 +578,32 @@ a#q-entry-component-defined
|
|||
### What is an _entry component_?
|
||||
|
||||
Any component that Angular loads _imperatively_ by type is an _entry component_,
|
||||
|
||||
|
||||
A component loaded _declaratively_ via its selector is _not_ an entry component.
|
||||
|
||||
Most application components are loaded declaratively.
|
||||
Angular uses the component's selector to locate the element in the template.
|
||||
Most application components are loaded declaratively.
|
||||
Angular uses the component's selector to locate the element in the template.
|
||||
It then creates the HTML representation of the component and inserts it into the DOM at the selected element.
|
||||
These are not entry components.
|
||||
|
||||
A few components are only loaded dynamically and are _never_ referenced in a component template.
|
||||
A few components are only loaded dynamically and are _never_ referenced in a component template.
|
||||
|
||||
The bootstrapped root `AppComponent` is an _entry component_.
|
||||
True, its selector matches an element tag in `index.html`.
|
||||
But `index.html` is not a component template and the `AppComponent`
|
||||
But `index.html` is not a component template and the `AppComponent`
|
||||
selector doesn't match an element in any component template.
|
||||
|
||||
Angular loads `AppComponent` dynamically either because we listed it _by type_ in `@NgModule.bootstrap`
|
||||
|
||||
Angular loads `AppComponent` dynamically either because we listed it _by type_ in `@NgModule.bootstrap`
|
||||
or because we boostrapped it imperatively with the module's `ngDoBootstrap` method.
|
||||
|
||||
Components in route definitions are also _entry components_.
|
||||
A route definition refers to a component by its _type_.
|
||||
The router ignores a routed component's selector (if it even has one) and
|
||||
loads the component dynamically into a `RouterOutlet`.
|
||||
A route definition refers to a component by its _type_.
|
||||
The router ignores a routed component's selector (if it even has one) and
|
||||
loads the component dynamically into a `RouterOutlet`.
|
||||
|
||||
The compiler can't discover these _entry components_ by looking for them in other component templates.
|
||||
The compiler can't discover these _entry components_ by looking for them in other component templates.
|
||||
We must tell it about them ... by adding them to the `entryComponents` list.
|
||||
|
||||
|
||||
Angular automatically adds two kinds of components to the module's `entryComponents`:
|
||||
1. the component in the `@NgModule.bootstrap` list
|
||||
1. components referenced in router configuration
|
||||
|
@ -624,7 +624,7 @@ a#q-bootstrap_vs_entry_component
|
|||
The `@NgModule.bootstrap` property tells the compiler _both_ that this is an entry component _and_
|
||||
that it should generate code to bootstrap the application with this component.
|
||||
|
||||
There is no need to list a component in both the `bootstrap` and `entryComponent` lists
|
||||
There is no need to list a component in both the `bootstrap` and `entryComponent` lists
|
||||
although it is harmless to do so.
|
||||
|
||||
.l-hr
|
||||
|
@ -633,20 +633,20 @@ a#q-when-entry-components
|
|||
.l-main-section
|
||||
:marked
|
||||
### When do I add components to _entryComponents_?
|
||||
|
||||
|
||||
Most application developers won't need to add components to the `entryComponents`.
|
||||
|
||||
Angular adds certain components to _entry components_ automatically.
|
||||
Components listed in `@NgModule.bootstrap` are added automatically.
|
||||
Components referenced in router configuration are added automatically.
|
||||
These two mechanisms account for almost all entry components.
|
||||
|
||||
If your app happens to bootstrap or dynamically load a component _by type_ in some other manner,
|
||||
|
||||
If your app happens to bootstrap or dynamically load a component _by type_ in some other manner,
|
||||
you'll have to add it to `entryComponents` explicitly.
|
||||
|
||||
Although it's harmless to add components to this list,
|
||||
it's best to add only the components that are truly _entry components_.
|
||||
Don't include components that [are referenced](#q-template-reference)
|
||||
Don't include components that [are referenced](#q-template-reference)
|
||||
in the templates of other components.
|
||||
|
||||
.l-hr
|
||||
|
@ -658,28 +658,28 @@ a#q-why-entry-components
|
|||
_Entry components_ are also declared.
|
||||
Why doesn't the Angular compiler generate code for every component in `@NgModule.declarations`?
|
||||
Then we wouldn't need entry components.
|
||||
|
||||
|
||||
The reason is _tree shaking_. For production apps we want to load the smallest, fastest code possible.
|
||||
The code should contain only the classes that we actually need.
|
||||
It should exclude a component that's never used, whether or not that component is declared.
|
||||
|
||||
In fact, many libraries declare and export components we'll never use.
|
||||
The _tree shaker_ will drop these components from the final code package
|
||||
if we don't reference them.
|
||||
if we don't reference them.
|
||||
|
||||
If the [Angular compiler](#q-angular-compiler) generated code for every declared component,
|
||||
If the [Angular compiler](#q-angular-compiler) generated code for every declared component,
|
||||
it would defeat the purpose of the tree shaker.
|
||||
|
||||
|
||||
Instead, the compiler adopts a recursive strategy that generates code only for the components we use.
|
||||
|
||||
It starts with the entry components,
|
||||
|
||||
It starts with the entry components,
|
||||
then it generates code for the declared components it [finds](#q-template-reference) in an entry component's template,
|
||||
then for the declared components it discovers in the templates of previously compiled components,
|
||||
and so on. At the end of the process, it has generated code for every entry component
|
||||
and every component reachable from an entry component.
|
||||
|
||||
If a component isn't an _entry component_ or wasn't found in a template,
|
||||
the compiler omits it.
|
||||
If a component isn't an _entry component_ or wasn't found in a template,
|
||||
the compiler omits it.
|
||||
|
||||
|
||||
.l-hr
|
||||
|
@ -701,21 +701,21 @@ a#q-module-recommendations
|
|||
#### _SharedModule_
|
||||
Create a `SharedModule` with the components, directives, and pipes that you use
|
||||
everywhere in your app. This module should consist entirely of `declarations`
|
||||
most of them exported.
|
||||
|
||||
most of them exported.
|
||||
|
||||
It may re-export other [widget modules](#widget-feature-module) such as `CommonModule`,
|
||||
`FormsModule` and modules with the UI controls that you use most widely.
|
||||
|
||||
|
||||
It should ***not*** have `providers` for reasons [explained earlier](#q-why-bad).
|
||||
Nor should any of its imported or re-exported modules have `providers`.
|
||||
Know what you're doing and why if you deviate from this guideline.
|
||||
|
||||
Import the `SharedModule` in your _feature_ modules,
|
||||
Import the `SharedModule` in your _feature_ modules,
|
||||
both those loaded when the app starts and those you lazy load later.
|
||||
|
||||
#### _CoreModule_
|
||||
Create a `CoreModule` with `providers` for the singleton services you load when the application starts.
|
||||
|
||||
|
||||
Import `CoreModule` in the root `AppModule` only.
|
||||
Never import `CoreModule` in any module other than the root `AppModule`.
|
||||
|
||||
|
@ -724,16 +724,17 @@ a#q-module-recommendations
|
|||
.l-sub-section
|
||||
:marked
|
||||
This chapter sample departs from that advice by declaring and exporting two components that are
|
||||
only used within the root `AppComponent` declared by `AppModule`.
|
||||
only used within the root `AppComponent` declared by `AppModule`.
|
||||
Someone following this guideline strictly would have declared these components in the `AppModule` instead.
|
||||
|
||||
:marked
|
||||
#### Feature Modules
|
||||
Create _Feature Modules_ around specific application business domains, user workflows, and utility collections.
|
||||
|
||||
|
||||
Feature modules tend to fall into one of these four groups:
|
||||
* [Domain Feature Modules](#domain-feature-module)
|
||||
* [Routed Feature Modules](#routed-feature-module)
|
||||
* [Routing Modules](#routing-module)
|
||||
* [Service Feature Modules](#service-feature-module)
|
||||
* [Widget Feature Modules](#widget-feature-module)
|
||||
|
||||
|
@ -753,7 +754,7 @@ table
|
|||
:marked
|
||||
Domain Feature Modules deliver a user experience **dedicated to a particular application domain**
|
||||
like editing a customer or placing an order.
|
||||
|
||||
|
||||
They typically have a top component that acts as the feature root.
|
||||
Private, supporting sub-components descend from it.
|
||||
|
||||
|
@ -763,45 +764,81 @@ table
|
|||
Domain feature modules rarely have _providers_.
|
||||
When they do, the lifetime of the provided services
|
||||
should be the same as the lifetime of the module.
|
||||
|
||||
|
||||
Do not provide application-wide singleton services in a domain feature module.
|
||||
|
||||
Domain feature modules are typically imported _exactly once_ by a larger feature module.
|
||||
|
||||
|
||||
They might be imported by the root `AppModule` of a small application that lacks routing.
|
||||
|
||||
.l-sub-section
|
||||
:marked
|
||||
For an example, see [_ContactModule_](../guide/ngmodule.html#contact-module-v1)
|
||||
For an example, see [_ContactModule_](../guide/ngmodule.html#contact-module-v1)
|
||||
in the Angular Module chapter, before we introduced routing.
|
||||
tr
|
||||
td(style="vertical-align: top")<a id="routed-feature-module"></a>Routed
|
||||
td
|
||||
:marked
|
||||
_Routed Feature Modules_ are _Domain Feature modules_
|
||||
_Routed Feature Modules_ are _Domain Feature modules_
|
||||
whose top components are the **targets of router navigation routes**.
|
||||
|
||||
All lazy loaded modules are routed feature modules by definition.
|
||||
|
||||
This chapter's `ContactModule`, `HeroModule` and `CrisisModule` are routed feature modules.
|
||||
|
||||
Routed Feature Modules _should not export anything_.
|
||||
Routed Feature Modules _should not export anything_.
|
||||
They don't have to because none of their components ever appear in the template of an external component.
|
||||
|
||||
A lazy loaded Routed Feature Module should _not be imported_ by any module.
|
||||
A lazy loaded Routed Feature Module should _not be imported_ by any module.
|
||||
Doing so would trigger an eager load, defeating the purpose of lazy loading.
|
||||
`HeroModule` and `CrisisModule` are lazy loaded. They aren't mentioned among the `AppModule` imports.
|
||||
|
||||
But an eager loaded Routed Feature Module must be imported by another module
|
||||
so that the compiler learns about its components.
|
||||
so that the compiler learns about its components.
|
||||
`ContactModule` is eager loaded and, therefore, is listed among the `AppModule` imports.
|
||||
|
||||
Routed Feature Modules rarely have _providers_ for reasons [explained earlier](#q-why-bad).
|
||||
When they do, the lifetime of the provided services
|
||||
should be the same as the lifetime of the module.
|
||||
|
||||
|
||||
Do not provide application-wide singleton services in a routed feature module
|
||||
or in a module that the routed module imports.
|
||||
tr
|
||||
td(style="vertical-align: top")<a id="routing-module"></a>Routing
|
||||
td
|
||||
:marked
|
||||
A [_Routing Module_](../guide/router.html#routing-module) **provides routing configuration** for another module.
|
||||
|
||||
A Routing Module separates routing concerns from its companion module.
|
||||
|
||||
It typically:
|
||||
* defines routes
|
||||
* adds router configuration to the module's `imports`
|
||||
* re-exports `RouterModule`
|
||||
* adds guard and resolver service providers to the module's `providers`.
|
||||
|
||||
The name of the Routing Module should parallel the name of its companion module, using the suffix "Routing".
|
||||
For example, `FooModule` in `foo.module.ts` has a routing module named `FooRoutingModule`
|
||||
in `foo-routing.module.ts`
|
||||
|
||||
If the companion module is the _root_ `AppModule`,
|
||||
the `AppRoutingModule` adds router configuration to its `imports` with `RouterModule.forRoot(routes)`.
|
||||
All other Routing Modules are children that import `RouterModule.forChild(routes)`.
|
||||
|
||||
A Routing Module re-exports the `RouterModule` as a convenience
|
||||
so that components of the companion module have access to
|
||||
router directives such as `RouterLink` and `RouterOutlet`.
|
||||
|
||||
A Routing Module **should not have its own `declarations`!**
|
||||
Components, directives, and pipes are the **responsibility of the feature module**
|
||||
not the _routing_ module.
|
||||
|
||||
A Routing Module should _only_ be imported by its companion module.
|
||||
|
||||
The `AppRoutingModule`, `ContactRoutingModule` and `HeroRoutingModule` are good examples.
|
||||
.l-sub-section
|
||||
:marked
|
||||
See also "[Do you need a _Routing Module_?](../guide/router.html#why-routing-module)".
|
||||
|
||||
tr
|
||||
td(style="vertical-align: top")<a id="service-feature-module"></a>Service
|
||||
|
@ -813,7 +850,7 @@ table
|
|||
The `CoreModule` and Angular's `HttpModule` are good examples.
|
||||
|
||||
Service Modules should _only_ be imported by the root `AppModule`.
|
||||
|
||||
|
||||
Do **not** import them in other feature modules.
|
||||
Know what you're doing and why if you deviate from this guideline.
|
||||
tr
|
||||
|
@ -821,13 +858,13 @@ table
|
|||
td
|
||||
:marked
|
||||
A _Widget Module_ makes **components, directives, and pipes** available to external modules.
|
||||
|
||||
|
||||
`CommonModule` and `SharedModule` are widget modules.
|
||||
Many third party UI component libraries are widget modules.
|
||||
|
||||
A Widget Module should consist entirely of _declarations_, most of them exported.
|
||||
A Widget Module should consist entirely of _declarations_, most of them exported.
|
||||
|
||||
A Widget Module should rarely have _providers_.
|
||||
A Widget Module should rarely have _providers_.
|
||||
Know what you're doing and why if you deviate from this guideline.
|
||||
|
||||
Import Widget Modules in any module whose component templates need the widgets.
|
||||
|
@ -840,8 +877,8 @@ table
|
|||
table
|
||||
tr
|
||||
th Feature Module
|
||||
th Declarations
|
||||
th Providers
|
||||
th Declarations
|
||||
th Providers
|
||||
th Exports
|
||||
th Imported By
|
||||
th Examples
|
||||
|
@ -859,6 +896,13 @@ table
|
|||
td No
|
||||
td Nobody
|
||||
td <code>ContactModule</code>, <code>HeroModule</code>, <code>CrisisModule</code>
|
||||
tr
|
||||
td Routing
|
||||
td No
|
||||
td Yes (Guards)
|
||||
td <code>RouterModule</code>
|
||||
td Feature (for routing)
|
||||
td <code>AppRoutingModule</code>, <code>ContactRoutingModule</code>, <code>HeroRoutingModule</code>
|
||||
tr
|
||||
td Service
|
||||
td No
|
||||
|
@ -900,20 +944,20 @@ code-example(format='.').
|
|||
|
||||
An _Angular Module_ is a feature of _Angular_ itself.
|
||||
|
||||
Angular's `NgModule` also has `imports` and `exports` and they serve a similar purpose.
|
||||
Angular's `NgModule` also has `imports` and `exports` and they serve a similar purpose.
|
||||
|
||||
We _import_ other Angular modules so we can use their exported classes in component templates.
|
||||
We _export_ this Angular module's classes so they can be imported and used by components of _other_ modules.
|
||||
|
||||
|
||||
The Angular module classes differ from JavaScript module class in three key respects:
|
||||
|
||||
1. An Angular module bounds [_declarable classes_](#q-declarables) only.
|
||||
1. An Angular module bounds [_declarable classes_](#q-declarables) only.
|
||||
Declarables are the only classes that matter to the [Angular compiler](#q-angular-compiler).
|
||||
|
||||
1. Instead of defining all member classes in one giant file (as in a JavaScript module),
|
||||
we list the module's classes in the `@NgModule.declarations` list.
|
||||
|
||||
1. An Angular module can only export the [_declarable classes_](#q-declarables)
|
||||
1. An Angular module can only export the [_declarable classes_](#q-declarables)
|
||||
it owns or imports from other modules.
|
||||
It doesn't declare or export any other kind of class.
|
||||
|
||||
|
@ -940,11 +984,11 @@ a#q-template-reference
|
|||
h4.
|
||||
How does Angular find components, directives, and pipes in a template?<br>What is a <i><b>template reference</b></i>?
|
||||
:marked
|
||||
The [Angular compiler](#q-angular-compiler) looks inside component templates
|
||||
The [Angular compiler](#q-angular-compiler) looks inside component templates
|
||||
for other components, directives, and pipes. When it finds one, that's a "template reference".
|
||||
|
||||
The Angular compiler finds a component or directive in a template when it can match the **selector** of that
|
||||
component or directive to some HTML in that template.
|
||||
The Angular compiler finds a component or directive in a template when it can match the **selector** of that
|
||||
component or directive to some HTML in that template.
|
||||
|
||||
The compiler finds a pipe if the pipe's **name** appears within the pipe syntax of the template HTML.
|
||||
|
||||
|
@ -953,7 +997,7 @@ h4.
|
|||
|
||||
.l-hr
|
||||
|
||||
a#q-angular-compiler
|
||||
a#q-angular-compiler
|
||||
.l-main-section
|
||||
:marked
|
||||
### What is the Angular Compiler?
|
||||
|
@ -963,25 +1007,25 @@ a#q-angular-compiler
|
|||
|
||||
The code we write is not immediately executable.
|
||||
Consider **components**.
|
||||
Components have templates that contain custom elements, attribute directives, Angular binding declarations,
|
||||
Components have templates that contain custom elements, attribute directives, Angular binding declarations,
|
||||
and some peculiar syntax that clearly isn't native HTML.
|
||||
|
||||
The _Angular Compiler_ reads the template markup,
|
||||
|
||||
The _Angular Compiler_ reads the template markup,
|
||||
combines it with the corresponding component class code, and emits _component factories_.
|
||||
|
||||
|
||||
A component factory creates a pure, 100% JavaScript representation
|
||||
of the component that incorporates everything described in its `@Component` metadata:
|
||||
of the component that incorporates everything described in its `@Component` metadata:
|
||||
the HTML, the binding instructions, the attached styles ... everything.
|
||||
|
||||
Because **directives** and **pipes** appear in component templates,
|
||||
Because **directives** and **pipes** appear in component templates,
|
||||
the _Angular Compiler_ incorporates them into compiled component code too.
|
||||
|
||||
`@NgModule` metadata tells the _Angular Compiler_ what components to compile for this module and
|
||||
`@NgModule` metadata tells the _Angular Compiler_ what components to compile for this module and
|
||||
how to link this module with other modules.
|
||||
|
||||
.l-hr
|
||||
|
||||
a#q-ngmodule-api
|
||||
a#q-ngmodule-api
|
||||
.l-main-section
|
||||
:marked
|
||||
## *NgModule* API
|
||||
|
@ -1006,11 +1050,11 @@ table
|
|||
td(style="vertical-align: top") <code>declarations</code>
|
||||
td
|
||||
:marked
|
||||
A list of [declarable](#q-declarables) classes,
|
||||
A list of [declarable](#q-declarables) classes,
|
||||
the **component**, **directive** and **pipe** classes that _belong to this module_.
|
||||
|
||||
These declared classes are visible within the module but invisible to
|
||||
components in a different module unless (a) they are _exported_ from this module and
|
||||
components in a different module unless (a) they are _exported_ from this module and
|
||||
(b) that other module _imports_ this one.
|
||||
|
||||
Components, directives and pipes must belong to _exactly_ one module.
|
||||
|
@ -1023,40 +1067,40 @@ table
|
|||
td
|
||||
:marked
|
||||
A list of dependency injection providers.
|
||||
|
||||
|
||||
Angular registers these providers with the root injector of the module's execution context.
|
||||
That's the application's root injector for all modules loaded when the application starts.
|
||||
|
||||
Angular can inject one of these provider services into any component in the application.
|
||||
If this module provides the `HeroService`, or any module loaded at launch provides the `HeroService`,
|
||||
Angular can inject the same `HeroService` intance into any app component.
|
||||
|
||||
A lazy loaded module has its own sub-root injector which typically
|
||||
|
||||
A lazy loaded module has its own sub-root injector which typically
|
||||
is a direct child of the application root injector.
|
||||
|
||||
Lazy loaded services are scoped to the lazy module's injector.
|
||||
If a lazy loaded module also provides the `HeroService`,
|
||||
If a lazy loaded module also provides the `HeroService`,
|
||||
any component created within that module's context (e.g., by router navigation)
|
||||
gets the local instance of the service, not the instance in the root application injector.
|
||||
|
||||
Components in external modules continue to receive the instance created for the application root.
|
||||
Components in external modules continue to receive the instance created for the application root.
|
||||
|
||||
tr
|
||||
td(style="vertical-align: top") <code>imports</code>
|
||||
td
|
||||
:marked
|
||||
A list of supporting modules.
|
||||
|
||||
Specifically, the list of modules whose exported components, directives or pipes
|
||||
|
||||
Specifically, the list of modules whose exported components, directives or pipes
|
||||
are referenced by the component templates declared in this module.
|
||||
|
||||
|
||||
A component template can [reference](#q-template-reference) another component, directive or pipe
|
||||
on two conditions: either the referenced class is declared in this module
|
||||
or the class was imported from another module.
|
||||
or the class was imported from another module.
|
||||
|
||||
A component can use the `NgIf` and `NgFor` directives only because its parent module
|
||||
A component can use the `NgIf` and `NgFor` directives only because its parent module
|
||||
imported the Angular `CommonModule` (perhaps indirectly by importing `BrowserModule`).
|
||||
|
||||
|
||||
We can import many standard directives with the `CommonModule`.
|
||||
But some familiar directives belong to other modules.
|
||||
A component template can bind with `[(ngModel)]` only after importing the Angular `FormsModule`.
|
||||
|
@ -1064,13 +1108,13 @@ table
|
|||
td(style="vertical-align: top") <code>exports</code>
|
||||
td
|
||||
:marked
|
||||
A list of declarations — **component**, **directive**, and **pipe** classes — that
|
||||
A list of declarations — **component**, **directive**, and **pipe** classes — that
|
||||
an importing module can use.
|
||||
|
||||
Exported declarations are the module's _public API_.
|
||||
A component in another module can [reference](#q-template-reference) _this_ module's `HeroComponent`
|
||||
Exported declarations are the module's _public API_.
|
||||
A component in another module can [reference](#q-template-reference) _this_ module's `HeroComponent`
|
||||
if (a) it imports this module and (b) this module exports `HeroComponent`.
|
||||
|
||||
|
||||
Declarations are private by default.
|
||||
If this module does _not_ export `HeroComponent`, no other module can see it.
|
||||
|
||||
|
@ -1092,11 +1136,11 @@ table
|
|||
A list of components that can be bootstrapped.
|
||||
|
||||
Usually there is only one component in this list, the _root component_ of the application.
|
||||
|
||||
Angular can launch with multiple bootstrap components,
|
||||
|
||||
Angular can launch with multiple bootstrap components,
|
||||
each with its own location in the host web page.
|
||||
|
||||
A bootstrap component is automatically an `entryComponent`
|
||||
A bootstrap component is automatically an `entryComponent`
|
||||
|
||||
tr
|
||||
td(style="vertical-align: top") <code>entryComponents</code>
|
||||
|
@ -1107,7 +1151,7 @@ table
|
|||
Most developers will never set this property. Here's why.
|
||||
|
||||
The [_Angular Compiler_](#q-angular-compiler) must know about every component actually used in the application.
|
||||
The compiler can discover most components by walking the tree of references
|
||||
The compiler can discover most components by walking the tree of references
|
||||
from one component template to another.
|
||||
|
||||
But there's always at least one component that is not referenced in any template:
|
||||
|
@ -1117,7 +1161,7 @@ table
|
|||
Routed components are also _entry components_ because they aren't referenced in a template either.
|
||||
The router creates them and drops them into the DOM near a `<router-outlet>`.
|
||||
|
||||
While the bootstrapped and routed components are _entry components_,
|
||||
While the bootstrapped and routed components are _entry components_,
|
||||
we usally don't have to add them to a module's `entryComponents` list.
|
||||
|
||||
Angular automatically adds components in the module's `bootstrap` list to the `entryComponents` list.
|
||||
|
@ -1126,7 +1170,7 @@ table
|
|||
That leaves only two sources of undiscoverable components.
|
||||
1. Components bootstrapped using one of the imperative techniques.
|
||||
1. Components dynamically loaded into the DOM by some means other than the router.
|
||||
|
||||
Both are advanced techniques that few developers will ever employ.
|
||||
If you are one of those few, you'll have to add these components to the
|
||||
|
||||
Both are advanced techniques that few developers will ever employ.
|
||||
If you are one of those few, you'll have to add these components to the
|
||||
`entryComponents` list yourself, either programmatically or by hand.
|
||||
|
|
|
@ -8,14 +8,14 @@ block includes
|
|||
**Angular Modules** help organize an application into cohesive blocks of functionality.
|
||||
|
||||
An Angular Module is a _class_ adorned with the **@NgModule** decorator function.
|
||||
`@NgModule` takes a metadata object that tells Angular how to compile and run module code.
|
||||
It identifies the module's _own_ components, directives and pipes,
|
||||
making some of them public so external components can use them.
|
||||
It may add service providers to the application dependency injectors.
|
||||
And there are more options covered here.
|
||||
`@NgModule` takes a metadata object that tells Angular how to compile and run module code.
|
||||
It identifies the module's _own_ components, directives and pipes,
|
||||
making some of them public so external components can use them.
|
||||
It may add service providers to the application dependency injectors.
|
||||
And there are more options covered here.
|
||||
|
||||
This page explains how to **create** `NgModule` classes and how to load them,
|
||||
either immediately when the application launches or later, as needed, via the [Router](router.html).
|
||||
This page explains how to **create** `NgModule` classes and how to load them,
|
||||
either immediately when the application launches or later, as needed, via the [Router](router.html).
|
||||
|
||||
## Table of Contents
|
||||
* [Angular modularity](#angular-modularity "Add structure to the app with NgModule")
|
||||
|
@ -27,8 +27,8 @@ block includes
|
|||
* [Resolve conflicts](#resolve-conflicts "When two directives have the same selector ...")
|
||||
* [Feature modules](#feature-modules "Partition the app into feature modules")
|
||||
* [Lazy loaded modules](#lazy-load "Load modules asynchronously") with the Router
|
||||
* [Shared modules](#shared-module "Create modules for commonly used components, directives, and pipes")
|
||||
* [The Core module](#core-module "Create a core module with app-wide singleton services and single-use components")
|
||||
* [Shared modules](#shared-module "Create modules for commonly used components, directives, and pipes")
|
||||
* [The Core module](#core-module "Create a core module with app-wide singleton services and single-use components")
|
||||
* [Configure core services with _forRoot_](#core-for-root "Configure providers during module import")
|
||||
* [Prevent reimport of the _CoreModule_](#prevent-reimport "because bad things happen if a lazy loaded module imports Core")
|
||||
* [NgModule metadata properties](#ngmodule-properties "A technical summary of the @NgModule metadata properties")
|
||||
|
@ -40,7 +40,7 @@ block includes
|
|||
* <live-example plnkr="minimal.0">A minimal NgModule app</live-example>
|
||||
* <live-example plnkr="contact.1b">The first contact module</live-example>
|
||||
* <live-example plnkr="contact.2">The revised contact module</live-example>
|
||||
* <live-example plnkr="pre-shared.3">Just before adding _SharedModule_</live-example>
|
||||
* <live-example plnkr="pre-shared.3">Just before adding _SharedModule_</live-example>
|
||||
* <live-example>The final version</live-example>
|
||||
|
||||
### Frequently Asked Questions (FAQs)
|
||||
|
@ -53,30 +53,30 @@ block includes
|
|||
|
||||
.l-hr
|
||||
|
||||
a#angular-modularity
|
||||
a#angular-modularity
|
||||
.l-main-section
|
||||
:marked
|
||||
## Angular Modularity
|
||||
|
||||
|
||||
Modules are a great way to organize the application and extend it with capabilities from external libraries.
|
||||
|
||||
Many Angular libraries are modules (e.g, `FormsModule`, `HttpModule`, `RouterModule`).
|
||||
Many third party libraries are available as Angular modules (e.g.,
|
||||
|
||||
Many Angular libraries are modules (e.g, `FormsModule`, `HttpModule`, `RouterModule`).
|
||||
Many third party libraries are available as Angular modules (e.g.,
|
||||
<a href="https://material.angular.io/" target="_blank">Material Design</a>,
|
||||
<a href="http://ionicframework.com/" target="_blank">Ionic</a>,
|
||||
<a href="https://github.com/angular/angularfire2" target="_blank">AngularFire2</a>).
|
||||
|
||||
Angular modules consolidate components, directives and pipes into
|
||||
cohesive blocks of functionality, each focused on a
|
||||
cohesive blocks of functionality, each focused on a
|
||||
feature area, application business domain, workflow, or common collection of utilities.
|
||||
|
||||
|
||||
Modules can also add services to the application.
|
||||
Such services might be internally-developed such as the application logger.
|
||||
They can come from outside sources such as the Angular router and Http client.
|
||||
|
||||
Modules can be loaded eagerly when the application starts.
|
||||
They can also be _lazy loaded_ asynchronously by the router.
|
||||
|
||||
|
||||
An Angular module is a class decorated with `@NgModule` metadata. The metadata:
|
||||
|
||||
* declare which components, directives and pipes _belong_ to the module.
|
||||
|
@ -84,43 +84,43 @@ a#angular-modularity
|
|||
* import other modules with the components, directives and pipes needed by the components in _this_ module.
|
||||
* provide services at the application level that any application component can use.
|
||||
|
||||
Every Angular app has at least one module class, the _root module_.
|
||||
Every Angular app has at least one module class, the _root module_.
|
||||
We bootstrap that module to launch the application.
|
||||
|
||||
The _root module_ is all we need in a simple application with a few components.
|
||||
As the app grows, we refactor the _root module_ into **feature modules**
|
||||
that represent collections of related functionality.
|
||||
As the app grows, we refactor the _root module_ into **feature modules**
|
||||
that represent collections of related functionality.
|
||||
We then import these modules into the _root module_.
|
||||
|
||||
We'll see how later in the page. Let's start with the _root module_.
|
||||
|
||||
a#root-module
|
||||
a#root-module
|
||||
.l-main-section
|
||||
:marked
|
||||
## _AppModule_ - the application root module
|
||||
|
||||
Every Angular app has a **root module** class.
|
||||
|
||||
Every Angular app has a **root module** class.
|
||||
By convention it's a class called `AppModule` in a file named `app.module.ts`.
|
||||
|
||||
This `AppModule` is about as minimal as it gets:
|
||||
+makeExample('ngmodule/ts/app/app.module.0.ts', '', 'app/app.module.ts (minimal)')(format=".")
|
||||
:marked
|
||||
The `@NgModule` decorator defines the metadata for the module.
|
||||
The `@NgModule` decorator defines the metadata for the module.
|
||||
We'll take an intuitive approach to understanding the metadata and fill in details as we go.
|
||||
|
||||
This metadata imports a single helper module, `BrowserModule`, the module every browser app must import.
|
||||
|
||||
|
||||
`BrowserModule` registers critical application service providers.
|
||||
It also includes common directives like `NgIf` and `NgFor` which become immediately visible and usable
|
||||
in any of this modules component templates.
|
||||
|
||||
The `declarations` list identifies the application's only component,
|
||||
in any of this modules component templates.
|
||||
|
||||
The `declarations` list identifies the application's only component,
|
||||
the _root component_, the top of this app's rather bare component tree.
|
||||
|
||||
The example `AppComponent` simply displays a data-bound title:
|
||||
+makeExample('ngmodule/ts/app/app.component.0.ts', '', 'app/app.component.ts (minimal)')(format=".")
|
||||
:marked
|
||||
Lastly, the `@NgModule.bootstrap` property identifies this `AppComponent` as the _bootstrap component_.
|
||||
Lastly, the `@NgModule.bootstrap` property identifies this `AppComponent` as the _bootstrap component_.
|
||||
When Angular launches the app, it places the HTML rendering of `AppComponent` in the DOM,
|
||||
inside the `<my-app>` element tags of the `index.html`
|
||||
|
||||
|
@ -129,20 +129,20 @@ a#bootstrap
|
|||
:marked
|
||||
## Bootstrapping in _main.ts_
|
||||
We launch the application by bootstrapping the `AppModule` in the `main.ts` file.
|
||||
|
||||
Angular offers a variety of bootstrapping options, targeting multiple platforms.
|
||||
|
||||
Angular offers a variety of bootstrapping options, targeting multiple platforms.
|
||||
In this page we consider two options, both targeting the browser.
|
||||
|
||||
### Dynamic bootstrapping with the Just-in-time (JiT) compiler
|
||||
In the first, _dynamic_ option, the [Angular compiler](../cookbook/ngmodule-faq.html#q-angular-compiler "About the Angular Compiler")
|
||||
In the first, _dynamic_ option, the [Angular compiler](../cookbook/ngmodule-faq.html#q-angular-compiler "About the Angular Compiler")
|
||||
compiles the application in the browser and then launches the app.
|
||||
|
||||
+makeExample('ngmodule/ts/app/main.ts', '', 'app/main.ts (dynamic)')(format=".")
|
||||
:marked
|
||||
The samples in this page demonstrate the dynamic bootstrapping approach.
|
||||
The samples in this page demonstrate the dynamic bootstrapping approach.
|
||||
|
||||
<live-example embedded plnkr="minimal.0" img="devguide/ngmodule/minimal-plunker.png">Try the live example.</live-example>
|
||||
|
||||
|
||||
|
||||
### Static bootstrapping with the Ahead-Of-time (AoT) compiler
|
||||
|
||||
|
@ -150,17 +150,17 @@ a#bootstrap
|
|||
launches faster, especially on mobile devices and high latency networks.
|
||||
|
||||
In the _static_ option, the Angular compiler runs ahead-of-time as part of the build process,
|
||||
producing a collection of class factories in their own files.
|
||||
producing a collection of class factories in their own files.
|
||||
Among them is the `AppModuleNgFactory`.
|
||||
|
||||
The syntax for bootstrapping the pre-compiled `AppModuleNgFactory` is similar to
|
||||
The syntax for bootstrapping the pre-compiled `AppModuleNgFactory` is similar to
|
||||
the dynamic version that bootstraps the `AppModule` class.
|
||||
|
||||
+makeExample('ngmodule/ts/app/main-static.ts', '', 'app/main.ts (static)')(format=".")
|
||||
:marked
|
||||
Because the entire application was pre-compiled,
|
||||
Because the entire application was pre-compiled,
|
||||
we don't ship the _Angular Compiler_ to the browser and we don't compile in the browser.
|
||||
|
||||
|
||||
The application code downloaded to the browser is much smaller than the dynamic equivalent
|
||||
and it is ready to execute immediately. The performance boost can be significant.
|
||||
|
||||
|
@ -181,7 +181,7 @@ a#declarations
|
|||
.l-main-section
|
||||
:marked
|
||||
## Declare directives and components
|
||||
The app evolves.
|
||||
The app evolves.
|
||||
The first addition is a `HighlightDirective`, an [attribute directive](attribute-directives.html)
|
||||
that sets the background color of the attached element.
|
||||
+makeExample('ngmodule/ts/app/highlight.directive.ts', '', 'app/highlight.directive.ts')(format=".")
|
||||
|
@ -189,7 +189,7 @@ a#declarations
|
|||
We update the `AppComponent` template to attach the directive to the title:
|
||||
+makeExample('ngmodule/ts/app/app.component.1.ts', 'template')(format=".")
|
||||
:marked
|
||||
If we ran the app now, Angular would not recognize the `highlight` attribute and would ignore it.
|
||||
If we ran the app now, Angular would not recognize the `highlight` attribute and would ignore it.
|
||||
We must declare the directive in `AppModule`.
|
||||
|
||||
Import the `HighlightDirective` class and add it to the module's `declarations` like this:
|
||||
|
@ -198,7 +198,7 @@ a#declarations
|
|||
:marked
|
||||
### Add a component
|
||||
|
||||
We decide to refactor the title into its own `TitleComponent`.
|
||||
We decide to refactor the title into its own `TitleComponent`.
|
||||
The component's template binds to the component's `title` and `subtitle` properties like this:
|
||||
+makeExample('ngmodule/ts/app/title.component.html', 'v1', 'app/title.component.html')(format=".")
|
||||
|
||||
|
@ -209,7 +209,7 @@ a#declarations
|
|||
using an input binding to set the `subtitle`.
|
||||
+makeExample('ngmodule/ts/app/app.component.1.ts', '', 'app/app.component.ts (v1)')(format=".")
|
||||
:marked
|
||||
Angular won't recognize the `<app-title>` tag until we declare it in `AppModule`.
|
||||
Angular won't recognize the `<app-title>` tag until we declare it in `AppModule`.
|
||||
Import the `TitleComponent` class and add it to the module's `declarations`:
|
||||
+makeExample('ngmodule/ts/app/app.module.1.ts', 'component')(format=".")
|
||||
|
||||
|
@ -228,8 +228,8 @@ a#providers
|
|||
A module can add providers to the application's root dependency injector, making those services
|
||||
available everywhere in the application.
|
||||
|
||||
Many applications capture information about the currently logged-in user and make that information
|
||||
accessible through a user service.
|
||||
Many applications capture information about the currently logged-in user and make that information
|
||||
accessible through a user service.
|
||||
This sample application has a dummy implementation of such a `UserService`.
|
||||
|
||||
+makeExample('ngmodule/ts/app/user.service.ts', '', 'app/user.service.ts')(format=".")
|
||||
|
@ -252,49 +252,49 @@ a#imports
|
|||
## Import supporting modules
|
||||
|
||||
The app shouldn't welcome a user if there is no user.
|
||||
|
||||
|
||||
Notice in the revised `TitleComponent` that an `*ngIf` directive guards the message.
|
||||
There is no message if there is no user.
|
||||
+makeExample('ngmodule/ts/app/title.component.html', 'ngIf', 'app/title.component.html (ngIf)')(format=".")
|
||||
:marked
|
||||
Although `AppModule` doesn't declare `NgIf`, the application still compiles and runs.
|
||||
How can that be? The Angular compiler should either ignore or complain about unrecognized HTML.
|
||||
|
||||
Angular _does_ recognize `NgIf` because we imported it earlier.
|
||||
|
||||
Angular _does_ recognize `NgIf` because we imported it earlier.
|
||||
The initial version of `AppModule` imports `BrowserModule`.
|
||||
+makeExample('ngmodule/ts/app/app.module.0.ts', 'imports', 'app/app.module.ts (imports)')(format=".")
|
||||
:marked
|
||||
Importing `BrowserModule` made all of its public components, directives and pipes visible
|
||||
Importing `BrowserModule` made all of its public components, directives and pipes visible
|
||||
to the component templates in `AppModule`. They are ready to use without further ado.
|
||||
.l-sub-section
|
||||
:marked
|
||||
More accurately, `NgIf` is declared in `CommonModule` from `@angular/common`.
|
||||
|
||||
`CommonModule` contributes many of the common directives that applications need including `ngIf` and `ngFor`.
|
||||
|
||||
|
||||
`BrowserModule` imports `CommonModule` and [_re-exports_](../cookbook/ngmodule-faq.html#q-re-export) it.
|
||||
The net effect is that an importer of `BrowserModule` gets `CommonModule` directives automatically.
|
||||
:marked
|
||||
Many familiar Angular directives do not belong to`CommonModule`.
|
||||
Many familiar Angular directives do not belong to`CommonModule`.
|
||||
For example, `NgModel` and `RouterLink` belong to Angular's `FormsModule` and `RouterModule` respectively.
|
||||
We must _import_ those modules before we can use their directives.
|
||||
|
||||
To illustrate this point, we extend the sample app with `ContactComponent`,
|
||||
To illustrate this point, we extend the sample app with `ContactComponent`,
|
||||
a form component that imports form support from the Angular `FormsModule`.
|
||||
|
||||
### Add the _ContactComponent_
|
||||
|
||||
[Angular Forms](forms.html) are a great way to manage user data entry.
|
||||
|
||||
The `ContactComponent` presents a "contact editor",
|
||||
The `ContactComponent` presents a "contact editor",
|
||||
implemented with _Angular Forms_ in the [_template-driven form_](forms.html) style.
|
||||
|
||||
.l-sub-section
|
||||
:marked
|
||||
#### Angular Form Styles
|
||||
|
||||
### Angular Form Styles
|
||||
|
||||
We write Angular form components in either the
|
||||
[_template-driven form_](forms.html) style or
|
||||
[_template-driven form_](forms.html) style or
|
||||
the [_reactive form_](../cookbook/dynamic-form.html) style.
|
||||
|
||||
This sample is about to import the `FormsModule` from `@angular/forms` because
|
||||
|
@ -303,13 +303,13 @@ a#imports
|
|||
should import the `ReactiveFormsModule` instead.
|
||||
|
||||
:marked
|
||||
The `ContactComponent` selector matches an element named `<app-contact>`.
|
||||
The `ContactComponent` selector matches an element named `<app-contact>`.
|
||||
Add an element with that name to the `AppComponent` template just below the `<app-title>`:
|
||||
+makeExample('ngmodule/ts/app/app.component.1b.ts', 'template', 'app/app.component.ts (template)')(format=".")
|
||||
|
||||
:marked
|
||||
The `ContactComponent` has a lot going on.
|
||||
Form components are often complex anyway and this one has its own `ContactService`,
|
||||
The `ContactComponent` has a lot going on.
|
||||
Form components are often complex anyway and this one has its own `ContactService`,
|
||||
its own [custom pipe](#pipes.html#custom-pipes) called `Awesome`,
|
||||
and an alternative version of the `HighlightDirective`.
|
||||
|
||||
|
@ -322,7 +322,7 @@ a#imports
|
|||
ngmodule/ts/app/contact/contact.service.ts,
|
||||
ngmodule/ts/app/contact/awesome.pipe.ts,
|
||||
ngmodule/ts/app/contact/highlight.directive.ts
|
||||
`,
|
||||
`,
|
||||
null,
|
||||
`app/contact/contact.component.html,
|
||||
app/contact/contact.component.ts,
|
||||
|
@ -348,12 +348,12 @@ a#imports
|
|||
Add the `FormsModule` to the `AppModule` metadata's `imports` list.
|
||||
+makeExample('ngmodule/ts/app/app.module.1.ts', 'imports')(format=".")
|
||||
:marked
|
||||
Now `[(ngModel)]` binding will work and the user input will be validated by Angular Forms,
|
||||
Now `[(ngModel)]` binding will work and the user input will be validated by Angular Forms,
|
||||
once we declare our new component, pipe and directive.
|
||||
|
||||
.alert.is-critical
|
||||
:marked
|
||||
**Do not** add `NgModel` — or the `FORMS_DIRECTIVES` —
|
||||
**Do not** add `NgModel` — or the `FORMS_DIRECTIVES` —
|
||||
to the `AppModule` metadata's declarations!
|
||||
|
||||
These directives belong to the `FormsModule`.
|
||||
|
@ -377,17 +377,17 @@ a#import-name-conflict
|
|||
We work around it by creating an alias for the second, contact version using the `as` JavaScript import keyword:
|
||||
+makeExample('ngmodule/ts/app/app.module.1b.ts', 'import-alias')(format=".")
|
||||
:marked
|
||||
This solves the immediate problem of referencing both directive _types_ in the same file but
|
||||
This solves the immediate problem of referencing both directive _types_ in the same file but
|
||||
leaves another problem unresoved as we discuss [below](#resolve-conflicts).
|
||||
|
||||
:marked
|
||||
### Provide the _ContactService_
|
||||
The `ContactComponent` displays contacts retrieved by the `ContactService`
|
||||
which Angular injects into its constructor.
|
||||
|
||||
which Angular injects into its constructor.
|
||||
|
||||
We have to provide that service somewhere.
|
||||
The `ContactComponent` _could_ provide it.
|
||||
But then it would be scoped to this component _only_.
|
||||
The `ContactComponent` _could_ provide it.
|
||||
But then it would be scoped to this component _only_.
|
||||
We want to share this service with other contact-related components that we will surely add later.
|
||||
|
||||
In this app we chose to add `ContactService` to the `AppModule` metadata's `providers` list:
|
||||
|
@ -398,27 +398,27 @@ a#import-name-conflict
|
|||
a#application-scoped-providers
|
||||
.l-sub-section
|
||||
:marked
|
||||
#### Application-scoped Providers
|
||||
The `ContactService` provider is _application_-scoped because Angular
|
||||
### Application-scoped Providers
|
||||
The `ContactService` provider is _application_-scoped because Angular
|
||||
registers a module's `providers` with the application's **root injector**.
|
||||
|
||||
Architecturally, the `ContactService` belongs to the Contact business domain.
|
||||
Architecturally, the `ContactService` belongs to the Contact business domain.
|
||||
Classes in _other_ domains don't need the `ContactService` and shouldn't inject it.
|
||||
|
||||
|
||||
We might expect Angular to offer a _module_-scoping mechanism to enforce this design.
|
||||
It doesn't. Angular module instances, unlike components, do not have their own injectors
|
||||
so they can't have their own provider scopes.
|
||||
|
||||
This omission is intentional.
|
||||
Angular modules are designed primarily to extend an application,
|
||||
This omission is intentional.
|
||||
Angular modules are designed primarily to extend an application,
|
||||
to enrich the entire app with the module's capabilities.
|
||||
|
||||
|
||||
Service scoping is rarely a problem in practice.
|
||||
Non-contact components can't inject the `ContactService` by accident.
|
||||
To inject `ContactService`, you must first import its _type_.
|
||||
Only Contact components should import the `ContactService` _type_.
|
||||
|
||||
See the [FAQ that pursues this issue](../cookbook/ngmodule-faq.html#q-component-scoped-providers)
|
||||
See the [FAQ that pursues this issue](../cookbook/ngmodule-faq.html#q-component-scoped-providers)
|
||||
and its mitigations in greater detail.
|
||||
|
||||
:marked
|
||||
|
@ -445,9 +445,9 @@ a#application-scoped-providers
|
|||
:marked
|
||||
Try the example:
|
||||
<live-example embedded plnkr="contact.1b" img="devguide/ngmodule/contact-1b-plunker.png"></live-example>
|
||||
|
||||
|
||||
a#resolve-conflicts
|
||||
.l-main-section
|
||||
.l-main-section
|
||||
:marked
|
||||
## Resolve directive conflicts
|
||||
|
||||
|
@ -465,10 +465,10 @@ a#resolve-conflicts
|
|||
app/contact/highlight.directive.ts`)
|
||||
|
||||
:marked
|
||||
Will Angular use only one of them? No.
|
||||
Will Angular use only one of them? No.
|
||||
Both directives are declared in this module so _both directives are active_.
|
||||
|
||||
When the two directives compete to color the same element,
|
||||
|
||||
When the two directives compete to color the same element,
|
||||
the directive declared later wins because its DOM changes overwrite the first.
|
||||
In this case, the contact's `HighlightDirective` colors the application title text blue
|
||||
when it should stay gold.
|
||||
|
@ -477,7 +477,7 @@ a#resolve-conflicts
|
|||
:marked
|
||||
The real problem is that there are _two different classes_ trying to do the same thing.
|
||||
|
||||
It's OK to import the _same_ directive class multiple times.
|
||||
It's OK to import the _same_ directive class multiple times.
|
||||
Angular removes duplicate classes and only registers one of them.
|
||||
|
||||
But these are actually two different classes, defined in different files, that happen to have the same name.
|
||||
|
@ -486,12 +486,12 @@ a#resolve-conflicts
|
|||
they take turns modifying the same HTML element.
|
||||
|
||||
:marked
|
||||
At least the app still compiles.
|
||||
If we define two different component classes with the same selector specifying the same element tag,
|
||||
At least the app still compiles.
|
||||
If we define two different component classes with the same selector specifying the same element tag,
|
||||
the compiler reports an error. It can't insert two components in the same DOM location.
|
||||
|
||||
What a mess!
|
||||
|
||||
What a mess!
|
||||
|
||||
We can eliminate component and directive conflicts by creating feature modules
|
||||
that insulate the declarations in one module from the declarations in another.
|
||||
|
||||
|
@ -504,7 +504,7 @@ a#feature-modules
|
|||
|
||||
* The root `AppModule` grows larger with each new application class and shows no signs of stopping.
|
||||
|
||||
* We have conflicting directives.
|
||||
* We have conflicting directives.
|
||||
The `HighlightDirective` in contact is re-coloring the work done by the `HighlightDirective` declared in `AppModule`.
|
||||
And it's coloring the application title text when it should only color the `ContactComponent`.
|
||||
|
||||
|
@ -516,7 +516,7 @@ a#feature-modules
|
|||
### _Feature Module_
|
||||
|
||||
A _feature module_ is a class adorned by the `@NgModule` decorator and its metadata,
|
||||
just like a root module.
|
||||
just like a root module.
|
||||
Feature module metadata have the same properties as the metadata for a root module.
|
||||
|
||||
The root module and the feature module share the same execution context.
|
||||
|
@ -533,16 +533,16 @@ a#feature-modules
|
|||
Otherwise, a feature module is distinguished primarily by its intent.
|
||||
|
||||
A feature module delivers a cohesive set of functionality
|
||||
focused on an application business domain, a user workflow, a facility (forms, http, routing),
|
||||
focused on an application business domain, a user workflow, a facility (forms, http, routing),
|
||||
or a collection of related utilities.
|
||||
|
||||
|
||||
While we can do everything within the root module,
|
||||
feature modules help us partition the app into areas of specific interest and purpose.
|
||||
|
||||
A feature module collaborates with the root module and with other modules
|
||||
through the services it provides and
|
||||
A feature module collaborates with the root module and with other modules
|
||||
through the services it provides and
|
||||
the components, directives, and pipes that it chooses to share.
|
||||
|
||||
|
||||
In the next section, we carve the contact functionality out of the root module
|
||||
and into a dedicated feature module.
|
||||
|
||||
|
@ -557,16 +557,16 @@ a#feature-modules
|
|||
1. Import the `ContactModule` into the `AppModule`.
|
||||
|
||||
`AppModule` is the only _existing_ class that changes. But we do add one new file.
|
||||
|
||||
|
||||
### Add the _ContactModule_
|
||||
|
||||
|
||||
Here's the new `ContactModule`
|
||||
+makeExample('ngmodule/ts/app/contact/contact.module.2.ts', '', 'app/contact/contact.module.ts')
|
||||
:marked
|
||||
We copy from `AppModule` the contact-related import statements and the `@NgModule` properties
|
||||
that concern the contact and paste them in `ContactModule`.
|
||||
|
||||
We _import_ the `FormsModule` because the contact component needs it.
|
||||
|
||||
We _import_ the `FormsModule` because the contact component needs it.
|
||||
.alert.is-important
|
||||
:marked
|
||||
Modules do not inherit access to the components, directives or pipes that are declared in other modules.
|
||||
|
@ -582,7 +582,7 @@ a#feature-modules
|
|||
other modules that import the `ContactModule` can include it in their component templates.
|
||||
|
||||
All other declared contact classes are private by default.
|
||||
The `AwesomePipe` and `HighlightDirective` are hidden from the rest of the application.
|
||||
The `AwesomePipe` and `HighlightDirective` are hidden from the rest of the application.
|
||||
The `HighlightDirective` can no longer color the `AppComponent` title text.
|
||||
|
||||
:marked
|
||||
|
@ -600,7 +600,7 @@ a#feature-modules
|
|||
+makeTabs(
|
||||
`ngmodule/ts/app/app.module.2.ts,
|
||||
ngmodule/ts/app/app.module.1b.ts`,
|
||||
'',
|
||||
'',
|
||||
`app/app.module.ts (v2),
|
||||
app/app.module.ts (v1)`)
|
||||
:marked
|
||||
|
@ -617,7 +617,7 @@ a#feature-modules
|
|||
* No `HighlightDirective` conflict
|
||||
|
||||
Try this `ContactModule` version of the sample.
|
||||
|
||||
|
||||
<live-example embedded plnkr="contact.2" img="devguide/ngmodule/contact-2-plunker.png">Try the live example.</live-example>
|
||||
|
||||
a#lazy-load
|
||||
|
@ -625,13 +625,13 @@ a#lazy-load
|
|||
:marked
|
||||
## Lazy loading modules with the Router
|
||||
|
||||
The Heroic Staffing Agency sample app has evolved.
|
||||
The Heroic Staffing Agency sample app has evolved.
|
||||
It has two more modules, one for managing the heroes-on-staff and another for matching crises to the heroes.
|
||||
Both modules are in the early stages of development.
|
||||
Both modules are in the early stages of development.
|
||||
Their specifics aren't important to the story and we won't discuss every line of code.
|
||||
.l-sub-section
|
||||
:marked
|
||||
Examine and download the complete source for this version from the
|
||||
Examine and download the complete source for this version from the
|
||||
<live-example plnkr="pre-shared.3" img="devguide/ngmodule/v3-plunker.png">live example.</live-example>
|
||||
:marked
|
||||
Some facets of the current application merit discussion.
|
||||
|
@ -656,71 +656,73 @@ a#lazy-load
|
|||
Some file names bear a `.3` extension indicating
|
||||
a difference with prior or future versions.
|
||||
We'll explain differences that matter in due course.
|
||||
|
||||
:marked
|
||||
The module still imports `ContactModule` so that its routes and components are mounted when the app starts.
|
||||
|
||||
The module does _not_ import `HeroModule` or `CrisisModule`.
|
||||
:marked
|
||||
The module still imports `ContactModule` so that its routes and components are mounted when the app starts.
|
||||
|
||||
The module does _not_ import `HeroModule` or `CrisisModule`.
|
||||
They'll be fetched and mounted asynchronously when the user navigates to one of their routes.
|
||||
|
||||
The significant change from version 2 is the addition of a ***routing*** object to the `imports`.
|
||||
The routing object, which provides a configured `Router` service, is defined in the `app.routing.ts` file.
|
||||
|
||||
The significant change from version 2 is the addition of the ***AppRoutingModule*** to the module `imports`.
|
||||
The `AppRoutingModule` is a [_Routing Module_](../guide/router.html#routing-module)
|
||||
that handles the app's routing concerns.
|
||||
|
||||
### App routing
|
||||
+makeExample('ngmodule/ts/app/app.routing.ts', '', 'app/app.routing.ts')(format='.')
|
||||
+makeExample('ngmodule/ts/app/app-routing.module.ts', '', 'app/app-routing.module.ts')(format='.')
|
||||
:marked
|
||||
The router is the subject of [its own page](router.html) so we'll skip lightly over the details and
|
||||
The router is the subject of [its own page](router.html) so we'll skip lightly over the details and
|
||||
concentrate on the intersection of Angular modules and routing.
|
||||
|
||||
This file defines three routes.
|
||||
|
||||
The first redirects the empty URL (e.g., `http://host.com/`)
|
||||
This file defines three routes.
|
||||
|
||||
The first redirects the empty URL (e.g., `http://host.com/`)
|
||||
to another route whose path is `contact` (e.g., `http://host.com/contact`).
|
||||
|
||||
|
||||
The `contact` route isn't defined here.
|
||||
It's defined in the _Contact_ feature's _own_ routing file, `contact.routing.ts`.
|
||||
It's defined in the _Contact_ feature's _own_ routing module, `contact-routing.module.ts`.
|
||||
It's standard practice for feature modules with routing components to define their own routes.
|
||||
We'll get to that file in a moment.
|
||||
|
||||
The remaining two routes use lazy loading syntax to tell the router where to find the modules:
|
||||
+makeExample('ngmodule/ts/app/app.routing.ts', 'lazy-routes')(format='.')
|
||||
+makeExample('ngmodule/ts/app/app-routing.module.ts', 'lazy-routes')(format='.')
|
||||
.l-sub-section
|
||||
:marked
|
||||
A lazy loaded module location is a _string_, not a _type_.
|
||||
A lazy loaded module location is a _string_, not a _type_.
|
||||
In this app, the string identifies both the module _file_ and the module _class_,
|
||||
the latter separated from the former by a `#`.
|
||||
|
||||
:marked
|
||||
### RouterModule.forRoot
|
||||
|
||||
The last line calls the `forRoot` static class method of the `RouterModule`, passing in the configuration.
|
||||
+makeExample('ngmodule/ts/app/app.routing.ts', 'forRoot')(format='.')
|
||||
The `forRoot` static class method of the `RouterModule` with the provided configuration,
|
||||
added to the `imports` array provides the routing concerns for the module.
|
||||
+makeExample('ngmodule/ts/app/app-routing.module.ts', 'forRoot')(format='.')
|
||||
:marked
|
||||
The returned `routing` object is a `ModuleWithProviders` containing both the `RouterModule` directives
|
||||
and the Dependency Injection providers that produce a configured `Router`.
|
||||
The returned `AppRoutingModule` class is a `Routing Module` containing both the `RouterModule` directives
|
||||
and the Dependency Injection providers that produce a configured `Router`.
|
||||
|
||||
This `routing` object is intended for the app _root_ module _only_.
|
||||
This `AppRoutingModule` is intended for the app _root_ module _only_.
|
||||
|
||||
.alert.is-critical
|
||||
:marked
|
||||
Never call `RouterModule.forRoot` in a feature module.
|
||||
Never call `RouterModule.forRoot` in a feature routing module.
|
||||
:marked
|
||||
Back in the root `AppModule`, we add this `routing` object to its `imports` list,
|
||||
Back in the root `AppModule`, we add the `AppRoutingModule` to its `imports` list,
|
||||
and the app is ready to navigate.
|
||||
+makeExample('ngmodule/ts/app/app.module.3.ts', 'imports', 'app/app.module.ts (imports)')(format='.')
|
||||
|
||||
:marked
|
||||
### Routing to a feature module
|
||||
The `app/contact` folder holds a new file, `contact.routing.ts`.
|
||||
It defines the `contact` route we mentioned a bit earlier and also creates a `routing` object like so:
|
||||
+makeExample('ngmodule/ts/app/contact/contact.routing.ts', 'routing', 'app/contact/contact.routing.ts (routing)')(format='.')
|
||||
The `app/contact` folder holds a new file, `contact-routing.module.ts`.
|
||||
It defines the `contact` route we mentioned a bit earlier and also provides a `ContactRoutingModule` like so:
|
||||
+makeExample('ngmodule/ts/app/contact/contact-routing.module.ts', 'routing', 'app/contact/contact-routing.module.ts (routing)')(format='.')
|
||||
:marked
|
||||
This time we pass the route list to the `forChild` method of the `RouterModule`.
|
||||
It produces a different kind of object intended for feature modules.
|
||||
It's only responsible for providing additional routes and is intended for feature modules.
|
||||
|
||||
.alert.is-important
|
||||
:marked
|
||||
Always call `RouterModule.forChild` in a feature module.
|
||||
Always call `RouterModule.forChild` in a feature routing module.
|
||||
|
||||
.alert.is-helpful
|
||||
:marked
|
||||
|
@ -736,15 +738,15 @@ a#lazy-load
|
|||
+makeTabs(
|
||||
`ngmodule/ts/app/contact/contact.module.3.ts,
|
||||
ngmodule/ts/app/contact/contact.module.2.ts`,
|
||||
'class, class',
|
||||
'class, class',
|
||||
`app/contact/contact.module.3.ts,
|
||||
app/contact/contact.module.2.ts`)
|
||||
:marked
|
||||
1. It imports the `routing` object from `contact.routing.ts`
|
||||
1. It imports the `ContactRoutingModule` object from `contact-routing.module.ts`
|
||||
1. It no longer exports `ContactComponent`
|
||||
|
||||
Now that we navigate to `ContactComponent` with the router there's no reason to make it public.
|
||||
Nor does it need a selector.
|
||||
Nor does it need a selector.
|
||||
No template will ever again reference this `ContactComponent`.
|
||||
It's gone from the [_AppComponent_ template](#app-component-template).
|
||||
|
||||
|
@ -755,7 +757,7 @@ a#hero-module
|
|||
The lazy loaded `HeroModule` and `CrisisModule` follow the same principles as any feature module.
|
||||
They don't look different from the eagerly loaded `ContactModule`.
|
||||
|
||||
The `HeroModule` is a bit more complex than the `CrisisModule` which makes it
|
||||
The `HeroModule` is a bit more complex than the `CrisisModule` which makes it
|
||||
a more interesting and useful example. Here's its file structure:
|
||||
|
||||
.filetree
|
||||
|
@ -765,13 +767,13 @@ a#hero-module
|
|||
.file hero-list.component.ts
|
||||
.file hero.component.ts
|
||||
.file hero.module.ts
|
||||
.file hero.routing.ts
|
||||
.file hero-routing.module.ts
|
||||
.file hero.service.ts
|
||||
.file highlight.directive.ts
|
||||
:marked
|
||||
This is the child routing scenario familiar to readers of the [Router](router.html#child-routing-component) page.
|
||||
The `HeroComponent` is the feature's top component and routing host.
|
||||
Its template has a `<router-outlet>` that displays either a list of heroes (`HeroList`)
|
||||
The `HeroComponent` is the feature's top component and routing host.
|
||||
Its template has a `<router-outlet>` that displays either a list of heroes (`HeroList`)
|
||||
or an editor of a selected hero (`HeroDetail`).
|
||||
Both components delegate to the `HeroService` to fetch and save data.
|
||||
|
||||
|
@ -782,10 +784,10 @@ a#hero-module
|
|||
The `HeroModule` is a feature module like any other.
|
||||
+makeExample('ngmodule/ts/app/hero/hero.module.3.ts', 'class', 'app/hero/hero.module.ts (class)')(format='.')
|
||||
:marked
|
||||
It imports the `FormsModule` because the `HeroDetailComponent` template binds with `[(ngModel)]`.
|
||||
It imports a `routing` object from `hero.routing.ts` just as `ContactModule` and `CrisisModule` do.
|
||||
It imports the `FormsModule` because the `HeroDetailComponent` template binds with `[(ngModel)]`.
|
||||
It imports the `HeroRoutingModule` from `hero-routing.module.ts` just as `ContactModule` and `CrisisModule` do.
|
||||
|
||||
The `CrisisModule` is much the same. There's nothing more to say that's new.
|
||||
The `CrisisModule` is much the same. There's nothing more to say that's new.
|
||||
|
||||
<live-example embedded plnkr="pre-shared.3" img="devguide/ngmodule/v3-plunker.png">Try the live example.</live-example>
|
||||
|
||||
|
@ -793,12 +795,12 @@ a#shared-module
|
|||
.l-main-section
|
||||
:marked
|
||||
## Shared modules
|
||||
|
||||
The app is shaping up.
|
||||
|
||||
The app is shaping up.
|
||||
One thing we don't like is carrying three different versions of the `HighlightDirective`.
|
||||
And there's a bunch of other stuff cluttering the app folder level that could be tucked away.
|
||||
|
||||
Let's add a `SharedModule` to hold the common components, directives, and pipes
|
||||
Let's add a `SharedModule` to hold the common components, directives, and pipes
|
||||
and share them with the modules that need them.
|
||||
|
||||
* create an `app/shared` folder
|
||||
|
@ -815,7 +817,7 @@ a#shared-module
|
|||
* It declares and exports the utility pipe, directive, and component classes as expected.
|
||||
* It re-exports the `CommonModule` and `FormsModule`
|
||||
|
||||
#### Re-exporting other modules
|
||||
### Re-exporting other modules
|
||||
|
||||
While reviewing our application, we noticed that many components requiring `SharedModule` directives
|
||||
also use `NgIf` and `NgFor` from `CommonModule`
|
||||
|
@ -825,9 +827,9 @@ a#shared-module
|
|||
We can reduce the repetition by having `SharedModule` re-export `CommonModule` and `FormsModule`
|
||||
so that importers of `SharedModule` get `CommonModule` and `FormsModule` _for free_.
|
||||
|
||||
As it happens, the components declared by `SharedModule` itself don't bind with `[(ngModel)]`.
|
||||
As it happens, the components declared by `SharedModule` itself don't bind with `[(ngModel)]`.
|
||||
Technically, there is no need for `SharedModule` to import `FormsModule`.
|
||||
|
||||
|
||||
`SharedModule` can still export `FormsModule` without listing it among its `imports`.
|
||||
|
||||
### Why _TitleComponent_ isn't shared
|
||||
|
@ -835,22 +837,22 @@ a#shared-module
|
|||
`SharedModule` exists to make commonly used components, directives and pipes available
|
||||
for use in the templates of components in _many_ other modules.
|
||||
|
||||
The `TitleComponent` is used _only once_ by the `AppComponent`.
|
||||
The `TitleComponent` is used _only once_ by the `AppComponent`.
|
||||
There's no point in sharing it.
|
||||
|
||||
<a id="no-shared-module-providers"></a>
|
||||
### Why _UserService_ isn't shared
|
||||
### Why _UserService_ isn't shared
|
||||
|
||||
While many components share the same service _instances_,
|
||||
they rely on Angular dependency injection to do this kind of sharing, not the module system.
|
||||
|
||||
|
||||
Several components of our sample inject the `UserService`.
|
||||
There should be _only one_ instance of the `UserService` in the entire application
|
||||
There should be _only one_ instance of the `UserService` in the entire application
|
||||
and _only one_ provider of it.
|
||||
|
||||
|
||||
`UserService` is an application-wide singleton.
|
||||
We don't want each module to have its own separate instance.
|
||||
Yet there is [a real danger](../cookbook/ngmodule-faq.html#q-why-it-is-bad) of that happening
|
||||
We don't want each module to have its own separate instance.
|
||||
Yet there is [a real danger](../cookbook/ngmodule-faq.html#q-why-it-is-bad) of that happening
|
||||
if the `SharedModule` provides the `UserService`.
|
||||
|
||||
.alert.is-critical
|
||||
|
@ -865,7 +867,7 @@ a#core-module
|
|||
At the moment, our root folder is cluttered with the `UserService`
|
||||
and the `TitleComponent` that only appears in the root `AppComponent`.
|
||||
We did not include them in the `SharedModule` for reasons just explained.
|
||||
|
||||
|
||||
Instead, we'll gather them in a single `CoreModule` that we **import _once_ when the app starts**
|
||||
and _never import anywhere else_.
|
||||
|
||||
|
@ -875,7 +877,7 @@ a#core-module
|
|||
* move the `UserService` and `TitleComponent` from `app/` to `app/core`
|
||||
* create a `CoreModule` class to own the core material
|
||||
* update the `AppRoot` module to import `CoreModule`
|
||||
|
||||
|
||||
Again, most of this is familiar blocking and tackling. The interesting part is the `CoreModule`
|
||||
+makeExample('ngmodule/ts/app/core/core.module.ts', 'v4', 'app/app/core/core.module.ts')
|
||||
.l-sub-section
|
||||
|
@ -883,29 +885,29 @@ a#core-module
|
|||
We're importing some extra symbols from the Angular core library that we're not using yet.
|
||||
They'll become relevant later in this page.
|
||||
:marked
|
||||
The `@NgModule` metadata should be familiar.
|
||||
The `@NgModule` metadata should be familiar.
|
||||
We declare the `TitleComponent` because this module _owns_ it and we export it
|
||||
because `AppComponent` (which is in `AppModule`) displays the title in its template.
|
||||
`TitleComponent` needs the Angular `NgIf` directive that we import from `CommonModule`.
|
||||
|
||||
`CoreModule` _provides_ the `UserService`. Angular registers that provider with the app root injector,
|
||||
making a singleton instance of the `UserService` available to any component that needs it,
|
||||
making a singleton instance of the `UserService` available to any component that needs it,
|
||||
whether that component is eagerly or lazily loaded.
|
||||
|
||||
.l-sub-section
|
||||
:marked
|
||||
#### Why bother?
|
||||
This scenario is clearly contrived.
|
||||
### Why bother?
|
||||
This scenario is clearly contrived.
|
||||
The app is too small to worry about a single service file and a tiny, one-time component.
|
||||
|
||||
A `TitleComponent` sitting in the root folder isn't bothering anyone.
|
||||
The root `AppModule` can register the `UserService` itself,
|
||||
as it does currently, even if we decide to relocate the `UserService` file to the `app/core` folder.
|
||||
|
||||
Real world apps have more to worry about.
|
||||
Real world apps have more to worry about.
|
||||
They can have several single-use components (e.g., spinners, message toasts, and modal dialogs)
|
||||
that appear only in the `AppComponent` template.
|
||||
We don't import them elsewhere so they're not _shared_ in that sense.
|
||||
that appear only in the `AppComponent` template.
|
||||
We don't import them elsewhere so they're not _shared_ in that sense.
|
||||
Yet they're too big and messy to leave loose in the root folder.
|
||||
|
||||
Apps often have many singleton services like this sample's `UserService`.
|
||||
|
@ -922,10 +924,10 @@ a#core-module
|
|||
.l-main-section
|
||||
:marked
|
||||
## Cleanup
|
||||
Having refactored to a `CoreModule` and a `SharedModule`, it's time to cleanup the other modules.
|
||||
Having refactored to a `CoreModule` and a `SharedModule`, it's time to cleanup the other modules.
|
||||
|
||||
### A trimmer _AppModule_
|
||||
|
||||
|
||||
Here is the updated `AppModule` paired with version 3 for comparison:
|
||||
+makeTabs(
|
||||
`ngmodule/ts/app/app.module.ts,
|
||||
|
@ -964,7 +966,7 @@ a#core-for-root
|
|||
## Configure core services with _CoreModule.forRoot_
|
||||
|
||||
A module that adds providers to the application can offer a facility for configuring those providers as well.
|
||||
|
||||
|
||||
By convention, the **_forRoot_** static method both provides and configures services at the same time.
|
||||
It takes a service configuration object and returns a
|
||||
[ModuleWithProviders](../api/core/index/ModuleWithProviders-interface.html) which is
|
||||
|
@ -975,8 +977,8 @@ a#core-for-root
|
|||
The root `AppModule` imports the `CoreModule` and adds the `providers` to the `AppModule` providers.
|
||||
.l-sub-section
|
||||
:marked
|
||||
More precisely, Angular accumulates all imported providers _before_ appending the items listed in `@NgModule.providers`.
|
||||
This sequence ensures that whatever we add explicitly to the `AppModule` providers takes precedence
|
||||
More precisely, Angular accumulates all imported providers _before_ appending the items listed in `@NgModule.providers`.
|
||||
This sequence ensures that whatever we add explicitly to the `AppModule` providers takes precedence
|
||||
over the providers of imported modules.
|
||||
:marked
|
||||
Let's add a `CoreModule.forRoot` method that configures the core `UserService`.
|
||||
|
@ -1008,10 +1010,10 @@ a#prevent-reimport
|
|||
:marked
|
||||
## Prevent reimport of the _CoreModule_
|
||||
|
||||
Only the root `AppModule` should import the `CoreModule`.
|
||||
Only the root `AppModule` should import the `CoreModule`.
|
||||
[Bad things happen](../cookbook/ngmodule-faq.html#q-why-it-is-bad) if a lazy loaded module imports it.
|
||||
|
||||
We could _hope_ that no developer makes that mistake.
|
||||
We could _hope_ that no developer makes that mistake.
|
||||
Or we can guard against it and fail fast by adding the following `CoreModule` constructor.
|
||||
+makeExample('ngmodule/ts/app/core/core.module.ts', 'ctor')(format='.')
|
||||
:marked
|
||||
|
@ -1020,25 +1022,25 @@ a#prevent-reimport
|
|||
|
||||
The injection _would be circular_ if Angular looked for `CoreModule` in the _current_ injector.
|
||||
The `@SkipSelf` decorator means "_look for_ `CoreModule` _in an ancestor injector, above me in the injector hierarchy._"
|
||||
|
||||
If the constructor executes as intended in the `AppModule`,
|
||||
|
||||
If the constructor executes as intended in the `AppModule`,
|
||||
there is no ancestor injector that could provide an instance of `CoreModule`.
|
||||
The injector should give up.
|
||||
|
||||
By default the injector throws an error when it can't find a requested provider.
|
||||
The `@Optional` decorator means not finding the service is OK.
|
||||
The `@Optional` decorator means not finding the service is OK.
|
||||
The injector returns `null`, the `parentModule` parameter is null,
|
||||
and the constructor concludes uneventfully.
|
||||
|
||||
It's a different story if we improperly import `CoreModule` into a lazy loaded module such as `HeroModule` (try it).
|
||||
|
||||
|
||||
Angular creates a lazy loaded module with its own injector, a _child_ of the root injector.
|
||||
`@SkipSelf` causes Angular to look for a `CoreModule` in the parent injector which this time is the root injector.
|
||||
Of course it finds the instance imported by the root `AppModule`.
|
||||
Of course it finds the instance imported by the root `AppModule`.
|
||||
Now `parentModule` exists and the constructor throws the error.
|
||||
:marked
|
||||
### Conclusion
|
||||
|
||||
|
||||
You made it! You can examine and download the complete source for this final version from the live example.
|
||||
<live-example embedded img="devguide/ngmodule/final-plunker.png"></live-example>
|
||||
|
||||
|
|
|
@ -46,6 +46,7 @@ include ../_util-fns
|
|||
* toggling css classes for the [active router link](#router-link-active)
|
||||
* embedding critical information in the URL with [route parameters](#route-parameters)
|
||||
* providing non-critical information in [optional route parameters](#optional-route-parameters)
|
||||
* refactoring routing into a [routing module](#routing-module)
|
||||
* add [child routes](#child-routing-component) under a feature section
|
||||
* [grouping child routes](#component-less-route) without a component
|
||||
* [redirecting](#redirect) from one route to another
|
||||
|
@ -87,7 +88,7 @@ include ../_util-fns
|
|||
It is not part of the Angular core. It is in its own library package, `@angular/router`.
|
||||
We import what we need from it as we would from any other Angular package.
|
||||
|
||||
+makeExcerpt('app/app.routing.ts (import)', 'import-router')
|
||||
+makeExcerpt('app/app.module.1.ts (import)', 'import-router')
|
||||
|
||||
.l-sub-section
|
||||
:marked
|
||||
|
@ -100,13 +101,14 @@ include ../_util-fns
|
|||
A router has no routes until we configure it.
|
||||
We bootstrap our application with an array of routes that we'll provide to our **`RouterModule.forRoot`** function.
|
||||
|
||||
In the following example, we configure our application with four route definitions.
|
||||
In the following example, we configure our application with four route definitions. The configured `RouterModule` is
|
||||
add to the `AppModule`'s `imports` array.
|
||||
|
||||
+makeExcerpt('app/app.routing.1.ts (excerpt)', 'route-config')
|
||||
+makeExcerpt('app/app.module.0.ts (excerpt)', 'route-config')
|
||||
|
||||
.l-sub-section
|
||||
:marked
|
||||
The `Routes` is an array of *routes* that describe how to navigate.
|
||||
The `RouterModule` is provided an array of *routes* that describe how to navigate.
|
||||
Each *Route* maps a URL `path` to a component.
|
||||
|
||||
There are no **leading slashes** in our **path**. The router parses and builds the URL for us,
|
||||
|
@ -135,14 +137,6 @@ include ../_util-fns
|
|||
that matches as the default route. The wildcard route is listed last as it's the most generic route and should be
|
||||
matched **only** if no other routes are matched first.
|
||||
|
||||
:marked
|
||||
We export the `routing` constant so we can import it into our `app.module.ts` file where we'll add
|
||||
a configured *Router* module to our `AppModule` imports.
|
||||
:marked
|
||||
Next we open `app.module.ts` where we must register our routing, routing providers, and declare our two route components.
|
||||
|
||||
+makeExcerpt('app/app.module.1.ts (basic setup)', 'router-basics')
|
||||
|
||||
:marked
|
||||
### Router Outlet
|
||||
Given this configuration, when the browser URL for this application becomes `/heroes`,
|
||||
|
@ -192,7 +186,7 @@ code-example(language="html").
|
|||
that make up the current state of the router. We can access the current `RouterState` from anywhere in our
|
||||
application using the `Router` service and the `routerState` property.
|
||||
|
||||
The router state provides us with methods to traverse up and down the route tree from any activated route
|
||||
Each `ActivatedRoute` in the `RouterState` provides methods to traverse up and down the route tree
|
||||
to get information we may need from parent, child and sibling routes.
|
||||
|
||||
:marked
|
||||
|
@ -413,20 +407,6 @@ a#base-href
|
|||
need routing and, depending on your requirements, you may need a different routing library.
|
||||
|
||||
We teach our router how to navigate by configuring it with routes.
|
||||
We recommend creating a separate `app.routing.ts` file dedicated to this purpose.
|
||||
|
||||
:marked
|
||||
Here is our first configuration. We pass the array of routes to the `RouterModule.forRoot` method
|
||||
which returns a module containing the configured `Router` service provider ... and some other,
|
||||
unseen providers that the routing library requires. We export this as the `routing` token.
|
||||
|
||||
+makeExcerpt('app/app.routing.2.ts')
|
||||
|
||||
.l-sub-section
|
||||
:marked
|
||||
We also export an empty `appRoutingProviders` array
|
||||
so we can simplify registration of router dependencies later in `app.module.ts`.
|
||||
We don't have any providers to register right now. But we will.
|
||||
|
||||
a#route-config
|
||||
h4#define-routes Define routes
|
||||
|
@ -451,25 +431,23 @@ h4#define-routes Define routes
|
|||
the `CrisisListComponent`, display its view, and update the browser's address location and history with the URL
|
||||
for that path.*
|
||||
|
||||
.l-sub-section
|
||||
:marked
|
||||
Learn about *providers* in the [Dependency Injection](dependency-injection.html#!#injector-providers) chapter.
|
||||
|
||||
h4#register-providers Register routing in the AppModule
|
||||
:marked
|
||||
Our app launches from the `app.module.ts` file in the `/app` folder.
|
||||
|
||||
We import the `routing` token we exported from the `app.routing.ts` file and add it to the `imports` array.
|
||||
|
||||
We import our `CrisisListComponent` and `HeroListComponent` components and add them to our *declarations*
|
||||
so they will be registered within our `AppModule`.
|
||||
|
||||
We also import the `appRoutingProviders` array and add it to the `providers` array.
|
||||
Here is our first configuration. We pass the array of routes to the `RouterModule.forRoot` method
|
||||
which returns a module containing the configured `Router` service provider ... and some other,
|
||||
unseen providers that the routing library requires. Once our application is bootstrapped, the `Router`
|
||||
will perform the initial navigation based on the current browser URL.
|
||||
|
||||
+makeExcerpt('app/app.module.1.ts')
|
||||
|
||||
.l-sub-section
|
||||
:marked
|
||||
Adding the configured `RouterModule` to the `AppModule` is sufficient for simple route configurations.
|
||||
As our application grows, we'll want to refactor our routing configuration into a separate file
|
||||
and create a **[Routing Module](#routing-module)**, a special type of `Service Module` dedicating for the purpose
|
||||
of routing in feature modules.
|
||||
|
||||
:marked
|
||||
Providing the router module in our `AppModule` makes the Router available everywhere in our application.
|
||||
Providing the `RouterModule` in our `AppModule` makes the Router available everywhere in our application.
|
||||
|
||||
h3#shell The <i>AppComponent</i> shell
|
||||
:marked
|
||||
|
@ -562,7 +540,6 @@ h3#router-directives <i>Router Directives</i>
|
|||
.children
|
||||
.file app.component.ts
|
||||
.file app.module.ts
|
||||
.file app.routing.ts
|
||||
.file crisis-list.component.ts
|
||||
.file hero-list.component.ts
|
||||
.file main.ts
|
||||
|
@ -579,7 +556,6 @@ h3#router-directives <i>Router Directives</i>
|
|||
+makeTabs(
|
||||
`router/ts/app/app.component.1.ts,
|
||||
router/ts/app/app.module.1.ts,
|
||||
router/ts/app/app.routing.2.ts,
|
||||
router/ts/app/main.ts,
|
||||
router/ts/app/hero-list.component.ts,
|
||||
router/ts/app/crisis-list.component.ts,
|
||||
|
@ -587,15 +563,85 @@ h3#router-directives <i>Router Directives</i>
|
|||
',,,,',
|
||||
`app.component.ts,
|
||||
app.module.ts,
|
||||
app.routing.ts,
|
||||
main.ts,
|
||||
hero-list.component.ts,
|
||||
crisis-list.component.ts,
|
||||
index.html`)
|
||||
|
||||
.l-main-section#routing-module
|
||||
:marked
|
||||
## Milestone #2: The *Routing Module*
|
||||
|
||||
In our initial route configuration, we provided a simple setup with two routes used
|
||||
to configure our application for routing. This is perfectly fine for simple routing.
|
||||
As our application grows and we make use of more *Router* features, such as guards,
|
||||
resolvers, and child routing, we'll naturally want to refactor our routing. We
|
||||
recommend moving the routing into a separate file using a special-purpose
|
||||
service called a *Routing Module*.
|
||||
|
||||
The **Routing Module**
|
||||
* separates our routing concerns from our feature module
|
||||
* provides a module to replace or remove when testing our feature module
|
||||
* provides a common place for require routing service providers including guards and resolvers
|
||||
* is **not** concerned with feature [module declarations](../cookbook/ngmodule-faq.html#!#routing-module)
|
||||
|
||||
:marked
|
||||
### Refactor routing into a module
|
||||
|
||||
We'll create a file named `app-routing.module.ts` in our `/app` folder to
|
||||
contain our `Routing Module`. The routing module will import our `RouterModule` tokens
|
||||
and configure our routes. We'll follow the convention of our filename and name
|
||||
the Angular module `AppRoutingModule`.
|
||||
|
||||
We import the `CrisisListComponent` and the `HeroListComponent` components
|
||||
just like we did in the `app.module.ts`. Then we'll move the `Router` imports
|
||||
and routing configuration including `RouterModule.forRoot` into our routing module.
|
||||
|
||||
We'll also export the `AppRoutingModule` so we can add it to our `AppModule` imports.
|
||||
|
||||
Our last step is to re-export the `RouterModule`. By re-exporting the `RouterModule`,
|
||||
our feature module will be provided with the `Router Directives` when using our `Routing Module`.
|
||||
|
||||
Here is our first `Routing Module`:
|
||||
|
||||
+makeExcerpt('app/app-routing.module.1.ts')
|
||||
|
||||
:marked
|
||||
Next, we'll update our `app.module.ts` file by importing our `AppRoutingModule` token
|
||||
from the `app-routing.module.ts` and replace our `RouterModule.forRoot` with our newly
|
||||
created `AppRoutingModule`.
|
||||
|
||||
+makeExcerpt('app/app.module.2.ts')
|
||||
|
||||
:marked
|
||||
Our application continues to work just the same, and we can use our routing module as
|
||||
the central place to maintain our routing configuration for each feature module.
|
||||
|
||||
a#why-routing-module
|
||||
:marked
|
||||
### Do you need a _Routing Module_?
|
||||
|
||||
The _Routing Module_ *replaces* the routing configuration in the root or feature module.
|
||||
_Either_ configure routes in the Routing Module _or_ within the module itself but not in both.
|
||||
|
||||
The Routing Module is a design choice whose value is most obvious when the configuration is complex
|
||||
and includes specialized guard and resolver services.
|
||||
It can seem like overkill when the actual configuration is dead simple.
|
||||
|
||||
Some developers skip the Routing Module (e.g., `AppRoutingModule`) when the configuration is simple and
|
||||
merge the routing configuration directly into the companion module (e.g., `AppModule`).
|
||||
|
||||
We recommend that you choose one pattern or the other and follow that pattern consistently.
|
||||
|
||||
Most developers should always implement a Routing Module for the sake of consistency.
|
||||
It keeps the code clean when configuration becomes complex.
|
||||
It makes testing the feature module easier.
|
||||
Its existence calls attention to the fact that a module is routed.
|
||||
It is where developers expect to find and expand routing configuration.
|
||||
|
||||
.l-main-section#heroes-feature
|
||||
:marked
|
||||
## Milestone #2: The Heroes Feature
|
||||
## Milestone #3: The Heroes Feature
|
||||
|
||||
We've seen how to navigate using the `RouterLink` directive.
|
||||
|
||||
|
@ -677,20 +723,25 @@ figure.image-display
|
|||
|
||||
We recommend giving each feature area its own route configuration file.
|
||||
|
||||
Create a new `heroes.routing.ts` in the `heroes` folder like this:
|
||||
Create a new `heroes-routing.module.ts` in the `heroes` folder like this:
|
||||
|
||||
+makeExcerpt('app/heroes/heroes.routing.ts')
|
||||
+makeExcerpt('app/heroes/heroes-routing.module.ts')
|
||||
|
||||
.l-sub-section
|
||||
:marked
|
||||
Keep the Routing Module file in the same folder as its companion module file.
|
||||
Here both `heroes-routing.module.ts` and `heroes.module.ts` are in the same `app/heroes` folder.
|
||||
|
||||
:marked
|
||||
We use the same techniques we learned for `app.routing.ts`.
|
||||
We use the same techniques we learned in creating the `app-routing.module.ts`.
|
||||
|
||||
We import the two components from their new locations in the `app/heroes/` folder, define the two hero routes.
|
||||
and add export our `heroesRouting` that returns configured `RouterModule` for our feature module.
|
||||
and add export our `HeroRoutingModule` that returns our `RoutingModule` for the hero feature module.
|
||||
|
||||
:marked
|
||||
Now that we have routes for our `Heroes` module, we'll need to register them with the *Router*.
|
||||
We'll import the *RouterModule* like we did in the `app.routing.ts`, but there is a slight difference here.
|
||||
In our `app.routing.ts`, we used the static **forRoot** method to register our routes and application level
|
||||
We'll import the *RouterModule* like we did in the `app-routing.module.ts`, but there is a slight difference here.
|
||||
In our `app-routing.module.ts`, we used the static **forRoot** method to register our routes and application level
|
||||
service providers. In a feature module we use static **forChild** method.
|
||||
|
||||
.l-sub-section
|
||||
|
@ -699,7 +750,7 @@ figure.image-display
|
|||
module, we'll use **RouterModule.forChild** method to only register additional routes.
|
||||
|
||||
:marked
|
||||
We import our `heroesRouting` token from `heroes.routing.ts` into our `Heroes` module and register the routing.
|
||||
We import our `HeroRoutingModule` token from `heroes-routing.module.ts` into our `Heroes` module and register the routing.
|
||||
|
||||
+makeExcerpt('app/heroes/heroes.module.ts (heroes routing)', 'heroes-routes')
|
||||
|
||||
|
@ -707,7 +758,7 @@ figure.image-display
|
|||
### Route definition with a parameter
|
||||
The route to `HeroDetailComponent` has a twist.
|
||||
|
||||
+makeExcerpt('app/heroes/heroes.routing.ts (excerpt)', 'hero-detail-route')
|
||||
+makeExcerpt('app/heroes/heroes-routing.module.ts (excerpt)', 'hero-detail-route')
|
||||
|
||||
:marked
|
||||
Notice the `:id` token in the path. That creates a slot in the path for a **Route Parameter**.
|
||||
|
@ -963,7 +1014,7 @@ figure.image-display
|
|||
The router embedded the `id` value in the navigation URL because we had defined it
|
||||
as a route parameter with an `:id` placeholder token in the route `path`:
|
||||
|
||||
+makeExcerpt('app/heroes/heroes.routing.ts', 'hero-detail-route')
|
||||
+makeExcerpt('app/heroes/heroes-routing.module.ts', 'hero-detail-route')
|
||||
|
||||
:marked
|
||||
When the user clicks the back button, the `HeroDetailComponent` constructs another *link parameters array*
|
||||
|
@ -975,7 +1026,7 @@ figure.image-display
|
|||
This array lacks a route parameter because we had no reason to send information to the `HeroListComponent`.
|
||||
|
||||
Now we have a reason. We'd like to send the id of the current hero with the navigation request so that the
|
||||
`HeroListComponent` can highlight that hero in its list.
|
||||
`HeroListComponent` can highlight that hero in its list.
|
||||
This is a _nice-to-have_ feature; the list will display perfectly well without it.
|
||||
|
||||
We do that with an object that contains an _optional_ `id` parameter.
|
||||
|
@ -1125,7 +1176,7 @@ h3#merge-hero-routes Import hero module into AppModule
|
|||
|
||||
Update `app.module.ts` as follows:
|
||||
|
||||
+makeExcerpt('app/app.module.2.ts (heroes module import)', 'hero-import')
|
||||
+makeExcerpt('app/app.module.3.ts (heroes module import)', 'hero-import')
|
||||
|
||||
:marked
|
||||
We imported the `HeroesModule` and added it to our `AppModule`'s `imports`.
|
||||
|
@ -1145,9 +1196,9 @@ h3#merge-hero-routes Import hero module into AppModule
|
|||
We can evolve the hero feature with more components and different routes.
|
||||
That's a key benefit of creating a separate module for each feature area.
|
||||
|
||||
Since our `Heroes` routes are defined within our feature module, we can also remove our initial `heroes` route from the `app.routing.ts`.
|
||||
Since our `Heroes` routes are defined within our feature module, we can also remove our initial `heroes` route from the `app-routing.module.ts`.
|
||||
|
||||
+makeExcerpt('app/app.routing.3.ts (v2)', '')
|
||||
+makeExcerpt('app/app-routing.module.2.ts (v2)', '')
|
||||
|
||||
:marked
|
||||
### Heroes App Wrap-up
|
||||
|
@ -1173,10 +1224,10 @@ h3#merge-hero-routes Import hero module into AppModule
|
|||
.file hero-list.component.ts
|
||||
.file hero.service.ts
|
||||
.file heroes.module.ts
|
||||
.file heroes.routing.ts
|
||||
.file heroes-routing.module.ts
|
||||
.file app.component.ts
|
||||
.file app.module.ts
|
||||
.file app.routing.ts
|
||||
.file app-routing.module.ts
|
||||
.file crisis-list.component.ts
|
||||
.file main.ts
|
||||
.file node_modules ...
|
||||
|
@ -1193,26 +1244,26 @@ h3#merge-hero-routes Import hero module into AppModule
|
|||
|
||||
+makeTabs(
|
||||
`router/ts/app/app.component.1.ts,
|
||||
router/ts/app/app.module.2.ts,
|
||||
router/ts/app/app.routing.3.ts,
|
||||
router/ts/app/app.module.3.ts,
|
||||
router/ts/app/app-routing.module.3.ts,
|
||||
router/ts/app/heroes/hero-list.component.ts,
|
||||
router/ts/app/heroes/hero-detail.component.ts,
|
||||
router/ts/app/heroes/hero.service.ts,
|
||||
router/ts/app/heroes/heroes.module.ts,
|
||||
router/ts/app/heroes/heroes.routing.ts`,
|
||||
router/ts/app/heroes/heroes-routing.module.ts`,
|
||||
null,
|
||||
`app.component.ts,
|
||||
app.module.ts,
|
||||
app.routing.ts,
|
||||
app-routing.module.ts,
|
||||
hero-list.component.ts,
|
||||
hero-detail.component.ts,
|
||||
hero.service.ts,
|
||||
heroes.module.ts,
|
||||
heroes.routing.ts`)
|
||||
heroes-routing.module.ts`)
|
||||
|
||||
.l-main-section#crisis-center-feature
|
||||
:marked
|
||||
## Milestone #3: The Crisis Center
|
||||
## Milestone #4: The Crisis Center
|
||||
|
||||
The *Crisis Center* is a fake view at the moment. Time to make it useful.
|
||||
|
||||
|
@ -1240,9 +1291,6 @@ h3#merge-hero-routes Import hero module into AppModule
|
|||
|
||||
* The router should block access to certain features until the user logs-in.
|
||||
|
||||
* Our `CrisisService` is only needed within the *Crisis Center* module.
|
||||
We should limit access to it to that module.
|
||||
|
||||
* Changes to a feature module such as *Crisis Center* shouldn't provoke changes to the `AppModule` or
|
||||
any other feature's component.
|
||||
We need to [*separate our concerns*](https://blog.8thlight.com/uncle-bob/2014/05/08/SingleReponsibilityPrinciple.html).
|
||||
|
@ -1298,31 +1346,6 @@ a#child-routing-component
|
|||
We *can* give it a selector. There's no harm in it.
|
||||
Our point is that we don't *need* one because we only *navigate* to it.
|
||||
|
||||
:marked
|
||||
### Service isolation
|
||||
|
||||
The `CrisisService` is neither needed nor wanted outside the *Crisis Center* domain.
|
||||
Instead of registering it with the `AppModule`'s providers —
|
||||
which makes it visible everywhere —
|
||||
we register the `CrisisService` in the `CrisisCenterModule` providers array.
|
||||
|
||||
+makeExcerpt('app/crisis-center/crisis-center.module.1.ts', 'providers', '')
|
||||
|
||||
:marked
|
||||
This limits the scope of the `CrisisService` to the *Crisis Center* routes.
|
||||
No module outside of the *Crisis Center* can access it.
|
||||
|
||||
There's a practical benefit to restricting its scope in this way.
|
||||
|
||||
First we can evolve the service independently of the rest of the application
|
||||
without fear of breaking what should be unrelated modules.
|
||||
|
||||
Second, we can delay loading this service into memory until we need it.
|
||||
We can remove it from the application launch bundle,
|
||||
reducing the size of the initial payload and improving performance.
|
||||
We can load it optionally, [asynchronously](#asynchronous-routing) with the other *Crisis Center* components
|
||||
if and when the user begins that workflow.
|
||||
|
||||
:marked
|
||||
### Child Route Configuration
|
||||
|
||||
|
@ -1334,10 +1357,10 @@ a#child-routing-component
|
|||
+makeExcerpt('app/crisis-center/crisis-center-home.component.ts (minus imports)', 'minus-imports')
|
||||
|
||||
:marked
|
||||
We create a `crisis-center.routing.ts` file as we did the `heroes.routing.ts` file.
|
||||
We create a `crisis-center-routing.module.ts` file as we did the `heroes-routing.module.ts` file.
|
||||
But this time we define **child routes** *within* the parent `crisis-center` route.
|
||||
|
||||
+makeExcerpt('app/crisis-center/crisis-center.routing.1.ts (Routes)', 'routes')
|
||||
+makeExcerpt('app/crisis-center/crisis-center-routing.module.1.ts (Routes)', 'routes')
|
||||
|
||||
:marked
|
||||
Notice that the parent `crisis-center` route has a `children` property
|
||||
|
@ -1378,22 +1401,22 @@ code-example.
|
|||
localhost:3000/crisis-center/2
|
||||
|
||||
:marked
|
||||
Here's the complete `crisis-center.routing.ts` file with its imports.
|
||||
Here's the complete `crisis-center-routing.module.ts` file with its imports.
|
||||
|
||||
+makeExcerpt('app/crisis-center/crisis-center.routing.1.ts', '')
|
||||
+makeExcerpt('app/crisis-center/crisis-center-routing.module.1.ts', '')
|
||||
|
||||
h3#import-crisis-module Import crisis center module into the AppModule routes
|
||||
:marked
|
||||
As with the `Heroes` module, we must import the `Crisis Center` module into the `AppModule`:
|
||||
|
||||
+makeExcerpt('app/app.module.3.ts (Crisis Center Module)', 'crisis-center-module')
|
||||
+makeExcerpt('app/app.module.4.ts (import CrisisCenterModule)', 'crisis-center-module')
|
||||
|
||||
:marked
|
||||
We also remove the initial crisis center route from our `app.routing.ts`. Our routes
|
||||
are now being provided by our `HeroesModule` and our `CrisisCenter` feature modules. We'll keep our `app.routing.ts` file
|
||||
We also remove the initial crisis center route from our `app-routing.module.ts`. Our routes
|
||||
are now being provided by our `HeroesModule` and our `CrisisCenter` feature modules. We'll keep our `app-routing.module.ts` file
|
||||
for general routes which we'll cover later in the chapter.
|
||||
|
||||
+makeExcerpt('app/app.routing.4.ts (v3)', '')
|
||||
+makeExcerpt('app/app-routing.module.3.ts (v3)', '')
|
||||
|
||||
a#redirect
|
||||
:marked
|
||||
|
@ -1414,7 +1437,7 @@ code-example.
|
|||
The preferred solution is to add a `redirect` route that transparently translates from the initial relative URL (`''`)
|
||||
to the desired default path (`/crisis-center`):
|
||||
|
||||
+makeExcerpt('app/crisis-center/crisis-center.routing.2.ts' , 'redirect', '')
|
||||
+makeExcerpt('app/crisis-center/crisis-center-routing.module.2.ts' , 'redirect', '')
|
||||
|
||||
:marked
|
||||
A redirect route requires a `pathMatch` property to tell the router how to match a URL to the path of a route.
|
||||
|
@ -1445,7 +1468,7 @@ code-example.
|
|||
:marked
|
||||
The updated route definitions look like this:
|
||||
|
||||
+makeExcerpt('app/crisis-center/crisis-center.routing.2.ts (routes v2)' , 'routes')
|
||||
+makeExcerpt('app/crisis-center/crisis-center-routing.module.2.ts (routes v2)' , 'routes')
|
||||
|
||||
.l-main-section
|
||||
h2#relative-navigation Relative Navigation
|
||||
|
@ -1522,7 +1545,7 @@ h2#relative-navigation Relative Navigation
|
|||
.l-main-section
|
||||
h2#guards Route Guards
|
||||
:marked
|
||||
## Milestone #4: Route Guards
|
||||
## Milestone #5: Route Guards
|
||||
|
||||
At the moment, *any* user can navigate *anywhere* in the application *anytime*.
|
||||
|
||||
|
@ -1597,7 +1620,7 @@ a#can-activate-guard
|
|||
.file admin-dashboard.component.ts
|
||||
.file admin.component.ts
|
||||
.file admin.module.ts
|
||||
.file admin.routing.ts
|
||||
.file admin-routing.module.ts
|
||||
.file manage-crises.component.ts
|
||||
.file manage-heroes.component.ts
|
||||
|
||||
|
@ -1631,7 +1654,7 @@ a#can-activate-guard
|
|||
:marked
|
||||
Our initial admin routing configuration:
|
||||
|
||||
+makeExcerpt('app/admin/admin.routing.1.ts (admin routing)', 'admin-routes')
|
||||
+makeExcerpt('app/admin/admin-routing.module.1.ts (admin routing)', 'admin-routes')
|
||||
|
||||
h3#component-less-route <i>Component-Less Route</i>: grouping routes without a component
|
||||
:marked
|
||||
|
@ -1646,7 +1669,7 @@ h3#component-less-route <i>Component-Less Route</i>: grouping routes without a c
|
|||
Next, we'll import the `AdminModule` into our `app.module.ts` and add it to the `imports` array
|
||||
to register our admin routes.
|
||||
|
||||
+makeExcerpt('app/app.module.3.ts (admin module)', 'admin-module')
|
||||
+makeExcerpt('app/app.module.4.ts (admin module)', 'admin-module')
|
||||
|
||||
:marked
|
||||
And we add a link to the `AppComponent` shell that users can click to get to this feature.
|
||||
|
@ -1671,10 +1694,10 @@ h3#component-less-route <i>Component-Less Route</i>: grouping routes without a c
|
|||
+makeExcerpt('app/auth-guard.service.1.ts')
|
||||
|
||||
:marked
|
||||
Next we open `admin.routing.ts `, import the `AuthGuard` class, and
|
||||
Next we open `admin-routing.module.ts `, import the `AuthGuard` class, and
|
||||
update the admin route with a `CanActivate` guard property that references it:
|
||||
|
||||
+makeExcerpt('app/admin/admin.routing.2.ts (guarded admin route)', 'admin-route')
|
||||
+makeExcerpt('app/admin/admin-routing.module.2.ts (guarded admin route)', 'admin-route')
|
||||
|
||||
:marked
|
||||
Our admin feature is now protected by the guard, albeit protected poorly.
|
||||
|
@ -1716,20 +1739,19 @@ h3#component-less-route <i>Component-Less Route</i>: grouping routes without a c
|
|||
to our stored URL if available, or use the default URL.
|
||||
There is nothing new about this component or the way we wire it into the router configuration.
|
||||
|
||||
We'll register a `/login` route in our `app.routing.ts` and add the necessary providers to the `appRoutingProviders`
|
||||
array we created earlier. In our `app.module.ts`, we'll import the `LoginComponent` and add it to our `AppModule` `declarations`.
|
||||
We'll register a `/login` route in our `login-routing.module.ts` and add the necessary providers to the `providers`
|
||||
array. In our `app.module.ts`, we'll import the `LoginComponent` and add it to our `AppModule` `declarations`.
|
||||
We'll also import and add the `LoginRoutingModule` to our `AppModule` imports.
|
||||
|
||||
+makeTabs(
|
||||
`router/ts/app/app.module.ts,
|
||||
router/ts/app/app.routing.6.ts,
|
||||
router/ts/app/login.component.1.ts,
|
||||
router/ts/app/login.routing.ts
|
||||
router/ts/app/login-routing.module.ts
|
||||
`,
|
||||
null,
|
||||
`app/app.module.ts,
|
||||
app/app.routing.ts,
|
||||
app/login.component.ts,
|
||||
app/login.routing.ts
|
||||
app/login-routing.module.ts
|
||||
`)
|
||||
|
||||
.l-sub-section
|
||||
|
@ -1759,7 +1781,7 @@ h3#can-activate-child-guard <i>CanActivateChild</i>: guarding child routes
|
|||
We add the same `AuthGuard` to our `component-less` admin route to protect all other child routes at one time
|
||||
instead of adding the `AuthGuard` to each route individually.
|
||||
|
||||
+makeExcerpt('app/admin/admin.routing.3.ts (excerpt)', 'can-activate-child')
|
||||
+makeExcerpt('app/admin/admin-routing.module.3.ts (excerpt)', 'can-activate-child')
|
||||
|
||||
h3#can-deactivate-guard <i>CanDeactivate</i>: handling unsaved changes
|
||||
:marked
|
||||
|
@ -1851,14 +1873,14 @@ a#CanDeactivate
|
|||
to resolve to truthy (navigate) or falsey (stay put).
|
||||
|
||||
:marked
|
||||
We add the `Guard` to our crisis detail route in `crisis-center.routing.ts` using the `canDeactivate` array.
|
||||
We add the `Guard` to our crisis detail route in `crisis-center-routing.module.ts` using the `canDeactivate` array.
|
||||
|
||||
+makeExcerpt('app/crisis-center/crisis-center.routing.3.ts (can deactivate guard)', '')
|
||||
+makeExcerpt('app/crisis-center/crisis-center-routing.module.3.ts (can deactivate guard)', '')
|
||||
|
||||
:marked
|
||||
We also need to add the `Guard` to our main `appRoutingProviders` so the `Router` can inject it during the navigation process.
|
||||
We also need to add the `Guard` to our main `AppRoutingModule` `providers` so the `Router` can inject it during the navigation process.
|
||||
|
||||
+makeExample('app/app.routing.6.ts', '', '')
|
||||
+makeExample('app/app-routing.module.4.ts', '', '')
|
||||
|
||||
:marked
|
||||
Now we have given our user a safeguard against unsaved changes.
|
||||
|
@ -1909,14 +1931,11 @@ h3#resolve-guard <i>Resolve</i>: pre-fetching component data
|
|||
We'll use our `CrisisService.getCrisis` method that returns a promise to prevent our route from loading until the data is fetched. If we don't find a valid `Crisis`,
|
||||
we navigate the user back to the `CrisisList`, canceling the previous in-flight navigation to the crisis details.
|
||||
|
||||
Now that our guard is ready, we'll import it in our `crisis-center.routing.ts` and use the `resolve` object in our route configuration.
|
||||
Now that our guard is ready, we'll import it in our `crisis-center-routing.module.ts` and use the `resolve` object in our route configuration.
|
||||
|
||||
+makeExcerpt('app/crisis-center/crisis-center.routing.ts (resolve)', 'crisis-detail-resolve')
|
||||
We'll add the `CrisisDetailResolve` service to our `CrisisCenterRoutingModule`'s `providers`, so its available to the `Router` during the navigation process.
|
||||
|
||||
:marked
|
||||
We'll add the `CrisisDetailResolve` service to our crisis center module's `providers`, so its available to the `Router` during the navigation process.
|
||||
|
||||
+makeExcerpt('app/crisis-center/crisis-center.module.ts (crisis detail resolve provider)', 'crisis-detail-resolve')
|
||||
+makeExcerpt('app/crisis-center/crisis-center-routing.module.ts (resolve)', 'crisis-detail-resolve')
|
||||
|
||||
:marked
|
||||
Now that we've added our `Resolve` guard to fetch data before the route loads, we no longer need to do this once we get into our `CrisisDetailComponent`.
|
||||
|
@ -1940,7 +1959,7 @@ h3#resolve-guard <i>Resolve</i>: pre-fetching component data
|
|||
`router/ts/app/app.component.ts,
|
||||
router/ts/app/crisis-center/crisis-center-home.component.ts,
|
||||
router/ts/app/crisis-center/crisis-center.component.ts,
|
||||
router/ts/app/crisis-center/crisis-center.routing.ts,
|
||||
router/ts/app/crisis-center/crisis-center-routing.module.ts,
|
||||
router/ts/app/crisis-center/crisis-list.component.ts,
|
||||
router/ts/app/crisis-center/crisis-detail.component.ts,
|
||||
router/ts/app/crisis-center/crisis-detail-resolve.service.ts,
|
||||
|
@ -1950,7 +1969,7 @@ h3#resolve-guard <i>Resolve</i>: pre-fetching component data
|
|||
`app.component.ts,
|
||||
crisis-center-home.component.ts,
|
||||
crisis-center.component.ts,
|
||||
crisis-center.routing.ts,
|
||||
crisis-center-routing.module.ts,
|
||||
crisis-list.component.ts,
|
||||
crisis-detail.component.ts,
|
||||
crisis-detail-resolve.service.ts,
|
||||
|
@ -2026,7 +2045,7 @@ a#fragment
|
|||
<a id="asynchronous-routing"></a>
|
||||
.l-main-section
|
||||
:marked
|
||||
## Milestone #5: Asynchronous Routing
|
||||
## Milestone #6: Asynchronous Routing
|
||||
|
||||
As we have completed our milestones, our application has naturally gotten larger. As we continue to build
|
||||
out feature areas our overall application size will get larger also. At some point we'll reach a tipping
|
||||
|
@ -2047,27 +2066,22 @@ a#fragment
|
|||
:marked
|
||||
### Lazy-Loading route configuration
|
||||
|
||||
We'll start by adding an `admin` route to our `app.routing.ts` file. We want to load our `Admin` module asynchronously,
|
||||
We'll start by adding an `admin` route to our `app-routing.module.ts` file. We want to load our `Admin` module asynchronously,
|
||||
so we'll use the `loadChildren` property in our route config where previously we used the `children` property to include our child routes.
|
||||
|
||||
We'll also change our `admin` **path** in our `admin.routing.ts` to an empty path. The `Router` supports
|
||||
We'll also change our `admin` **path** in our `admin-routing.module.ts` to an empty path. The `Router` supports
|
||||
*empty path* routes, which we can use for grouping routes together without adding anything additional paths to the URL. Our
|
||||
users will still visit `/admin` and our `AdminComponent` still serves as our *Routing Component* which contains
|
||||
our child routes.
|
||||
|
||||
+makeTabs(
|
||||
`router/ts/app/app.routing.ts,
|
||||
router/ts/app/admin/admin.routing.ts`,
|
||||
`router/ts/app/app-routing.module.ts,
|
||||
router/ts/app/admin/admin-routing.module.ts`,
|
||||
'lazy-load-admin,',
|
||||
`app.routing.ts (load children),
|
||||
app/admin/admin.routing.ts (empty path admin)
|
||||
`app-routing.module.ts (load children),
|
||||
app/admin/admin-routing.module.ts (empty path admin)
|
||||
`)
|
||||
|
||||
.l-sub-section
|
||||
:marked
|
||||
We use the ES2015 `spread` feature to flatten the route arrays of our `adminRoutes` and `loginRoutes`
|
||||
into our `appRoutes` array to provide a simple array of routes.
|
||||
|
||||
:marked
|
||||
The `loadChildren` property is used by the `Router` to map to our bundle we want to lazy-load, in this case being the `AdminModule`.
|
||||
|
||||
|
@ -2116,10 +2130,10 @@ h3#can-load-guard <i>CanLoad Guard</i>: guarding against loading of feature modu
|
|||
+makeExcerpt('app/auth-guard.service.ts (can load guard)', '')
|
||||
|
||||
:marked
|
||||
Next, we'll import the `AuthGuard` into our `app.routing.ts` and add the `AuthGuard` to the `canLoad` array for
|
||||
Next, we'll import the `AuthGuard` into our `app-routing.module.ts` and add the `AuthGuard` to the `canLoad` array for
|
||||
our `admin` route. Now our `admin` feature area is only loaded when the proper access has been granted.
|
||||
|
||||
+makeExcerpt('app/app.routing.ts (can load guard)', 'can-load-guard')
|
||||
+makeExcerpt('app/app-routing.module.ts (can load guard)', 'can-load-guard')
|
||||
|
||||
<a id="final-app"></a>
|
||||
.l-main-section
|
||||
|
@ -2325,4 +2339,4 @@ code-example(format=".", language="bash").
|
|||
providing the `useHash: true` in an object as the second argument of the `RouterModule.forRoot`
|
||||
in our `AppModule`.
|
||||
|
||||
+makeExcerpt('app/app.module.5.ts (hash URL strategy)', '')
|
||||
+makeExcerpt('app/app.module.6.ts (hash URL strategy)', '')
|
||||
|
|
|
@ -27,7 +27,7 @@
|
|||
},
|
||||
"toh-pt5": {
|
||||
"title": "Routing",
|
||||
"intro": "We add the Angular Component Router and learn to navigate among the views",
|
||||
"intro": "We add the Angular Router and learn to navigate among the views",
|
||||
"nextable": true
|
||||
},
|
||||
"toh-pt6": {
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
block includes
|
||||
include ../_util-fns
|
||||
- var _appRoutingTsVsAppComp = 'app.routing.ts'
|
||||
- var _appRoutingTsVsAppComp = 'app.module.ts'
|
||||
- var _declsVsDirectives = 'declarations'
|
||||
- var _RoutesVsAtRouteConfig = 'Routes'
|
||||
- var _RouterModuleVsRouterDirectives = 'RouterModule'
|
||||
|
@ -194,7 +194,7 @@ block router-config-intro
|
|||
### Configure routes
|
||||
|
||||
Our application doesn't have any routes yet.
|
||||
We'll start by creating a configuration file for the application routes.
|
||||
We'll start by creating a configuration for the application routes.
|
||||
|
||||
:marked
|
||||
*Routes* tell the router which views to display when a user clicks a link or
|
||||
|
@ -202,11 +202,12 @@ block router-config-intro
|
|||
|
||||
Let's define our first route as a route to the heroes component:
|
||||
|
||||
- var _file = _docsFor == 'dart' ? 'app.component.ts' : 'app.routing.ts'
|
||||
- var _file = _docsFor == 'dart' ? 'app.component.ts' : 'app.module.2.ts'
|
||||
+makeExcerpt('app/' + _file + ' (heroes route)', 'heroes')
|
||||
|
||||
- var _are = _docsFor == 'dart' ? 'takes' : 'are'
|
||||
- var _routePathPrefix = _docsFor == 'dart' ? '/' : ''
|
||||
|
||||
:marked
|
||||
The `!{_RoutesVsAtRouteConfig}` !{_are} !{_an} !{_array} of *route definitions*.
|
||||
We have only one route definition at the moment but rest assured, we'll add more.
|
||||
|
@ -224,24 +225,18 @@ block router-config-intro
|
|||
|
||||
+ifDocsFor('ts|js')
|
||||
:marked
|
||||
We'll export a `routing` constant initialized using the `RouterModule.forRoot` method applied to our !{_array} of routes.
|
||||
This method returns a **configured router module** that we'll add to our root NgModule, `AppModule`.
|
||||
### Make the router available
|
||||
|
||||
+makeExcerpt('app/app.routing.1.ts (excerpt)', 'routing-export')
|
||||
We've setup the initial route configuration. Now we'll add it to our `AppModule`.
|
||||
We'll add our configured `RouterModule` to the `AppModule` imports !{_array}.
|
||||
|
||||
+makeExcerpt('app/app.module.2.ts (app routing)', '')
|
||||
|
||||
.l-sub-section
|
||||
:marked
|
||||
We call the `forRoot` method because we're providing a configured router at the _root_ of the application.
|
||||
The `forRoot` method gives us the Router service providers and directives needed for routing.
|
||||
|
||||
:marked
|
||||
### Make the router available
|
||||
|
||||
We've setup initial routes in the `app.routing.ts` file. Now we'll add it to our root NgModule.
|
||||
|
||||
Import the `routing` constant from `app.routing.ts` and add it the `imports` !{_array} of `AppModule`.
|
||||
|
||||
+makeExcerpt('app/app.module.ts', 'routing')
|
||||
We use the `forRoot` method because we're providing a configured router at the _root_ of the application.
|
||||
The `forRoot` method gives us the Router service providers and directives needed for routing, and
|
||||
performs the initial navigation based on the current browser URL.
|
||||
|
||||
- var _heroesRoute = _docsFor == 'dart' ? "'Heroes'" : 'heroes'
|
||||
:marked
|
||||
|
@ -319,12 +314,12 @@ block routerLink
|
|||
Import the dashboard component and
|
||||
add the following route definition to the `!{_RoutesVsAtRouteConfig}` !{_array} of definitions.
|
||||
|
||||
- var _file = _docsFor == 'dart' ? 'lib/app_component.dart' : 'app/app.routing.ts'
|
||||
- var _file = _docsFor == 'dart' ? 'lib/app_component.dart' : 'app/app.module.3.ts'
|
||||
+makeExcerpt(_file + ' (Dashboard route)', 'dashboard')
|
||||
|
||||
+ifDocsFor('ts|js')
|
||||
:marked
|
||||
Also import and add `DashboardComponent` to our root NgModule's `declarations`.
|
||||
Also import and add `DashboardComponent` to our `AppModule`'s `declarations`.
|
||||
|
||||
+makeExcerpt('app/app.module.ts', 'dashboard')
|
||||
|
||||
|
@ -340,7 +335,7 @@ block redirect-vs-use-as-default
|
|||
We can use a redirect route to make this happen. Add the following
|
||||
to our array of route definitions:
|
||||
|
||||
+makeExcerpt('app/app.routing.ts','redirect')
|
||||
+makeExcerpt('app/app.module.3.ts','redirect')
|
||||
|
||||
.l-sub-section
|
||||
:marked
|
||||
|
@ -466,7 +461,7 @@ code-example(format='').
|
|||
|
||||
Here's the *route definition* we'll use.
|
||||
|
||||
- var _file = _docsFor == 'dart' ? 'app/app.component.ts' : 'app/app.routing.ts'
|
||||
- var _file = _docsFor == 'dart' ? 'app/app.component.ts' : 'app/app.module.3.ts'
|
||||
+makeExcerpt(_file + ' (hero detail)','hero-detail')
|
||||
|
||||
:marked
|
||||
|
@ -634,7 +629,7 @@ block extract-id
|
|||
token in the parameterized hero detail route definition we added to
|
||||
`!{_appRoutingTsVsAppComp}` earlier in the chapter:
|
||||
|
||||
- var _file = _docsFor == 'dart' ? 'app/app.component.ts' : 'app/app.routing.ts'
|
||||
- var _file = _docsFor == 'dart' ? 'app/app.component.ts' : 'app/app.module.3.ts'
|
||||
+makeExcerpt(_file + ' (hero detail)', 'hero-detail')
|
||||
|
||||
:marked
|
||||
|
@ -661,7 +656,7 @@ block extract-id
|
|||
|
||||
:marked
|
||||
Delete the `<h1>` at the top (forgot about it during the `AppComponent`-to-`HeroesComponent` conversion).
|
||||
|
||||
|
||||
Delete the last line of the template with the `<my-hero-detail>` tags.
|
||||
|
||||
We'll no longer show the full `HeroDetailComponent` here.
|
||||
|
@ -864,7 +859,6 @@ block file-tree-end
|
|||
.file app.component.css
|
||||
.file app.component.ts
|
||||
.file app.module.ts
|
||||
.file app.routing.ts
|
||||
.file dashboard.component.css
|
||||
.file dashboard.component.html
|
||||
.file dashboard.component.ts
|
||||
|
|
|
@ -219,7 +219,7 @@ block get-heroes-details
|
|||
Although we made significant *internal* changes to `getHeroes()`, the public signature did not change.
|
||||
We still return a !{_Promise}. We won't have to update any of the components that call `getHeroes()`.
|
||||
|
||||
Our stakeholders are thrilled with the added flexibility from the API integration.
|
||||
Our stakeholders are thrilled with the added flexibility from the API integration.
|
||||
Now they want the ability to create and delete heroes.
|
||||
|
||||
Let's see first what happens when we try to update a hero's details.
|
||||
|
@ -229,7 +229,7 @@ block get-heroes-details
|
|||
## Update hero details
|
||||
|
||||
We can edit a hero's name already in the hero detail view. Go ahead and try
|
||||
it. As we type, the hero name is updated in the view heading.
|
||||
it. As we type, the hero name is updated in the view heading.
|
||||
But when we hit the `Back` button, the changes are lost!
|
||||
|
||||
.l-sub-section
|
||||
|
@ -515,7 +515,7 @@ block observable-transformers
|
|||
- var _declarations = _docsFor == 'dart' ? 'directives' : 'declarations'
|
||||
- var declFile = _docsFor == 'dart' ? 'app/dashboard.component.ts' : 'app/app.module.ts'
|
||||
:marked
|
||||
Finally, we import `HeroSearchComponent` from
|
||||
Finally, we import `HeroSearchComponent` from
|
||||
<span ngio-ex>hero-search.component.ts</span>
|
||||
and add it to the `!{_declarations}` !{_array}:
|
||||
|
||||
|
@ -544,7 +544,7 @@ block filetree
|
|||
.file app.component.ts
|
||||
.file app.component.css
|
||||
.file app.module.ts
|
||||
.file app.routing.ts
|
||||
.file app-routing.module.ts
|
||||
.file dashboard.component.css
|
||||
.file dashboard.component.html
|
||||
.file dashboard.component.ts
|
||||
|
|
Loading…
Reference in New Issue