docs: NgModule guide prose for CLI (partial) (#19776)

Also replaces “Angular Module” with “NgModule” wherever that is clarifying.
Continue using “module” when qualified as in “feature module”, “root module”, “routing module”, etc.

PR Close #19776
This commit is contained in:
Ward Bell 2017-10-17 17:36:22 -07:00 committed by Miško Hevery
parent 69c53c3e03
commit 816d5ba3fd
47 changed files with 1170 additions and 1421 deletions

View File

@ -14,7 +14,7 @@
"app/contact/contact.component.html", "app/contact/contact.component.html",
"app/contact/contact.component.3.ts", "app/contact/contact.component.3.ts",
"app/contact/contact.service.ts", "app/contact/contact.service.ts",
"app/contact/highlight.directive.ts", "app/contact/contact-highlight.directive.ts",
"main.1b.ts", "main.1b.ts",
"styles.css", "styles.css",

View File

@ -16,7 +16,7 @@
"app/contact/awesome.pipe.ts", "app/contact/awesome.pipe.ts",
"app/contact/contact.component.3.ts", "app/contact/contact.component.3.ts",
"app/contact/contact.module.2.ts", "app/contact/contact.module.2.ts",
"app/contact/highlight.directive.ts", "app/contact/contact-highlight.directive.ts",
"main.2.ts", "main.2.ts",
"styles.css", "styles.css",

View File

@ -15,7 +15,7 @@ describe('NgModule', function () {
return { return {
title: element.all(by.tagName('h1')).get(0), title: element.all(by.tagName('h1')).get(0),
subtitle: element.all(by.css('app-title p i')).get(0), welcome: element.all(by.css('app-title p i')).get(0),
contactButton: buttons.get(0), contactButton: buttons.get(0),
crisisButton: buttons.get(1), crisisButton: buttons.get(1),
heroesButton: buttons.get(2) heroesButton: buttons.get(2)
@ -67,7 +67,7 @@ describe('NgModule', function () {
it('should welcome us', function () { it('should welcome us', function () {
const commons = getCommonsSectionStruct(); const commons = getCommonsSectionStruct();
expect(commons.subtitle.getText()).toBe('Welcome, ' + (name || 'Sherlock Holmes')); expect(commons.welcome.getText()).toBe('Welcome, ' + (name || 'Sherlock Holmes'));
}); });
}; };
} }

View File

@ -19,7 +19,7 @@
"app/contact/contact.component.3.ts", "app/contact/contact.component.3.ts",
"app/contact/contact.module.3.ts", "app/contact/contact.module.3.ts",
"app/contact/contact-routing.module.3.ts", "app/contact/contact-routing.module.3.ts",
"app/contact/highlight.directive.ts", "app/contact/contact-highlight.directive.ts",
"app/crisis/*.ts", "app/crisis/*.ts",

View File

@ -1,14 +1,19 @@
import { NgModule } from '@angular/core'; import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router'; import { Routes, RouterModule } from '@angular/router';
export const routes: Routes = [ import { ContactModule } from './contact/contact.module.3';
const routes: Routes = [
{ path: '', redirectTo: 'contact', pathMatch: 'full'}, { path: '', redirectTo: 'contact', pathMatch: 'full'},
{ path: 'crisis', loadChildren: 'app/crisis/crisis.module#CrisisModule' }, { path: 'crisis', loadChildren: 'app/crisis/crisis.module#CrisisModule' },
{ path: 'heroes', loadChildren: 'app/hero/hero.module.3#HeroModule' } { path: 'heroes', loadChildren: 'app/hero/hero.module.3#HeroModule' }
]; ];
@NgModule({ @NgModule({
imports: [RouterModule.forRoot(routes)], imports: [
ContactModule,
RouterModule.forRoot(routes)
],
exports: [RouterModule] exports: [RouterModule]
}) })
export class AppRoutingModule {} export class AppRoutingModule {}

View File

@ -2,18 +2,29 @@
import { NgModule } from '@angular/core'; import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router'; import { Routes, RouterModule } from '@angular/router';
export const routes: Routes = [ import { ContactModule } from './contact/contact.module';
// #docregion routes
const routes: Routes = [
{ path: '', redirectTo: 'contact', pathMatch: 'full'}, { path: '', redirectTo: 'contact', pathMatch: 'full'},
// #docregion lazy-routes // #docregion lazy-routes
{ path: 'crisis', loadChildren: 'app/crisis/crisis.module#CrisisModule' }, { path: 'crisis', loadChildren: 'app/crisis/crisis.module#CrisisModule' },
{ path: 'heroes', loadChildren: 'app/hero/hero.module#HeroModule' } { path: 'heroes', loadChildren: 'app/hero/hero.module#HeroModule' }
// #enddocregion lazy-routes // #enddocregion lazy-routes
]; ];
// #enddocregion routes
// #docregion forRoot
@NgModule({ @NgModule({
imports: [RouterModule.forRoot(routes)], // #docregion imports
imports: [
ContactModule,
// #docregion forRoot
RouterModule.forRoot(routes),
// #enddocregion forRoot
],
// #enddocregion imports
// #docregion exports
exports: [RouterModule] exports: [RouterModule]
// #enddocregion exports
}) })
export class AppRoutingModule {} export class AppRoutingModule {}
// #enddocregion forRoot

View File

@ -6,5 +6,5 @@ import { Component } from '@angular/core';
template: '<h1>{{title}}</h1>', template: '<h1>{{title}}</h1>',
}) })
export class AppComponent { export class AppComponent {
title = 'Minimal NgModule'; title = 'Angular Modules';
} }

