docs(architecture): move diagram up; elab on svcs; add LC Hooks links
This commit is contained in:
parent
f697e01b76
commit
bf29846f3e
|
@ -2,11 +2,15 @@
|
||||||
import {Component} from 'angular2/core';
|
import {Component} from 'angular2/core';
|
||||||
// #enddocregion import
|
// #enddocregion import
|
||||||
import {HeroListComponent} from './hero-list.component';
|
import {HeroListComponent} from './hero-list.component';
|
||||||
|
import {SalesTaxComponent} from './sales-tax.component';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'my-app',
|
selector: 'my-app',
|
||||||
template: '<hero-list></hero-list>',
|
template: `
|
||||||
directives: [HeroListComponent]
|
<hero-list></hero-list>
|
||||||
|
<sales-tax></sales-tax>
|
||||||
|
`,
|
||||||
|
directives: [HeroListComponent, SalesTaxComponent]
|
||||||
})
|
})
|
||||||
// #docregion export
|
// #docregion export
|
||||||
export class AppComponent { }
|
export class AppComponent { }
|
||||||
|
|
|
@ -1,18 +1,21 @@
|
||||||
import {Injectable} from 'angular2/core';
|
import {Injectable, Type} from 'angular2/core';
|
||||||
import {Logger} from './logger.service';
|
import {Logger} from './logger.service';
|
||||||
import {Hero} from './hero';
|
import {Hero} from './hero';
|
||||||
|
|
||||||
|
const HEROES = [
|
||||||
|
new Hero('Windstorm', 'Weather mastery'),
|
||||||
|
new Hero('Mr. Nice', 'Killing them with kindness'),
|
||||||
|
new Hero('Magneta', 'Manipulates metalic objects')
|
||||||
|
];
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class BackendService {
|
export class BackendService {
|
||||||
constructor(private _logger: Logger) {}
|
constructor(private _logger: Logger) {}
|
||||||
|
|
||||||
getAll<T>(type: {new(...args:any[]): any }) : any[]{
|
getAll(type:Type) : PromiseLike<any[]>{
|
||||||
if (type === Hero) {
|
if (type === Hero) {
|
||||||
// TODO get from the database and return as a promise
|
// TODO get from the database
|
||||||
return [
|
return Promise.resolve<Hero[]>(HEROES);
|
||||||
new Hero('Windstorm', 'Weather mastery'),
|
|
||||||
new Hero('Mr. Nice', 'Killing them with kindness'),
|
|
||||||
new Hero('Magneta', 'Manipulates metalic objects')];
|
|
||||||
}
|
}
|
||||||
let err = new Error('Cannot get object of this type');
|
let err = new Error('Cannot get object of this type');
|
||||||
this._logger.error(err);
|
this._logger.error(err);
|
||||||
|
|
|
@ -7,7 +7,5 @@ import {BackendService} from './backend.service';
|
||||||
import {Logger} from './logger.service';
|
import {Logger} from './logger.service';
|
||||||
|
|
||||||
// #docregion bootstrap
|
// #docregion bootstrap
|
||||||
bootstrap(AppComponent, [
|
bootstrap(AppComponent, [BackendService, HeroService, Logger]);
|
||||||
BackendService, HeroService, Logger
|
|
||||||
]);
|
|
||||||
// #enddocregion bootstrap
|
// #enddocregion bootstrap
|
||||||
|
|
|
@ -1,9 +1,8 @@
|
||||||
// #docplaster
|
// #docplaster
|
||||||
|
import {Component, OnInit} from 'angular2/core';
|
||||||
import {Component} from 'angular2/core';
|
|
||||||
import {Hero} from './hero';
|
import {Hero} from './hero';
|
||||||
import {HeroDetailComponent} from './hero-detail.component';
|
import {HeroDetailComponent} from './hero-detail.component';
|
||||||
import {HeroService} from './hero.service'
|
import {HeroService} from './hero.service';
|
||||||
|
|
||||||
// #docregion metadata
|
// #docregion metadata
|
||||||
// #docregion providers
|
// #docregion providers
|
||||||
|
@ -23,15 +22,18 @@ export class HeroesComponent { ... }
|
||||||
// #enddocregion metadata, providers
|
// #enddocregion metadata, providers
|
||||||
*/
|
*/
|
||||||
// #docregion class
|
// #docregion class
|
||||||
export class HeroListComponent {
|
export class HeroListComponent implements OnInit {
|
||||||
// #docregion ctor
|
// #docregion ctor
|
||||||
constructor(service: HeroService) {
|
constructor(private _service: HeroService){ }
|
||||||
this.heroes = service.getHeroes();
|
|
||||||
}
|
|
||||||
// #enddocregion ctor
|
// #enddocregion ctor
|
||||||
|
|
||||||
heroes:Hero[];
|
heroes:Hero[];
|
||||||
selectedHero: Hero;
|
selectedHero: Hero;
|
||||||
|
|
||||||
|
ngOnInit(){
|
||||||
|
this.heroes = this._service.getHeroes();
|
||||||
|
}
|
||||||
|
|
||||||
selectHero(hero: Hero) { this.selectedHero = hero; }
|
selectHero(hero: Hero) { this.selectedHero = hero; }
|
||||||
}
|
}
|
||||||
// #enddocregion class
|
// #enddocregion class
|
||||||
|
|
|
@ -3,16 +3,23 @@ import {Hero} from './hero';
|
||||||
import {BackendService} from './backend.service';
|
import {BackendService} from './backend.service';
|
||||||
import {Logger} from './logger.service';
|
import {Logger} from './logger.service';
|
||||||
|
|
||||||
// #docregion class
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
|
// #docregion class
|
||||||
export class HeroService {
|
export class HeroService {
|
||||||
constructor(private _backend: BackendService, private _logger:Logger){}
|
// #docregion ctor
|
||||||
|
constructor(
|
||||||
|
private _backend: BackendService,
|
||||||
|
private _logger: Logger) { }
|
||||||
|
// #enddocregion ctor
|
||||||
|
|
||||||
|
private _heroes:Hero[] = [];
|
||||||
|
|
||||||
getHeroes() {
|
getHeroes() {
|
||||||
// TODO return as a promise
|
this._backend.getAll(Hero).then( (heroes:Hero[]) => {
|
||||||
let heroes = <Hero[]> this._backend.getAll(Hero);
|
this._logger.log(`Fetched ${heroes.length} heroes.`);
|
||||||
this._logger.log(`Got ${heroes.length} heroes from the server.`);
|
this._heroes.push(...heroes); // fill cache
|
||||||
return heroes;
|
});
|
||||||
|
return this._heroes;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// #enddocregion class
|
// #enddocregion class
|
|
@ -1,8 +1,11 @@
|
||||||
|
// #docregion
|
||||||
import {Injectable} from 'angular2/core';
|
import {Injectable} from 'angular2/core';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
|
// #docregion class
|
||||||
export class Logger {
|
export class Logger {
|
||||||
log(msg: any) { console.log(msg); }
|
log(msg: any) { console.log(msg); }
|
||||||
error(msg: any) { console.error(msg); }
|
error(msg: any) { console.error(msg); }
|
||||||
warn(msg: any) { console.warn(msg); }
|
warn(msg: any) { console.warn(msg); }
|
||||||
}
|
}
|
||||||
|
// #enddocregion class
|
|
@ -0,0 +1,41 @@
|
||||||
|
// #docplaster
|
||||||
|
// #docregion
|
||||||
|
import {Component} from 'angular2/core';
|
||||||
|
import {SalesTaxService} from './sales-tax.service';
|
||||||
|
import {TaxRateService} from './tax-rate.service';
|
||||||
|
|
||||||
|
// #docregion metadata
|
||||||
|
// #docregion providers
|
||||||
|
@Component({
|
||||||
|
// #enddocregion providers
|
||||||
|
selector: 'sales-tax',
|
||||||
|
template: `
|
||||||
|
<h2>Sales Tax Calculator</h2>
|
||||||
|
Amount: <input #amountBox (change)="0">
|
||||||
|
|
||||||
|
<div *ngIf=amountBox.value>
|
||||||
|
The sales tax is
|
||||||
|
{{ getTax(amountBox.value) | currency:'USD':true:'1.2-2' }}
|
||||||
|
</div>
|
||||||
|
`,
|
||||||
|
// #docregion providers
|
||||||
|
providers: [SalesTaxService, TaxRateService]
|
||||||
|
})
|
||||||
|
// #enddocregion providers
|
||||||
|
// #enddocregion metadata
|
||||||
|
/*
|
||||||
|
// #docregion metadata, providers
|
||||||
|
export class SalesTaxComponent { ... }
|
||||||
|
// #enddocregion metadata, providers
|
||||||
|
*/
|
||||||
|
// #docregion class
|
||||||
|
export class SalesTaxComponent {
|
||||||
|
// #docregion ctor
|
||||||
|
constructor(private _salesTaxService: SalesTaxService) { }
|
||||||
|
// #enddocregion ctor
|
||||||
|
|
||||||
|
getTax(value:string | number){
|
||||||
|
return this._salesTaxService.getVAT(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// #enddocregion class
|
|
@ -0,0 +1,19 @@
|
||||||
|
// #docregion
|
||||||
|
import {Injectable, Inject} from 'angular2/core';
|
||||||
|
import {TaxRateService} from './tax-rate.service';
|
||||||
|
|
||||||
|
// #docregion class
|
||||||
|
@Injectable()
|
||||||
|
export class SalesTaxService {
|
||||||
|
constructor(private _rateService: TaxRateService) { }
|
||||||
|
getVAT(value:string | number){
|
||||||
|
let amount:number;
|
||||||
|
if (typeof value === "string"){
|
||||||
|
amount = parseFloat(value);
|
||||||
|
} else {
|
||||||
|
amount = value;
|
||||||
|
}
|
||||||
|
return (amount || 0) * this._rateService.getRate('VAT');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// #enddocregion class
|
|
@ -0,0 +1,9 @@
|
||||||
|
// #docregion
|
||||||
|
import {Injectable} from 'angular2/core';
|
||||||
|
|
||||||
|
// #docregion class
|
||||||
|
@Injectable()
|
||||||
|
export class TaxRateService {
|
||||||
|
getRate(rateName:string){return 0.10;} // always 10% everywhere
|
||||||
|
}
|
||||||
|
// #enddocregion class
|
|
@ -14,14 +14,13 @@ include ../../../../_includes/_util-fns
|
||||||
|
|
||||||
<!-- figure img(src="/resources/images/devguide/architecture/airplane.png" alt="Us" align="left" style="width:200px; margin-left:-40px;margin-right:10px" ) -->
|
<!-- figure img(src="/resources/images/devguide/architecture/airplane.png" alt="Us" align="left" style="width:200px; margin-left:-40px;margin-right:10px" ) -->
|
||||||
:marked
|
:marked
|
||||||
Of course there is more to it than this.
|
Of course there is more to it than this. We'll learn the details when we dive into the guide chapters.
|
||||||
We're cruising at high altitude in this overview.
|
Let's get the big picture first.
|
||||||
We're looking for landmarks. We should expect the object below to be fuzzy and obscured by occasional clouds.
|
|
||||||
Details become more clear and precise when we land in the chapters themselves.
|
|
||||||
<br clear="all">
|
|
||||||
|
|
||||||
|
figure
|
||||||
|
img(src="/resources/images/devguide/architecture/overview2.png" alt="overview" style="margin-left:-40px;" width="700")
|
||||||
:marked
|
:marked
|
||||||
An Angular 2 application rests on eight main building blocks:
|
The architecture diagram identifies the eight main building blocks of an Angular 2 application:
|
||||||
1. [Module](#module)
|
1. [Module](#module)
|
||||||
1. [Component](#component)
|
1. [Component](#component)
|
||||||
1. [Template](#template)
|
1. [Template](#template)
|
||||||
|
@ -31,9 +30,6 @@ include ../../../../_includes/_util-fns
|
||||||
1. [Directive](#directive)
|
1. [Directive](#directive)
|
||||||
1. [Dependency Injection](#dependency-injection)
|
1. [Dependency Injection](#dependency-injection)
|
||||||
|
|
||||||
figure
|
|
||||||
img(src="/resources/images/devguide/architecture/overview2.png" alt="overview" style="margin-left:-40px;" width="700")
|
|
||||||
:marked
|
|
||||||
Learn these eight and we're on our way.
|
Learn these eight and we're on our way.
|
||||||
|
|
||||||
.l-sub-section
|
.l-sub-section
|
||||||
|
@ -53,6 +49,18 @@ figure
|
||||||
A typical module is a cohesive block of code dedicated to a single purpose.
|
A typical module is a cohesive block of code dedicated to a single purpose.
|
||||||
A module **exports** something of value in that code, typically one thing such as a class.
|
A module **exports** something of value in that code, typically one thing such as a class.
|
||||||
<br clear="all"><br>
|
<br clear="all"><br>
|
||||||
|
.l-sub-section
|
||||||
|
:marked
|
||||||
|
### Modules are optional
|
||||||
|
We highly recommend modular design. TypeScript has great support for ES2015 module syntax and our chapters assume we're taking a modular
|
||||||
|
approach using that syntax. That's why we list *Module* among the basic building blocks.
|
||||||
|
|
||||||
|
Angular itself doesn't require a modular approach nor this particular syntax. Don't use it if you don't want it.
|
||||||
|
Each chapter has plenty to offer after you steer clear of the `import` and `export` statements.
|
||||||
|
|
||||||
|
Find setup and organization clues in the JavaScript track (select it from the combobox at the top of this page)
|
||||||
|
which demonstrates Angular 2 development with plain old JavaScript and no module system.
|
||||||
|
:marked
|
||||||
Perhaps the first module we meet is a module that exports a *component* class.
|
Perhaps the first module we meet is a module that exports a *component* class.
|
||||||
The component is one of the basic Angular blocks, we write a lot of them,
|
The component is one of the basic Angular blocks, we write a lot of them,
|
||||||
and we'll talk about components in the next segment. For the moment it is enough to know that a
|
and we'll talk about components in the next segment. For the moment it is enough to know that a
|
||||||
|
@ -144,7 +152,7 @@ figure
|
||||||
+makeExample('architecture/ts/app/hero-list.component.ts', 'class', 'app/hero-list.component.ts')
|
+makeExample('architecture/ts/app/hero-list.component.ts', 'class', 'app/hero-list.component.ts')
|
||||||
:marked
|
:marked
|
||||||
Angular creates, updates, and destroys components as the user moves through the application.
|
Angular creates, updates, and destroys components as the user moves through the application.
|
||||||
The developer can take action at each moment in this lifecycle through optional [Lifecycle Hooks](#).
|
The developer can take action at each moment in this lifecycle through optional [Lifecycle Hooks](lifecycle-hooks.html).
|
||||||
.l-sub-section
|
.l-sub-section
|
||||||
:marked
|
:marked
|
||||||
We're not showing those hooks in this example
|
We're not showing those hooks in this example
|
||||||
|
@ -233,7 +241,7 @@ code-example(language="html").
|
||||||
:marked
|
:marked
|
||||||
>Angular inserts an instance of the `HeroListComponent` view between those tags.
|
>Angular inserts an instance of the `HeroListComponent` view between those tags.
|
||||||
|
|
||||||
* `templateUrl` - the address of this component's template which we showed [above](#the-template).
|
* `templateUrl` - the address of this component's template which we showed [above](#template).
|
||||||
|
|
||||||
* `directives` - an array of the Components or Directives that *this* template requires.
|
* `directives` - an array of the Components or Directives that *this* template requires.
|
||||||
We saw in the last line of our template that we expect Angular to insert a `HeroDetailComponent`
|
We saw in the last line of our template that we expect Angular to insert a `HeroDetailComponent`
|
||||||
|
@ -387,13 +395,23 @@ figure
|
||||||
* tax calculator
|
* tax calculator
|
||||||
* application configuration
|
* application configuration
|
||||||
|
|
||||||
There is nothing specifically "Angular" about services. Angular itself has no definition of a "service".
|
There is nothing specifically *Angular* about services. Angular itself has no definition of a *service*.
|
||||||
There is no service base class, no place to register a "service".
|
There is no *ServiceBase* class.
|
||||||
|
|
||||||
Yet services are fundamental to any Angular application. Our components are big consumers of services.
|
Yet services are fundamental to any Angular application.
|
||||||
|
|
||||||
We prefer our component classes lean. Our components don't fetch data from the server,
|
Here's an example of a service class that logs to the browser console
|
||||||
they don't validate user input, they don't log directly to the console. They delegate such tasks to services.
|
+makeExample('architecture/ts/app/logger.service.ts', 'class', 'app/logger.service.ts (class only)')(format=".")
|
||||||
|
:marked
|
||||||
|
Here's a `HeroServce` that fetches heroes and returns them in a resolved [promise](http://www.html5rocks.com/en/tutorials/es6/promises/).
|
||||||
|
The `HeroService` depends on the `LoggerService` and another `BackendService` that handles the server communication grunt work.
|
||||||
|
+makeExample('architecture/ts/app/hero.service.ts', 'class', 'app/hero.service.ts (class only)')(format=".")
|
||||||
|
:marked
|
||||||
|
Services are everywhere.
|
||||||
|
|
||||||
|
Our components are big consumers of services. They depend upon services to handle most chores.
|
||||||
|
They don't fetch data from the server, they don't validate user input, they don't log directly to the console.
|
||||||
|
They delegate such tasks to services.
|
||||||
|
|
||||||
A component's job is to enable the user experience and nothing more. It mediates between the view (rendered by the template)
|
A component's job is to enable the user experience and nothing more. It mediates between the view (rendered by the template)
|
||||||
and the application logic (which often includes some notion of a "model"). A good component presents
|
and the application logic (which often includes some notion of a "model"). A good component presents
|
||||||
|
@ -499,7 +517,7 @@ figure
|
||||||
when to update the screen.
|
when to update the screen.
|
||||||
Learn how it uses **zones** to intercept asynchronous activity and run its change detection strategies.
|
Learn how it uses **zones** to intercept asynchronous activity and run its change detection strategies.
|
||||||
|
|
||||||
>**Component Router** - With the Component Router service, users can navigate a multi-screen application
|
>**[Component Router](router.html)** - With the Component Router service, users can navigate a multi-screen application
|
||||||
in a familiar web browsing style using URLs.
|
in a familiar web browsing style using URLs.
|
||||||
|
|
||||||
>**Events** - The DOM raises events. So can components and services. Angular offers mechanisms for
|
>**Events** - The DOM raises events. So can components and services. Angular offers mechanisms for
|
||||||
|
@ -509,7 +527,7 @@ figure
|
||||||
|
|
||||||
>**HTTP** - Communicate with a server to get data, save data, and invoke server-side actions with this Angular HTTP client.
|
>**HTTP** - Communicate with a server to get data, save data, and invoke server-side actions with this Angular HTTP client.
|
||||||
|
|
||||||
>**Lifecycle Hooks** - We can tap into key moments in the lifetime of a component, from its creation to its destruction,
|
>**[Lifecycle Hooks](lifecycle-hooks.html)** - We can tap into key moments in the lifetime of a component, from its creation to its destruction,
|
||||||
by implementing the "Lifecycle Hook" interfaces.
|
by implementing the "Lifecycle Hook" interfaces.
|
||||||
|
|
||||||
>**[Pipes](pipes.html)** - Services that transform values for display.
|
>**[Pipes](pipes.html)** - Services that transform values for display.
|
||||||
|
|
|
@ -376,6 +376,7 @@
|
||||||
* `ngAfterViewChecked` - after every check of a component's view(s)
|
* `ngAfterViewChecked` - after every check of a component's view(s)
|
||||||
* `ngOnDestroy` - just before the directive is destroyed.
|
* `ngOnDestroy` - just before the directive is destroyed.
|
||||||
|
|
||||||
|
Learn more in the [Lifecycle Hooks](lifecycle-hooks.html) chapter.
|
||||||
.l-main-section
|
.l-main-section
|
||||||
<a id="M"></a>
|
<a id="M"></a>
|
||||||
:marked
|
:marked
|
||||||
|
|
|
@ -815,7 +815,7 @@ code-example(format="").
|
||||||
|
|
||||||
<a id="lifecycle-hooks"></a>
|
<a id="lifecycle-hooks"></a>
|
||||||
### Router Lifecycle Hooks
|
### Router Lifecycle Hooks
|
||||||
Angular components have their own lifecycle hooks. Angular calls the methods of the
|
Angular components have their own [lifecycle hooks](lifecycle-hooks.html). Angular calls the methods of the
|
||||||
[OnInit](../api/core/OnInit-interface.html) and [OnDestroy]((../api/core/OnDestroy-interface.html)
|
[OnInit](../api/core/OnInit-interface.html) and [OnDestroy]((../api/core/OnDestroy-interface.html)
|
||||||
interfaces when it creates and destroys components.
|
interfaces when it creates and destroys components.
|
||||||
|
|
||||||
|
|
|
@ -126,7 +126,7 @@ figure.image-display
|
||||||
|
|
||||||
:marked
|
:marked
|
||||||
We also log when a component is created or destroyed
|
We also log when a component is created or destroyed
|
||||||
using the built-in `ngOnInit` and `ngOnDestroy` lifecycle hooks.
|
using the built-in `ngOnInit` and `ngOnDestroy` [lifecycle hooks](lifecycle-hooks.html).
|
||||||
Here it is in action:
|
Here it is in action:
|
||||||
|
|
||||||
figure.image-display
|
figure.image-display
|
||||||
|
|
Loading…
Reference in New Issue