View File

@ -11,9 +11,7 @@ import { Component } from '@angular/core';
// #enddocregion template // #enddocregion template
*/ */
// #docregion // #docregion
template: '<app-title [subtitle]="subtitle"></app-title>' template: '<app-title></app-title>'
}) })
export class AppComponent { export class AppComponent {}
subtitle = '(v1)';
}
// #enddocregion // #enddocregion

View File

@ -5,11 +5,9 @@ import { Component } from '@angular/core';
selector: 'app-root', selector: 'app-root',
// #docregion template // #docregion template
template: ` template: `
<app-title [subtitle]="subtitle"></app-title> <app-title></app-title>
<app-contact></app-contact> <app-contact></app-contact>
` `
// #enddocregion template // #enddocregion template
}) })
export class AppComponent { export class AppComponent {}
subtitle = '(v1)';
}

View File

@ -3,10 +3,8 @@ import { Component } from '@angular/core';
@Component({ @Component({
selector: 'app-root', selector: 'app-root',
template: ` template: `
<app-title [subtitle]="subtitle"></app-title> <app-title></app-title>
<app-contact></app-contact> <app-contact></app-contact>
` `
}) })
export class AppComponent { export class AppComponent {}
subtitle = '(v2)';
}

View File

@ -4,7 +4,7 @@ import { Component } from '@angular/core';
selector: 'app-root', selector: 'app-root',
// #docregion template // #docregion template
template: ` template: `
<app-title [subtitle]="subtitle"></app-title> <app-title></app-title>
<nav> <nav>
<a routerLink="contact" routerLinkActive="active">Contact</a> <a routerLink="contact" routerLinkActive="active">Contact</a>
<a routerLink="crisis" routerLinkActive="active">Crisis Center</a> <a routerLink="crisis" routerLinkActive="active">Crisis Center</a>
@ -14,6 +14,4 @@ import { Component } from '@angular/core';
` `
// #enddocregion template // #enddocregion template
}) })
export class AppComponent { export class AppComponent {}
subtitle = '(v3)';
}

View File

@ -5,7 +5,7 @@ import { Component } from '@angular/core';
@Component({ @Component({
selector: 'app-root', selector: 'app-root',
template: ` template: `
<app-title [subtitle]="subtitle"></app-title> <app-title></app-title>
<nav> <nav>
<a routerLink="contact" routerLinkActive="active">Contact</a> <a routerLink="contact" routerLinkActive="active">Contact</a>
<a routerLink="crisis" routerLinkActive="active">Crisis Center</a> <a routerLink="crisis" routerLinkActive="active">Crisis Center</a>
@ -14,6 +14,4 @@ import { Component } from '@angular/core';
<router-outlet></router-outlet> <router-outlet></router-outlet>
` `
}) })
export class AppComponent { export class AppComponent {}
subtitle = '(Final)';
}

View File

@ -1,17 +1,7 @@
// #docplaster
// #docregion
import { NgModule } from '@angular/core'; import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser'; import { BrowserModule } from '@angular/platform-browser';
import import { AppComponent } from './app.component.0';
// #enddocregion
{ AppComponent } from './app.component.0';
/*
// #docregion
{ AppComponent } from './app.component';
// #enddocregion
*/
// #docregion
@NgModule({ @NgModule({
// #docregion imports // #docregion imports

View File

@ -1,14 +1,15 @@
// #docplaster // #docplaster
// #docregion // #docregion
/* Angular Imports */
import { NgModule } from '@angular/core'; import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser'; import { BrowserModule } from '@angular/platform-browser';
import /* App Imports */
// #enddocregion // #enddocregion
{ AppComponent } from './app.component.1'; import { AppComponent } from './app.component.1';
/* /*
// #docregion // #docregion
{ AppComponent } from './app.component'; import { AppComponent } from './app.component';
// #enddocregion // #enddocregion
*/ */
// #docregion // #docregion
@ -21,12 +22,9 @@ import { FormsModule } from '@angular/forms';
import { AwesomePipe } from './contact/awesome.pipe'; import { AwesomePipe } from './contact/awesome.pipe';
import { ContactComponent } from './contact/contact.component.3'; import { ContactComponent } from './contact/contact.component.3';
// #docregion import-contact-directive
import { import {
HighlightDirective as ContactHighlightDirective ContactHighlightDirective as ContactHighlightDirective
} from './contact/highlight.directive'; } from './contact/contact-highlight.directive';
// #enddocregion import-contact-directive
@NgModule({ @NgModule({
// #docregion imports // #docregion imports

View File

@ -1,15 +1,16 @@
// #docplaster // #docplaster
// #docregion // #docregion
/* Angular Imports */
import { NgModule } from '@angular/core'; import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser'; import { BrowserModule } from '@angular/platform-browser';
import { FormsModule } from '@angular/forms';
/* App Root */ /* App Imports */
import
// #enddocregion // #enddocregion
{ AppComponent } from './app.component.1b'; import { AppComponent } from './app.component.1b';
/* /*
// #docregion // #docregion
{ AppComponent } from './app.component'; import { AppComponent } from './app.component';
// #enddocregion // #enddocregion
*/ */
// #docregion // #docregion
@ -18,25 +19,17 @@ import { TitleComponent } from './title.component';
import { UserService } from './user.service'; import { UserService } from './user.service';
/* Contact Imports */ /* Contact Imports */
import
// #enddocregion // #enddocregion
{ ContactComponent } from './contact/contact.component.3'; import { ContactComponent } from './contact/contact.component.3';
/* /*
// #docregion // #docregion
{ ContactComponent } from './contact/contact.component'; import { ContactComponent } from './contact/contact.component';
// #enddocregion // #enddocregion
*/ */
// #docregion // #docregion
import { ContactService } from './contact/contact.service';
import { AwesomePipe } from './contact/awesome.pipe'; import { AwesomePipe } from './contact/awesome.pipe';
import { ContactService } from './contact/contact.service';
// #docregion import-alias import { ContactHighlightDirective } from './contact/contact-highlight.directive';
import {
HighlightDirective as ContactHighlightDirective
} from './contact/highlight.directive';
// #enddocregion import-alias
import { FormsModule } from '@angular/forms';
@NgModule({ @NgModule({
imports: [ BrowserModule, FormsModule ], imports: [ BrowserModule, FormsModule ],

View File

@ -1,15 +1,15 @@
// #docplaster // #docplaster
// #docregion // #docregion
/* Angular Imports */
import { NgModule } from '@angular/core'; import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser'; import { BrowserModule } from '@angular/platform-browser';
/* App Root */ /* App Imports */
import
// #enddocregion // #enddocregion
{ AppComponent } from './app.component.2'; import { AppComponent } from './app.component.2';
/* /*
// #docregion // #docregion
{ AppComponent } from './app.component'; import { AppComponent } from './app.component';
// #enddocregion // #enddocregion
*/ */
// #docregion // #docregion
@ -18,12 +18,11 @@ import { TitleComponent } from './title.component';
import { UserService } from './user.service'; import { UserService } from './user.service';
/* Contact Imports */ /* Contact Imports */
import
// #enddocregion // #enddocregion
{ ContactModule } from './contact/contact.module.2'; import { ContactModule } from './contact/contact.module.2';
/* /*
// #docregion // #docregion
{ ContactModule } from './contact/contact.module'; import { ContactModule } from './contact/contact.module';
// #enddocregion // #enddocregion
*/ */
// #docregion // #docregion

View File

@ -1,25 +1,36 @@
// #docplaster // #docplaster
// #docregion // #docregion
/* Angular Imports */
import { NgModule } from '@angular/core'; import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser'; import { BrowserModule } from '@angular/platform-browser';
/* App Root */ /* App Imports */
// #enddocregion
import { AppComponent } from './app.component.3'; import { AppComponent } from './app.component.3';
/*
// #docregion
import { AppComponent } from './app.component';
// #enddocregion
*/
// #docregion
import { HighlightDirective } from './highlight.directive'; import { HighlightDirective } from './highlight.directive';
import { TitleComponent } from './title.component'; import { TitleComponent } from './title.component';
import { UserService } from './user.service'; import { UserService } from './user.service';
/* Feature Modules */
import { ContactModule } from './contact/contact.module.3';
/* Routing Module */ /* Routing Module */
// #enddocregion
import { AppRoutingModule } from './app-routing.module.3'; import { AppRoutingModule } from './app-routing.module.3';
/*
// #docregion
import { AppRoutingModule } from './app-routing.module';
// #enddocregion
*/
// #docregion
@NgModule({ @NgModule({
// #docregion imports // #docregion imports
imports: [ imports: [
BrowserModule, BrowserModule,
ContactModule,
AppRoutingModule AppRoutingModule
], ],
// #enddocregion imports // #enddocregion imports

View File

@ -1,14 +1,14 @@
// #docplaster // #docplaster
// #docregion // #docregion
// #docregion v4 // #docregion v4
/* Angular Imports */
import { NgModule } from '@angular/core'; import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser'; import { BrowserModule } from '@angular/platform-browser';
/* App Root */ /* App Imports */
import { AppComponent } from './app.component'; import { AppComponent } from './app.component';
/* Feature Modules */ /* Core Modules */
import { ContactModule } from './contact/contact.module';
import { CoreModule } from './core/core.module'; import { CoreModule } from './core/core.module';
/* Routing Module */ /* Routing Module */
@ -18,7 +18,6 @@ import { AppRoutingModule } from './app-routing.module';
// #docregion import-for-root // #docregion import-for-root
imports: [ imports: [
BrowserModule, BrowserModule,
ContactModule,
// #enddocregion v4 // #enddocregion v4
// #enddocregion import-for-root // #enddocregion import-for-root
/* /*

View File

@ -1,4 +1,4 @@
/* tslint:disable */ // #docplaster
// Same directive name and selector as // Same directive name and selector as
// HighlightDirective in parent AppModule // HighlightDirective in parent AppModule
// It selects for both input boxes and 'highlight' attr // It selects for both input boxes and 'highlight' attr
@ -7,12 +7,14 @@
// #docregion // #docregion
import { Directive, ElementRef } from '@angular/core'; import { Directive, ElementRef } from '@angular/core';
// Highlight the host element or any InputElement in blue
@Directive({ selector: '[highlight], input' }) @Directive({ selector: '[highlight], input' })
/** Highlight the attached element or an InputElement in blue */ export class ContactHighlightDirective {
export class HighlightDirective {
constructor(el: ElementRef) { constructor(el: ElementRef) {
el.nativeElement.style.backgroundColor = 'powderblue'; el.nativeElement.style.backgroundColor = 'powderblue';
console.log( // #enddocregion
`* Contact highlight called for ${el.nativeElement.tagName}`); console.log(`* Contact highlight called for ${el.nativeElement.tagName}`);
// #docregion
} }
} }
// #enddocregion

View File

@ -3,10 +3,12 @@ import { RouterModule } from '@angular/router';
import { ContactComponent } from './contact.component.3'; import { ContactComponent } from './contact.component.3';
@NgModule({ const routes = [
imports: [RouterModule.forChild([
{ path: 'contact', component: ContactComponent} { path: 'contact', component: ContactComponent}
])], ];
@NgModule({
imports: [ RouterModule.forChild(routes) ],
exports: [ RouterModule ] exports: [ RouterModule ]
}) })
export class ContactRoutingModule {} export class ContactRoutingModule {}

View File

@ -4,10 +4,12 @@ import { RouterModule } from '@angular/router';
import { ContactComponent } from './contact.component'; import { ContactComponent } from './contact.component';
// #docregion routing // #docregion routing
@NgModule({ const routes = [
imports: [RouterModule.forChild([
{ path: 'contact', component: ContactComponent} { path: 'contact', component: ContactComponent}
])], ];
@NgModule({
imports: [ RouterModule.forChild(routes) ],
exports: [ RouterModule ] exports: [ RouterModule ]
}) })
export class ContactRoutingModule {} export class ContactRoutingModule {}

View File

@ -21,7 +21,7 @@ export class ContactComponent implements OnInit {
} }
ngOnInit() { ngOnInit() {
this.contactService.getContacts().then(contacts => { this.contactService.getContacts().subscribe(contacts => {
this.msg = ''; this.msg = '';
this.contacts = contacts; this.contacts = contacts;
this.contact = contacts[0]; this.contact = contacts[0];

View File

@ -27,3 +27,6 @@
margin-bottom: 20px; margin-bottom: 20px;
} }
.button-group {
padding-top: 12px;
}

View File

@ -6,18 +6,32 @@
<!-- #docregion awesome --> <!-- #docregion awesome -->
<h3 highlight>{{ contact.name | awesome }}</h3> <h3 highlight>{{ contact.name | awesome }}</h3>
<!-- #enddocregion awesome --> <!-- #enddocregion awesome -->
<div class="form-group"> <div class="form-group">
<label for="name">Name</label> <label for="name">Name</label>
<!-- #docregion ngModel -->
<input type="text" class="form-control" required <input type="text" class="form-control" required
[(ngModel)]="contact.name" [(ngModel)]="contact.name"
name="name" #name="ngModel" > name="name" #name="ngModel" >
<!-- #enddocregion ngModel -->
<div [hidden]="name.valid" class="alert alert-danger"> <div [hidden]="name.valid" class="alert alert-danger">
Name is required Name is required
</div> </div>
</div> </div>
<br>
<button type="submit" class="btn btn-default" [disabled]="!contactForm.form.valid">Save</button> <div class="button-group">
<button type="button" class="btn" (click)="next()" [disabled]="!contactForm.form.valid">Next Contact</button> <button type="submit" class="btn btn-default"
<button type="button" class="btn" (click)="newContact()">New Contact</button> [disabled]="!contactForm.form.valid">
Save</button>
<button type="button" class="btn" (click)="next()"
[disabled]="!contactForm.form.valid">
Next Contact</button>
<button type="button" class="btn" (click)="newContact()">
New Contact</button>
</div>
</form> </form>
<!-- #enddocregion --> <!-- #enddocregion -->

View File

@ -22,7 +22,7 @@ export class ContactComponent implements OnInit {
} }
ngOnInit() { ngOnInit() {
this.contactService.getContacts().then(contacts => { this.contactService.getContacts().subscribe(contacts => {
this.msg = ''; this.msg = '';
this.contacts = contacts; this.contacts = contacts;
this.contact = contacts[0]; this.contact = contacts[0];

View File

@ -0,0 +1,11 @@
// #docregion
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
@NgModule({
imports: [
CommonModule
],
declarations: []
})
export class ContactModule { }

View File

@ -5,24 +5,31 @@ import { CommonModule } from '@angular/common';
import { FormsModule } from '@angular/forms'; import { FormsModule } from '@angular/forms';
import { AwesomePipe } from './awesome.pipe'; import { AwesomePipe } from './awesome.pipe';
import
// #enddocregion // #enddocregion
{ ContactComponent } from './contact.component.3'; import { ContactComponent } from './contact.component.3';
/* /*
// #docregion // #docregion
{ ContactComponent } from './contact.component'; import { ContactComponent } from './contact.component';
// #enddocregion // #enddocregion
*/ */
// #docregion // #docregion
import { ContactHighlightDirective } from './contact-highlight.directive';
import { ContactService } from './contact.service'; import { ContactService } from './contact.service';
import { HighlightDirective } from './highlight.directive';
// #docregion class // #docregion class
@NgModule({ @NgModule({
imports: [ CommonModule, FormsModule ], imports: [
declarations: [ ContactComponent, HighlightDirective, AwesomePipe ], CommonModule,
FormsModule
],
declarations: [
AwesomePipe,
ContactComponent,
ContactHighlightDirective
],
// #docregion exports
exports: [ ContactComponent ], exports: [ ContactComponent ],
// #enddocregion exports
providers: [ ContactService ] providers: [ ContactService ]
}) })
export class ContactModule { } export class ContactModule { }

View File

@ -1,20 +1,42 @@
// #docplaster
// #docregion // #docregion
import { NgModule } from '@angular/core'; import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common'; import { CommonModule } from '@angular/common';
import { FormsModule } from '@angular/forms'; import { FormsModule } from '@angular/forms';
import { AwesomePipe } from './awesome.pipe'; import { AwesomePipe } from './awesome.pipe';
// #enddocregion
import { ContactComponent } from './contact.component.3'; import { ContactComponent } from './contact.component.3';
/*
// #docregion
import { ContactComponent } from './contact.component';
// #enddocregion
*/
// #docregion
import { ContactHighlightDirective } from './contact-highlight.directive';
import { ContactService } from './contact.service'; import { ContactService } from './contact.service';
import { HighlightDirective } from './highlight.directive';
// #enddocregion
import { ContactRoutingModule } from './contact-routing.module.3'; import { ContactRoutingModule } from './contact-routing.module.3';
/*
// #docregion
import { ContactRoutingModule } from './contact-routing.module';
// #enddocregion
*/
// #docregion
// #docregion class // #docregion class
@NgModule({ @NgModule({
imports: [ CommonModule, FormsModule, ContactRoutingModule ], imports: [
declarations: [ ContactComponent, HighlightDirective, AwesomePipe ], CommonModule,
FormsModule,
ContactRoutingModule
],
declarations: [
AwesomePipe,
ContactComponent,
ContactHighlightDirective
],
providers: [ ContactService ] providers: [ ContactService ]
}) })
export class ContactModule { } export class ContactModule { }

View File

@ -8,7 +8,10 @@ import { ContactRoutingModule } from './contact-routing.module';
// #docregion class // #docregion class
@NgModule({ @NgModule({
imports: [ SharedModule, ContactRoutingModule ], imports: [
SharedModule,
ContactRoutingModule
],
declarations: [ ContactComponent ], declarations: [ ContactComponent ],
providers: [ ContactService ] providers: [ ContactService ]
}) })

View File

@ -1,5 +1,10 @@
// #docplaster
// #docregion // #docregion
import { Injectable } from '@angular/core'; import { Injectable, OnDestroy } from '@angular/core';
import { Observable } from 'rxjs/Observable';
import { of } from 'rxjs/observable/of';
import { delay } from 'rxjs/operators';
export class Contact { export class Contact {
constructor(public id: number, public name: string) { } constructor(public id: number, public name: string) { }
@ -13,17 +18,21 @@ const CONTACTS: Contact[] = [
const FETCH_LATENCY = 500; const FETCH_LATENCY = 500;
/** Simulate a data service that retrieves contacts from a server */
@Injectable() @Injectable()
export class ContactService { export class ContactService implements OnDestroy {
// #enddocregion
constructor() { console.log('ContactService instance created.'); }
ngOnDestroy() { console.log('ContactService instance destroyed.'); }
getContacts() { // #docregion
return new Promise<Contact[]>(resolve => { getContacts(): Observable<Contact[]> {
setTimeout(() => { resolve(CONTACTS); }, FETCH_LATENCY); return of(CONTACTS).pipe(delay(FETCH_LATENCY));
});
} }
getContact(id: number | string) { getContact(id: number | string): Observable<Contact> {
return this.getContacts() return of(CONTACTS.find(contact => contact.id === +id))
.then(heroes => heroes.find(hero => hero.id === +id)); .pipe(delay(FETCH_LATENCY));
} }
} }
// #enddocregion

View File

@ -1,5 +1,5 @@
<!-- Exact copy from earlier app.component.html --> <!-- Exact copy from earlier app.component.html -->
<h1 highlight>{{title}} {{subtitle}}</h1> <h1 highlight>{{title}}</h1>
<p *ngIf="user"> <p *ngIf="user">
<i>Welcome, {{user}}</i> <i>Welcome, {{user}}</i>
<p> <p>

View File

@ -7,7 +7,6 @@ import { UserService } from '../core/user.service';
templateUrl: './title.component.html', templateUrl: './title.component.html',
}) })
export class TitleComponent { export class TitleComponent {
@Input() subtitle = '';
title = 'Angular Modules'; title = 'Angular Modules';
user = ''; user = '';

View File

@ -1,4 +1,5 @@
import { Component, OnInit } from '@angular/core'; import { Component } from '@angular/core';
import { Observable } from 'rxjs/Observable';
import { Crisis, import { Crisis,
CrisisService } from './crisis.service'; CrisisService } from './crisis.service';
@ -6,17 +7,15 @@ import { Crisis,
@Component({ @Component({
template: ` template: `
<h3 highlight>Crisis List</h3> <h3 highlight>Crisis List</h3>
<div *ngFor='let crisis of crisises | async'> <div *ngFor='let crisis of crises | async'>
<a routerLink="{{'../' + crisis.id}}">{{crisis.id}} - {{crisis.name}}</a> <a routerLink="{{'../' + crisis.id}}">{{crisis.id}} - {{crisis.name}}</a>
</div> </div>
` `
}) })
export class CrisisListComponent implements OnInit { export class CrisisListComponent {
crisises: Promise<Crisis[]>; crises: Observable<Crisis[]>;
constructor(private crisisService: CrisisService) { } constructor(private crisisService: CrisisService) {
this.crises = this.crisisService.getCrises();
ngOnInit() {
this.crisises = this.crisisService.getCrises();
} }
} }

View File

@ -1,4 +1,8 @@
import { Injectable } from '@angular/core'; import { Injectable, OnDestroy } from '@angular/core';
import { Observable } from 'rxjs/Observable';
import { of } from 'rxjs/observable/of';
import { delay } from 'rxjs/operators';
export class Crisis { export class Crisis {
constructor(public id: number, public name: string) { } constructor(public id: number, public name: string) { }
@ -13,18 +17,18 @@ const CRISES: Crisis[] = [
const FETCH_LATENCY = 500; const FETCH_LATENCY = 500;
/** Simulate a data service that retrieves crises from a server */
@Injectable() @Injectable()
export class CrisisService { export class CrisisService implements OnDestroy {
constructor() { console.log('CrisisService instance created.'); }
ngOnDestroy() { console.log('CrisisService instance destroyed.'); }
getCrises() { getCrises(): Observable<Crisis[]> {
return new Promise<Crisis[]>(resolve => { return of(CRISES).pipe(delay(FETCH_LATENCY));
setTimeout(() => { resolve(CRISES); }, FETCH_LATENCY);
});
} }
getCrisis(id: number | string) { getCrisis(id: number | string): Observable<Crisis> {
return this.getCrises() return of(CRISES.find(crisis => crisis.id === +id))
.then(heroes => heroes.find(hero => hero.id === +id)); .pipe(delay(FETCH_LATENCY));
} }
} }

View File

@ -26,6 +26,6 @@ export class HeroDetailComponent implements OnInit {
ngOnInit() { ngOnInit() {
let id = parseInt(this.route.snapshot.paramMap.get('id'), 10); let id = parseInt(this.route.snapshot.paramMap.get('id'), 10);
this.heroService.getHero(id).then(hero => this.hero = hero); this.heroService.getHero(id).subscribe(hero => this.hero = hero);
} }
} }

View File

@ -1,4 +1,5 @@
import { Component, OnInit } from '@angular/core'; import { Component } from '@angular/core';
import { Observable } from 'rxjs/Observable';
import { Hero, import { Hero,
HeroService } from './hero.service'; HeroService } from './hero.service';
@ -11,11 +12,9 @@ import { Hero,
</div> </div>
` `
}) })
export class HeroListComponent implements OnInit { export class HeroListComponent {
heroes: Promise<Hero[]>; heroes: Observable<Hero[]>;
constructor(private heroService: HeroService) { } constructor(private heroService: HeroService) {
ngOnInit() {
this.heroes = this.heroService.getHeroes(); this.heroes = this.heroService.getHeroes();
} }
} }

View File

@ -5,9 +5,10 @@ import { FormsModule } from '@angular/forms';
import { HeroComponent } from './hero.component.3'; import { HeroComponent } from './hero.component.3';
import { HeroDetailComponent } from './hero-detail.component'; import { HeroDetailComponent } from './hero-detail.component';
import { HeroListComponent } from './hero-list.component'; import { HeroListComponent } from './hero-list.component';
import { HighlightDirective } from './highlight.directive';
import { HeroRoutingModule } from './hero-routing.module.3'; import { HeroRoutingModule } from './hero-routing.module.3';
import { HighlightDirective } from './highlight.directive';
// #docregion class // #docregion class
@NgModule({ @NgModule({
imports: [ CommonModule, FormsModule, HeroRoutingModule ], imports: [ CommonModule, FormsModule, HeroRoutingModule ],

View File

@ -1,4 +1,8 @@
import { Injectable } from '@angular/core'; import { Injectable, OnDestroy } from '@angular/core';
import { Observable } from 'rxjs/Observable';
import { of } from 'rxjs/observable/of';
import { delay } from 'rxjs/operators';
export class Hero { export class Hero {
constructor(public id: number, public name: string) { } constructor(public id: number, public name: string) { }
@ -15,18 +19,19 @@ const HEROES: Hero[] = [
const FETCH_LATENCY = 500; const FETCH_LATENCY = 500;
/** Simulate a data service that retrieves heroes from a server */
@Injectable() @Injectable()
export class HeroService { export class HeroService implements OnDestroy {
getHeroes() { constructor() { console.log('HeroService instance created.'); }
return new Promise<Hero[]>(resolve => { ngOnDestroy() { console.log('HeroService instance destroyed.'); }
setTimeout(() => { resolve(HEROES); }, FETCH_LATENCY);
}); getHeroes(): Observable<Hero[]> {
return of(HEROES).pipe(delay(FETCH_LATENCY));
} }
getHero(id: number | string) { getHero(id: number | string): Observable<Hero> {
return this.getHeroes() return of(HEROES.find(hero => hero.id === +id))
.then(heroes => heroes.find(hero => hero.id === +id)); .pipe(delay(FETCH_LATENCY));
} }
} }

View File

@ -1,12 +1,15 @@
// #docplaster
// #docregion // #docregion
import { Directive, ElementRef } from '@angular/core'; import { Directive, ElementRef } from '@angular/core';
// Highlight the host element in gold
@Directive({ selector: '[highlight]' }) @Directive({ selector: '[highlight]' })
/** Highlight the attached element in gold */
export class HighlightDirective { export class HighlightDirective {
constructor(el: ElementRef) { constructor(el: ElementRef) {
el.nativeElement.style.backgroundColor = 'gold'; el.nativeElement.style.backgroundColor = 'gold';
console.log( // #enddocregion
`* AppRoot highlight called for ${el.nativeElement.tagName}`); console.log(`* AppRoot highlight called for ${el.nativeElement.tagName}`);
// #docregion
} }
} }
// #enddocregion

View File

@ -1,9 +1,8 @@
/* tslint:disable */
// Exact copy of contact/highlight.directive except for color and message // Exact copy of contact/highlight.directive except for color and message
import { Directive, ElementRef } from '@angular/core'; import { Directive, ElementRef } from '@angular/core';
@Directive({ selector: '[highlight], input' }) @Directive({ selector: '[highlight], input' })
/** Highlight the attached element or an InputElement in gray */ // Highlight the host element or any InputElement in gray
export class HighlightDirective { export class HighlightDirective {
constructor(el: ElementRef) { constructor(el: ElementRef) {
el.nativeElement.style.backgroundColor = 'lightgray'; el.nativeElement.style.backgroundColor = 'lightgray';

View File

@ -1,6 +1,6 @@
<!-- #docregion --> <!-- #docregion -->
<!-- #docregion v1 --> <!-- #docregion v1 -->
<h1 highlight>{{title}} {{subtitle}}</h1> <h1 highlight>{{title}}</h1>
<!-- #enddocregion v1 --> <!-- #enddocregion v1 -->
<!-- #docregion ngIf --> <!-- #docregion ngIf -->
<p *ngIf="user"> <p *ngIf="user">

View File

@ -1,18 +1,17 @@
// #docplaster // #docplaster
// #docregion // #docregion
// #docregion v1 // #docregion v1
import { Component, Input } from '@angular/core'; import { Component } from '@angular/core';
// #enddocregion v1 // #enddocregion v1
import { UserService } from './user.service'; import { UserService } from './user.service';
// #docregion v1 // #docregion v1
@Component({ @Component({
selector: 'app-title', selector: 'app-title',
templateUrl: './title.component.html', templateUrl: './title.component.html'
}) })
export class TitleComponent { export class TitleComponent {
@Input() subtitle = ''; title = 'Angular Modules';
title = 'NgModules';
// #enddocregion v1 // #enddocregion v1
user = ''; user = '';

View File

@ -409,7 +409,7 @@ function; it can only contain a single `return` statement.
The Angular [`RouterModule`](api/router/RouterModule) exports two macro static methods, `forRoot` and `forChild`, to help declare root and child routes. The Angular [`RouterModule`](api/router/RouterModule) exports two macro static methods, `forRoot` and `forChild`, to help declare root and child routes.
Review the [source code](https://github.com/angular/angular/blob/master/packages/router/src/router_module.ts#L139 "RouterModule.forRoot source code") Review the [source code](https://github.com/angular/angular/blob/master/packages/router/src/router_module.ts#L139 "RouterModule.forRoot source code")
for these methods to see how macros can simplify configuration of complex Angular modules. for these methods to see how macros can simplify configuration of complex [NgModules](guide/ngmodule).
### Metadata rewriting ### Metadata rewriting

View File

@ -160,7 +160,7 @@ Providing the `UserService` with an Angular module is a good choice.
<div class="l-sub-section"> <div class="l-sub-section">
To be precise, Angular module providers are registered with the root injector To be precise, Angular module providers are registered with the root injector
_unless the module is_ [lazy loaded](guide/ngmodule#lazy-load). _unless the module is_ [lazy loaded](guide/ngmodule#lazy-load-DI).
In this sample, all modules are _eagerly loaded_ when the application starts, In this sample, all modules are _eagerly loaded_ when the application starts,
so all module providers are registered with the app's root injector. so all module providers are registered with the app's root injector.

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -225,17 +225,17 @@
{ {
"title": "NgModules", "title": "NgModules",
"tooltip": "Learn how to use NgModules to make your apps efficient.", "tooltip": "Modularize your app with NgModules.",
"children": [ "children": [
{ {
"url": "guide/ngmodule", "url": "guide/ngmodule",
"title": "NgModules", "title": "NgModules",
"tooltip": "Define application modules with @NgModule." "tooltip": "Define application modules with the NgModule."
}, },
{ {
"url": "guide/ngmodule-faq", "url": "guide/ngmodule-faq",
"title": "NgModule FAQs", "title": "NgModule FAQs",
"tooltip": "Answers to frequently asked questions about @NgModule." "tooltip": "Answers to frequently asked questions about NgModules."
} }
]}, ]},