docs(dependency-injection): added DI examples; update/expand text
closes #748
This commit is contained in:
parent
77db0755c8
commit
76a8d022a7
|
@ -0,0 +1,213 @@
|
|||
|
||||
describe('Dependency Injection Tests', function () {
|
||||
|
||||
|
||||
var expectedMsg;
|
||||
|
||||
beforeAll(function () {
|
||||
browser.get('');
|
||||
});
|
||||
|
||||
describe('Cars:', function() {
|
||||
|
||||
it('DI car displays as expected', function () {
|
||||
expectedMsg = 'DI car with 4 cylinders and Flintstone tires.';
|
||||
expect(element(by.css('#di')).getText()).toEqual(expectedMsg);
|
||||
});
|
||||
|
||||
it('No DI car displays as expected', function () {
|
||||
expectedMsg = 'No DI car with 4 cylinders and Flintstone tires.';
|
||||
expect(element(by.css('#nodi')).getText()).toEqual(expectedMsg);
|
||||
});
|
||||
|
||||
it('Injector car displays as expected', function () {
|
||||
expectedMsg = 'Injector car with 4 cylinders and Flintstone tires.';
|
||||
expect(element(by.css('#injector')).getText()).toEqual(expectedMsg);
|
||||
});
|
||||
|
||||
it('Factory car displays as expected', function () {
|
||||
expectedMsg = 'Factory car with 4 cylinders and Flintstone tires.';
|
||||
expect(element(by.css('#factory')).getText()).toEqual(expectedMsg);
|
||||
});
|
||||
|
||||
it('Simple car displays as expected', function () {
|
||||
expectedMsg = 'Simple car with 4 cylinders and Flintstone tires.';
|
||||
expect(element(by.css('#simple')).getText()).toEqual(expectedMsg);
|
||||
});
|
||||
|
||||
it('Super car displays as expected', function () {
|
||||
expectedMsg = 'Super car with 12 cylinders and Flintstone tires.';
|
||||
expect(element(by.css('#super')).getText()).toEqual(expectedMsg);
|
||||
});
|
||||
|
||||
it('Test car displays as expected', function () {
|
||||
expectedMsg = 'Test car with 8 cylinders and YokoGoodStone tires.';
|
||||
expect(element(by.css('#test')).getText()).toEqual(expectedMsg);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Other Injections:', function() {
|
||||
it('DI car displays as expected', function () {
|
||||
expectedMsg = 'DI car with 4 cylinders and Flintstone tires.';
|
||||
expect(element(by.css('#car')).getText()).toEqual(expectedMsg);
|
||||
});
|
||||
|
||||
it('Hero displays as expected', function () {
|
||||
expectedMsg = 'Mr. Nice';
|
||||
expect(element(by.css('#hero')).getText()).toEqual(expectedMsg);
|
||||
});
|
||||
|
||||
it('Optional injection displays as expected', function () {
|
||||
expectedMsg = 'R.O.U.S.\'s? I don\'t think they exist!';
|
||||
expect(element(by.css('#rodent')).getText()).toEqual(expectedMsg);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Tests:', function() {
|
||||
|
||||
it('Tests display as expected', function () {
|
||||
expectedMsg = /Tests passed/;
|
||||
expect(element(by.css('#tests')).getText()).toMatch(expectedMsg);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('Provider variations:', function() {
|
||||
|
||||
it('P1 (class) displays as expected', function () {
|
||||
expectedMsg = 'Hello from logger provided with Logger class';
|
||||
expect(element(by.css('#p1')).getText()).toEqual(expectedMsg);
|
||||
});
|
||||
|
||||
it('P2 (Provider) displays as expected', function () {
|
||||
expectedMsg = 'Hello from logger provided with Provider class and useClass';
|
||||
expect(element(by.css('#p2')).getText()).toEqual(expectedMsg);
|
||||
});
|
||||
|
||||
it('P3 (provide) displays as expected', function () {
|
||||
expectedMsg = 'Hello from logger provided with useClass';
|
||||
expect(element(by.css('#p3')).getText()).toEqual(expectedMsg);
|
||||
});
|
||||
|
||||
it('P4 (useClass:BetterLogger) displays as expected', function () {
|
||||
expectedMsg = 'Hello from logger provided with useClass:BetterLogger';
|
||||
expect(element(by.css('#p4')).getText()).toEqual(expectedMsg);
|
||||
});
|
||||
|
||||
it('P5 (useClass:EvenBetterLogger - dependency) displays as expected', function () {
|
||||
expectedMsg = 'Message to Bob: Hello from EvenBetterlogger.';
|
||||
expect(element(by.css('#p5')).getText()).toEqual(expectedMsg);
|
||||
});
|
||||
|
||||
it('P6a (no alias) displays as expected', function () {
|
||||
expectedMsg = 'Hello OldLogger (but we want NewLogger)';
|
||||
expect(element(by.css('#p6a')).getText()).toEqual(expectedMsg);
|
||||
});
|
||||
|
||||
it('P6b (alias) displays as expected', function () {
|
||||
expectedMsg = 'Hello from NewLogger (via aliased OldLogger)';
|
||||
expect(element(by.css('#p6b')).getText()).toEqual(expectedMsg);
|
||||
});
|
||||
|
||||
it('P7 (useValue) displays as expected', function () {
|
||||
expectedMsg = 'Silent logger says "Shhhhh!". Provided via "useValue"';
|
||||
expect(element(by.css('#p7')).getText()).toEqual(expectedMsg);
|
||||
});
|
||||
|
||||
it('P8 (useFactory) displays as expected', function () {
|
||||
expectedMsg = 'Hero service injected successfully';
|
||||
expect(element(by.css('#p8')).getText()).toEqual(expectedMsg);
|
||||
});
|
||||
|
||||
it('P9a (string token) displays as expected', function () {
|
||||
expectedMsg = '"app.config" Application title is Dependency Injection';
|
||||
expect(element(by.css('#p9a')).getText()).toEqual(expectedMsg);
|
||||
});
|
||||
|
||||
it('P9b (OpaqueToken) displays as expected', function () {
|
||||
expectedMsg = 'APP_CONFIG Application title is Dependency Injection';
|
||||
expect(element(by.css('#p9b')).getText()).toEqual(expectedMsg);
|
||||
});
|
||||
|
||||
it('P10a (required dependency) displays as expected', function () {
|
||||
expectedMsg = 'Hello from the required logger.';
|
||||
expect(element(by.css('#p10a')).getText()).toEqual(expectedMsg);
|
||||
});
|
||||
|
||||
it('P10b (optional dependency) displays as expected', function () {
|
||||
expectedMsg = 'Optional logger was not available.';
|
||||
expect(element(by.css('#p10b')).getText()).toEqual(expectedMsg);
|
||||
})
|
||||
});
|
||||
|
||||
describe('User/Heroes:', function() {
|
||||
it('User is Bob - unauthorized', function () {
|
||||
expectedMsg = /Bob, is not authorized/;
|
||||
expect(element(by.css('#user')).getText()).toMatch(expectedMsg);
|
||||
});
|
||||
|
||||
it('should have button', function () {
|
||||
expect(element.all(by.cssContainingText('button','Next User'))
|
||||
.get(0).isDisplayed()).toBe(true, "'Next User' button should be displayed");
|
||||
});
|
||||
|
||||
it('unauthorized user should have multiple unauthorized heroes', function () {
|
||||
var heroes = element.all(by.css('#unauthorized hero-list div'));
|
||||
expect(heroes.count()).toBeGreaterThan(0);
|
||||
});
|
||||
|
||||
it('unauthorized user should have no secret heroes', function () {
|
||||
var heroes = element.all(by.css('#unauthorized hero-list div'));
|
||||
expect(heroes.count()).toBeGreaterThan(0);
|
||||
|
||||
heroes.filter(function(elem, index){
|
||||
return elem.getText().then(function(text) {
|
||||
return /secret/.test(text);
|
||||
});
|
||||
}).then(function(filteredElements) {
|
||||
//console.log("******Secret heroes count: "+filteredElements.length);
|
||||
expect(filteredElements.length).toEqual(0);
|
||||
});
|
||||
});
|
||||
|
||||
it('unauthorized user should have no authorized heros listed', function () {
|
||||
expect(element.all(by.css('#authorized hero-list div')).count()).toEqual(0);
|
||||
});
|
||||
|
||||
describe('after button click', function() {
|
||||
|
||||
beforeAll(function (done) {
|
||||
var buttonEle = element.all(by.cssContainingText('button','Next User')).get(0);
|
||||
buttonEle.click().then(done,done);
|
||||
});
|
||||
|
||||
it('User is Alice - authorized', function () {
|
||||
expectedMsg = /Alice, is authorized/;
|
||||
expect(element(by.css('#user')).getText()).toMatch(expectedMsg);
|
||||
});
|
||||
|
||||
it('authorized user should have multiple authorized heroes ', function () {
|
||||
var heroes = element.all(by.css('#authorized hero-list div'));
|
||||
expect(heroes.count()).toBeGreaterThan(0);
|
||||
});
|
||||
|
||||
it('authorized user should have secret heroes', function () {
|
||||
var heroes = element.all(by.css('#authorized hero-list div'));
|
||||
expect(heroes.count()).toBeGreaterThan(0);
|
||||
|
||||
heroes.filter(function(elem, index){
|
||||
return elem.getText().then(function(text) {
|
||||
return /secret/.test(text);
|
||||
});
|
||||
}).then(function(filteredElements) {
|
||||
//console.log("******Secret heroes count: "+filteredElements.length);
|
||||
expect(filteredElements.length).toBeGreaterThan(0);
|
||||
});
|
||||
});
|
||||
|
||||
it('authorized user should have no unauthorized heros listed', function () {
|
||||
expect(element.all(by.css('#unauthorized hero-list div')).count()).toEqual(0);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
|
@ -0,0 +1 @@
|
|||
**/*.js
|
|
@ -0,0 +1,31 @@
|
|||
// Early versions
|
||||
|
||||
// #docregion
|
||||
import {Component} from 'angular2/core';
|
||||
import {CarComponent} from './car/car.component';
|
||||
import {HeroesComponent} from './heroes/heroes.component.1';
|
||||
|
||||
@Component({
|
||||
selector: 'my-app',
|
||||
template: `
|
||||
<h1>{{title}}</h1>
|
||||
<my-car></my-car>
|
||||
<my-heroes></my-heroes>
|
||||
`,
|
||||
directives:[CarComponent, HeroesComponent]
|
||||
})
|
||||
|
||||
export class AppComponent {
|
||||
title = 'Dependency Injection';
|
||||
}
|
||||
// #enddocregion
|
||||
|
||||
|
||||
/*
|
||||
//#docregion ctor-di-fail
|
||||
// FAIL! Injectable `config` is not a class!
|
||||
constructor(heroService: HeroService, config: config) {
|
||||
this.title = config.title;
|
||||
}
|
||||
//#enddocregion ctor-di-fail
|
||||
*/
|
|
@ -0,0 +1,39 @@
|
|||
// #docregion
|
||||
// #docregion imports
|
||||
import {Component} from 'angular2/core';
|
||||
import {CarComponent} from './car/car.component';
|
||||
import {HeroesComponent} from './heroes/heroes.component.1';
|
||||
|
||||
import {provide, Inject} from 'angular2/core';
|
||||
import {Config, CONFIG} from './app.config';
|
||||
import {Logger} from './logger.service';
|
||||
// #enddocregion imports
|
||||
|
||||
@Component({
|
||||
selector: 'my-app',
|
||||
template: `
|
||||
<h1>{{title}}</h1>
|
||||
<my-car></my-car>
|
||||
<my-heroes></my-heroes>
|
||||
`,
|
||||
directives:[CarComponent, HeroesComponent],
|
||||
// #docregion providers
|
||||
providers: [
|
||||
Logger,
|
||||
// #docregion provider-config
|
||||
provide('app.config', {useValue: CONFIG})
|
||||
// #enddocregion provider-config
|
||||
]
|
||||
// #docregion providers
|
||||
})
|
||||
export class AppComponent {
|
||||
title:string;
|
||||
|
||||
// #docregion ctor
|
||||
constructor(@Inject('app.config') config:Config) {
|
||||
|
||||
this.title = config.title;
|
||||
}
|
||||
// #docregion ctor
|
||||
}
|
||||
// #enddocregion
|
|
@ -0,0 +1,65 @@
|
|||
// #docplaster
|
||||
// #docregion
|
||||
// #docregion imports
|
||||
import {Component, Inject, provide} from 'angular2/core';
|
||||
|
||||
import {CarComponent} from './car/car.component';
|
||||
import {HeroesComponent} from './heroes/heroes.component';
|
||||
|
||||
import {APP_CONFIG,
|
||||
Config, CONFIG} from './app.config';
|
||||
import {Logger} from './logger.service';
|
||||
|
||||
import {User, UserService} from './user.service';
|
||||
// #enddocregion imports
|
||||
import {InjectorComponent} from './injector.component';
|
||||
import {TestComponent} from './test.component';
|
||||
import {ProvidersComponent} from './providers.component';
|
||||
|
||||
@Component({
|
||||
selector: 'my-app',
|
||||
template: `
|
||||
<h1>{{title}}</h1>
|
||||
<my-car></my-car>
|
||||
<my-injectors></my-injectors>
|
||||
<my-tests></my-tests>
|
||||
<h2>User</h2>
|
||||
<p id="user">
|
||||
{{userInfo}}
|
||||
<button (click)='nextUser()'>Next User</button>
|
||||
<p>
|
||||
<my-heroes id="authorized" *ngIf="isAuthorized"></my-heroes>
|
||||
<my-heroes id="unauthorized" *ngIf="!isAuthorized"></my-heroes>
|
||||
`,
|
||||
directives:[CarComponent, HeroesComponent,
|
||||
InjectorComponent, TestComponent, ProvidersComponent],
|
||||
// #docregion providers
|
||||
providers: [
|
||||
Logger,
|
||||
UserService,
|
||||
provide(APP_CONFIG, {useValue: CONFIG})
|
||||
]
|
||||
// #enddocregion providers
|
||||
})
|
||||
export class AppComponent {
|
||||
title:string;
|
||||
|
||||
//#docregion ctor
|
||||
constructor(
|
||||
@Inject(APP_CONFIG) config:Config,
|
||||
private _userService: UserService) {
|
||||
|
||||
this.title = config.title;
|
||||
}
|
||||
// #enddocregion ctor
|
||||
|
||||
get isAuthorized() { return this.user.isAuthorized;}
|
||||
nextUser() { this._userService.getNewUser(); }
|
||||
get user() { return this._userService.user; }
|
||||
|
||||
get userInfo() {
|
||||
return `Current user, ${this.user.name}, is `+
|
||||
`${this.isAuthorized ? '' : 'not'} authorized. `;
|
||||
}
|
||||
}
|
||||
// #enddocregion
|
|
@ -0,0 +1,18 @@
|
|||
//#docregion
|
||||
// #docregion token
|
||||
import {OpaqueToken} from 'angular2/core';
|
||||
|
||||
export let APP_CONFIG = new OpaqueToken('app.config');
|
||||
// #enddocregion token
|
||||
|
||||
//#docregion config
|
||||
export interface Config {
|
||||
apiEndpoint: string,
|
||||
title: string
|
||||
}
|
||||
|
||||
export const CONFIG:Config = {
|
||||
apiEndpoint: 'api.heroes.com',
|
||||
title: 'Dependency Injection'
|
||||
};
|
||||
//#enddocregion config
|
|
@ -0,0 +1,46 @@
|
|||
// Examples with car and engine variations
|
||||
|
||||
// #docplaster
|
||||
import {Car, Engine, Tires} from './car';
|
||||
|
||||
///////// example 1 ////////////
|
||||
export function simpleCar() {
|
||||
//#docregion car-ctor-instantiation
|
||||
// Simple car with 4 cylinders and Flintstone tires.
|
||||
var car = new Car(new Engine(), new Tires());
|
||||
//#enddocregion car-ctor-instantiation
|
||||
car.description = 'Simple';
|
||||
return car;
|
||||
}
|
||||
|
||||
|
||||
///////// example 2 ////////////
|
||||
//#docregion car-ctor-instantiation-with-param
|
||||
class Engine2 {
|
||||
constructor(public cylinders: number) { }
|
||||
}
|
||||
//#enddocregion car-ctor-instantiation-with-param
|
||||
export function superCar() {
|
||||
//#docregion car-ctor-instantiation-with-param
|
||||
// Super car with 12 cylinders and Flintstone tires.
|
||||
var bigCylinders = 12;
|
||||
var car = new Car(new Engine2(bigCylinders), new Tires());
|
||||
//#enddocregion car-ctor-instantiation-with-param
|
||||
car.description = 'Super';
|
||||
return car;
|
||||
}
|
||||
|
||||
/////////// example 3 //////////
|
||||
//#docregion car-ctor-instantiation-with-mocks
|
||||
class MockEngine extends Engine { cylinders = 8; }
|
||||
class MockTires extends Tires { make = "YokoGoodStone"; }
|
||||
|
||||
//#enddocregion car-ctor-instantiation-with-mocks
|
||||
export function testCar() {
|
||||
//#docregion car-ctor-instantiation-with-mocks
|
||||
// Test car with 8 cylinders and YokoGoodStone tires.
|
||||
var car = new Car(new MockEngine(), new MockTires());
|
||||
//#enddocregion car-ctor-instantiation-with-mocks
|
||||
car.description = 'Test';
|
||||
return car;
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
// #docregion
|
||||
import {Engine, Tires, Car} from './car';
|
||||
|
||||
export class CarFactory {
|
||||
|
||||
createCar() {
|
||||
let car = new Car(this.createEngine(), this.createTires());
|
||||
car.description = 'Factory';
|
||||
return car;
|
||||
}
|
||||
|
||||
createEngine() {
|
||||
return new Engine();
|
||||
}
|
||||
|
||||
createTires() {
|
||||
return new Tires();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
// #docplaster
|
||||
//#docregion
|
||||
import { Injector } from 'angular2/core';
|
||||
|
||||
import {Car, Engine, Tires} from './car';
|
||||
import {Logger} from '../logger.service';
|
||||
|
||||
//#docregion injector
|
||||
export function useInjector() {
|
||||
var injector:Injector;
|
||||
|
||||
//#enddocregion injector
|
||||
/*
|
||||
//#docregion injector-no-new
|
||||
// Cannot 'new' an Injector like this!
|
||||
var injector = new Injector([Car, Engine, Tires, Logger]);
|
||||
//#enddocregion injector-no-new
|
||||
*/
|
||||
|
||||
//#docregion injector
|
||||
//#docregion injector-create-and-call
|
||||
injector = Injector.resolveAndCreate([Car, Engine, Tires, Logger]);
|
||||
//#docregion injector-call
|
||||
var car = injector.get(Car);
|
||||
//#enddocregion injector-call
|
||||
//#enddocregion injector-create-and-call
|
||||
car.description = 'Injector';
|
||||
|
||||
var logger = injector.get(Logger);
|
||||
logger.log('Injector car.drive() said: '+car.drive());
|
||||
|
||||
return car;
|
||||
}
|
||||
//#enddocregion injector
|
||||
|
||||
|
||||
//#enddocregion
|
|
@ -0,0 +1,24 @@
|
|||
// Car without DI
|
||||
import {Engine, Tires} from './car';
|
||||
|
||||
//#docregion car
|
||||
export class Car {
|
||||
|
||||
//#docregion car-ctor
|
||||
public engine: Engine;
|
||||
public tires: Tires;
|
||||
public description = 'No DI';
|
||||
|
||||
constructor() {
|
||||
this.engine = new Engine();
|
||||
this.tires = new Tires();
|
||||
}
|
||||
//#enddocregion car-ctor
|
||||
|
||||
// Method using the engine and tires
|
||||
drive() {
|
||||
return `${this.description} car with ` +
|
||||
`${this.engine.cylinders} cylinders and ${this.tires.make} tires.`
|
||||
}
|
||||
}
|
||||
//#enddocregion car
|
|
@ -0,0 +1,37 @@
|
|||
// #docregion
|
||||
import { Component, Injector} from 'angular2/core';
|
||||
import { Car, Engine, Tires } from './car';
|
||||
import { Car as CarNoDi } from './car-no-di';
|
||||
import { CarFactory} from './car-factory';
|
||||
|
||||
import { testCar,
|
||||
simpleCar,
|
||||
superCar } from './car-creations';
|
||||
|
||||
import { useInjector } from './car-injector';
|
||||
|
||||
|
||||
@Component({
|
||||
selector: 'my-car',
|
||||
template: `
|
||||
<h2>Cars</h2>
|
||||
<div id="di">{{car.drive()}}</div>
|
||||
<div id="nodi">{{noDiCar.drive()}}</div>
|
||||
<div id="injector">{{injectorCar.drive()}}</div>
|
||||
<div id="factory">{{factoryCar.drive()}}</div>
|
||||
<div id="simple">{{simpleCar.drive()}}</div>
|
||||
<div id="super">{{superCar.drive()}}</div>
|
||||
<div id="test">{{testCar.drive()}}</div>
|
||||
`,
|
||||
providers: [Car, Engine, Tires]
|
||||
})
|
||||
export class CarComponent {
|
||||
constructor(public car: Car) {}
|
||||
|
||||
factoryCar = (new CarFactory).createCar();
|
||||
injectorCar = useInjector();
|
||||
noDiCar = new CarNoDi;
|
||||
simpleCar = simpleCar();
|
||||
superCar = superCar();
|
||||
testCar = testCar();
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
// #docregion
|
||||
import {Injectable} from 'angular2/core';
|
||||
|
||||
// #docregion engine
|
||||
export class Engine {
|
||||
public cylinders = 4; // default
|
||||
}
|
||||
// #enddocregion engine
|
||||
|
||||
// #docregion tires
|
||||
export class Tires {
|
||||
public make = 'Flintstone';
|
||||
public model = 'Square';
|
||||
}
|
||||
// #enddocregion tires
|
||||
|
||||
@Injectable()
|
||||
// #docregion car
|
||||
export class Car {
|
||||
//#docregion car-ctor
|
||||
public description = 'DI';
|
||||
|
||||
constructor(public engine: Engine, public tires: Tires) { }
|
||||
// #enddocregion car-ctor
|
||||
|
||||
// Method using the engine and tires
|
||||
drive() {
|
||||
return `${this.description} car with ` +
|
||||
`${this.engine.cylinders} cylinders and ${this.tires.make} tires.`
|
||||
}
|
||||
}
|
||||
// #enddocregion car
|
|
@ -0,0 +1,16 @@
|
|||
// #docregion
|
||||
import { Component } from 'angular2/core';
|
||||
import { Hero } from './hero';
|
||||
import { HEROES } from './mock-heroes';
|
||||
|
||||
@Component({
|
||||
selector: 'hero-list',
|
||||
template: `
|
||||
<div *ngFor="#hero of heroes">
|
||||
{{hero.id}} - {{hero.name}}
|
||||
</div>
|
||||
`,
|
||||
})
|
||||
export class HeroListComponent {
|
||||
heroes = HEROES;
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
// #docregion
|
||||
import { Component } from 'angular2/core';
|
||||
import { Hero } from './hero';
|
||||
import { HeroService } from './hero.service';
|
||||
|
||||
@Component({
|
||||
selector: 'hero-list',
|
||||
template: `
|
||||
<div *ngFor="#hero of heroes">
|
||||
{{hero.id}} - {{hero.name}}
|
||||
</div>
|
||||
`,
|
||||
})
|
||||
export class HeroListComponent {
|
||||
heroes: Hero[];
|
||||
|
||||
//#docregion ctor
|
||||
constructor(heroService: HeroService) {
|
||||
this.heroes = heroService.getHeroes();
|
||||
}
|
||||
//#enddocregion ctor
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
// #docregion
|
||||
import { Component } from 'angular2/core';
|
||||
import { Hero } from './hero';
|
||||
import { HeroService } from './hero.service';
|
||||
|
||||
@Component({
|
||||
selector: 'hero-list',
|
||||
template: `
|
||||
<div *ngFor="#hero of heroes">
|
||||
{{hero.id}} - {{hero.name}}
|
||||
({{hero.isSecret ? 'secret' : 'public'}})
|
||||
</div>
|
||||
`,
|
||||
})
|
||||
export class HeroListComponent {
|
||||
heroes: Hero[];
|
||||
|
||||
//#docregion ctor-signature
|
||||
constructor(heroService: HeroService) {
|
||||
//#enddocregion ctor-signature
|
||||
this.heroes = heroService.getHeroes();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
// #docregion
|
||||
import {Hero} from './hero';
|
||||
import {HEROES} from './mock-heroes';
|
||||
|
||||
export class HeroService {
|
||||
getHeroes() { return HEROES; }
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
// #docregion
|
||||
import {Injectable} from 'angular2/core';
|
||||
import {Hero} from './hero';
|
||||
import {HEROES} from './mock-heroes';
|
||||
import {Logger} from '../logger.service';
|
||||
|
||||
@Injectable()
|
||||
export class HeroService {
|
||||
|
||||
constructor(private _logger: Logger) { }
|
||||
|
||||
getHeroes() {
|
||||
this._logger.log('Getting heroes ...')
|
||||
return HEROES;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
// #docregion
|
||||
import {provide} from 'angular2/core';
|
||||
import {HeroService} from './hero.service';
|
||||
import {Logger} from '../logger.service';
|
||||
import {UserService} from '../user.service';
|
||||
|
||||
// #docregion factory
|
||||
let heroServiceFactory = (logger: Logger, userService: UserService) => {
|
||||
return new HeroService(logger, userService.user.isAuthorized);
|
||||
}
|
||||
// #enddocregion factory
|
||||
|
||||
// #docregion provider
|
||||
export let heroServiceProvider =
|
||||
provide(HeroService, {
|
||||
useFactory: heroServiceFactory,
|
||||
deps: [Logger, UserService]
|
||||
});
|
||||
// #enddocregion provider
|
|
@ -0,0 +1,22 @@
|
|||
// #docregion
|
||||
import {Injectable} from 'angular2/core';
|
||||
import {Hero} from './hero';
|
||||
import {HEROES} from './mock-heroes';
|
||||
import {Logger} from '../logger.service';
|
||||
|
||||
@Injectable()
|
||||
export class HeroService {
|
||||
private _user:string;
|
||||
|
||||
// #docregion internals
|
||||
constructor(
|
||||
private _logger: Logger,
|
||||
private _isAuthorized: boolean) { }
|
||||
|
||||
getHeroes() {
|
||||
let auth = this._isAuthorized ? 'authorized ': 'unauthorized';
|
||||
this._logger.log(`Getting heroes for ${auth} user.`);
|
||||
return HEROES.filter(hero => this._isAuthorized || !hero.isSecret);
|
||||
}
|
||||
// #enddocregion internals
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
// #docregion
|
||||
export class Hero {
|
||||
id: number;
|
||||
name: string;
|
||||
isSecret = false;
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
// #docplaster
|
||||
// #docregion
|
||||
// #docregion v1
|
||||
import { Component } from 'angular2/core';
|
||||
import { HeroListComponent } from './hero-list.component';
|
||||
// #enddocregion v1
|
||||
import { HeroService } from './hero.service';
|
||||
// #docregion v1
|
||||
|
||||
@Component({
|
||||
selector: 'my-heroes',
|
||||
template: `
|
||||
<h2>Heroes</h2>
|
||||
<hero-list></hero-list>
|
||||
`,
|
||||
// #enddocregion v1
|
||||
// #docregion providers
|
||||
providers:[HeroService],
|
||||
// #enddocregion providers
|
||||
// #docregion v1
|
||||
directives:[HeroListComponent]
|
||||
})
|
||||
export class HeroesComponent { }
|
||||
// #enddocregion v1
|
|
@ -0,0 +1,15 @@
|
|||
// #docregion
|
||||
import { Component } from 'angular2/core';
|
||||
import { HeroListComponent } from './hero-list.component';
|
||||
import { heroServiceProvider} from './hero.service.provider';
|
||||
|
||||
@Component({
|
||||
selector: 'my-heroes',
|
||||
template: `
|
||||
<h2>Heroes</h2>
|
||||
<hero-list></hero-list>
|
||||
`,
|
||||
providers:[heroServiceProvider],
|
||||
directives:[HeroListComponent]
|
||||
})
|
||||
export class HeroesComponent { }
|
|
@ -0,0 +1,15 @@
|
|||
// #docregion
|
||||
import { Hero } from './hero';
|
||||
|
||||
export var HEROES: Hero[] = [
|
||||
{ "id": 11, isSecret: false, "name": "Mr. Nice" },
|
||||
{ "id": 12, isSecret: false, "name": "Narco" },
|
||||
{ "id": 13, isSecret: false, "name": "Bombasto" },
|
||||
{ "id": 14, isSecret: false, "name": "Celeritas" },
|
||||
{ "id": 15, isSecret: false, "name": "Magneta" },
|
||||
{ "id": 16, isSecret: false, "name": "RubberMan" },
|
||||
{ "id": 17, isSecret: false, "name": "Dynama" },
|
||||
{ "id": 18, isSecret: true, "name": "Dr IQ" },
|
||||
{ "id": 19, isSecret: true, "name": "Magma" },
|
||||
{ "id": 20, isSecret: true, "name": "Tornado" }
|
||||
];
|
|
@ -0,0 +1,46 @@
|
|||
// #docplaster
|
||||
//#docregion
|
||||
import {Component, Injector} from 'angular2/core';
|
||||
|
||||
import {Car, Engine, Tires} from './car/car';
|
||||
import {HeroService} from './heroes/hero.service';
|
||||
import {heroServiceProvider} from './heroes/hero.service.provider';
|
||||
import {Logger} from './logger.service';
|
||||
|
||||
//#docregion injector
|
||||
@Component({
|
||||
selector: 'my-injectors',
|
||||
template: `
|
||||
<h2>Other Injections</h2>
|
||||
<div id="car"> {{car.drive()}}</div>
|
||||
<div id="hero">{{hero.name}}</div>
|
||||
<div id="rodent">{{rodent}}</div>
|
||||
`,
|
||||
providers: [Car, Engine, Tires,
|
||||
heroServiceProvider, Logger]
|
||||
})
|
||||
export class InjectorComponent {
|
||||
constructor(private _injector: Injector) { }
|
||||
|
||||
car:Car = this._injector.get(Car);
|
||||
|
||||
//#docregion get-hero-service
|
||||
heroService:HeroService = this._injector.get(HeroService);
|
||||
//#enddocregion get-hero-service
|
||||
hero = this.heroService.getHeroes()[0];
|
||||
|
||||
get rodent() {
|
||||
let rous = this._injector.getOptional(ROUS);
|
||||
if (rous) {
|
||||
throw new Error('Aaaargh!')
|
||||
}
|
||||
return "R.O.U.S.'s? I don't think they exist!";
|
||||
}
|
||||
}
|
||||
//#enddocregion injector
|
||||
|
||||
/**
|
||||
* R.O.U.S. - Rodents Of Unusual Size
|
||||
* // https://www.youtube.com/watch?v=BOv5ZjAOpC8
|
||||
*/
|
||||
class ROUS { }
|
|
@ -0,0 +1,11 @@
|
|||
// #docregion
|
||||
import {Injectable} from 'angular2/core';
|
||||
|
||||
@Injectable()
|
||||
export class Logger {
|
||||
logs:string[] = []; // capture logs for testing
|
||||
log(message: string){
|
||||
this.logs.push(message);
|
||||
console.log(message);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
import {bootstrap} from 'angular2/platform/browser';
|
||||
import {AppComponent} from './app.component';
|
||||
import {HeroService} from './heroes/hero.service';
|
||||
|
||||
//#docregion bootstrap
|
||||
// Injecting services in bootstrap works but is discouraged
|
||||
bootstrap(AppComponent, [HeroService]);
|
||||
//#enddocregion bootstrap
|
|
@ -0,0 +1,9 @@
|
|||
//#docregion
|
||||
import {bootstrap} from 'angular2/platform/browser';
|
||||
import {AppComponent} from './app.component';
|
||||
import {ProvidersComponent} from './providers.component';
|
||||
|
||||
//#docregion bootstrap
|
||||
bootstrap(AppComponent);
|
||||
//#enddocregion bootstrap
|
||||
bootstrap(ProvidersComponent);
|
|
@ -0,0 +1,355 @@
|
|||
// Examples of provider arrays
|
||||
import { Component, Host, Inject, Injectable,
|
||||
provide, Provider} from 'angular2/core';
|
||||
|
||||
import { APP_CONFIG,
|
||||
Config, CONFIG } from './app.config';
|
||||
|
||||
import { HeroService} from './heroes/hero.service';
|
||||
import { heroServiceProvider } from './heroes/hero.service.provider';
|
||||
import { Logger } from './logger.service';
|
||||
import { User, UserService } from './user.service';
|
||||
|
||||
let template = '{{log}}';
|
||||
|
||||
//////////////////////////////////////////
|
||||
@Component({
|
||||
selector: 'provider-1',
|
||||
template: template,
|
||||
providers:
|
||||
//#docregion providers-1
|
||||
[Logger]
|
||||
//#enddocregion providers-1
|
||||
})
|
||||
export class ProviderComponent1 {
|
||||
log:string;
|
||||
constructor(logger: Logger) {
|
||||
logger.log('Hello from logger provided with Logger class');
|
||||
this.log = logger.logs[0];
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////
|
||||
@Component({
|
||||
selector: 'provider-2',
|
||||
template: template,
|
||||
providers:
|
||||
//#docregion providers-2
|
||||
[new Provider(Logger, {useClass: Logger})]
|
||||
//#enddocregion providers-2
|
||||
})
|
||||
export class ProviderComponent2 {
|
||||
log:string;
|
||||
constructor(logger: Logger) {
|
||||
logger.log('Hello from logger provided with Provider class and useClass');
|
||||
this.log = logger.logs[0];
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////
|
||||
@Component({
|
||||
selector: 'provider-3',
|
||||
template: template,
|
||||
providers:
|
||||
//#docregion providers-3
|
||||
[provide(Logger, {useClass: Logger})]
|
||||
//#enddocregion providers-3
|
||||
})
|
||||
export class ProviderComponent3 {
|
||||
log:string;
|
||||
constructor(logger: Logger) {
|
||||
logger.log('Hello from logger provided with useClass');
|
||||
this.log = logger.logs[0];
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////
|
||||
class BetterLogger extends Logger {}
|
||||
|
||||
@Component({
|
||||
selector: 'provider-4',
|
||||
template: template,
|
||||
providers:
|
||||
//#docregion providers-4
|
||||
[provide(Logger, {useClass: BetterLogger})]
|
||||
//#enddocregion providers-4
|
||||
})
|
||||
export class ProviderComponent4 {
|
||||
log:string;
|
||||
constructor(logger: Logger) {
|
||||
logger.log('Hello from logger provided with useClass:BetterLogger');
|
||||
this.log = logger.logs[0];
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////
|
||||
// #docregion EvenBetterLogger
|
||||
@Injectable()
|
||||
class EvenBetterLogger {
|
||||
logs:string[] = [];
|
||||
|
||||
constructor(private _userService: UserService) { }
|
||||
|
||||
log(message:string){
|
||||
message = `Message to ${this._userService.user.name}: ${message}.`;
|
||||
console.log(message);
|
||||
this.logs.push(message);
|
||||
}
|
||||
}
|
||||
// #enddocregion EvenBetterLogger
|
||||
|
||||
@Component({
|
||||
selector: 'provider-5',
|
||||
template: template,
|
||||
providers:
|
||||
//#docregion providers-5
|
||||
[
|
||||
UserService,
|
||||
provide(Logger, {useClass: EvenBetterLogger})
|
||||
]
|
||||
//#enddocregion providers-5
|
||||
})
|
||||
export class ProviderComponent5 {
|
||||
log:string;
|
||||
constructor(logger: Logger) {
|
||||
logger.log('Hello from EvenBetterlogger');
|
||||
this.log = logger.logs[0];
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////
|
||||
class NewLogger extends Logger {}
|
||||
class OldLogger {
|
||||
logs:string[] = [];
|
||||
log(message:string) {
|
||||
throw new Error('Should not call the old logger!')
|
||||
};
|
||||
}
|
||||
|
||||
@Component({
|
||||
selector: 'provider-6a',
|
||||
template: template,
|
||||
providers:
|
||||
//#docregion providers-6a
|
||||
[
|
||||
NewLogger,
|
||||
// Not aliased! Creates two instances of `NewLogger`
|
||||
provide(OldLogger, {useClass:NewLogger})
|
||||
]
|
||||
//#enddocregion providers-6a
|
||||
})
|
||||
export class ProviderComponent6a {
|
||||
log:string;
|
||||
constructor(newLogger:NewLogger, oldLogger: OldLogger) {
|
||||
if (newLogger === oldLogger){
|
||||
throw new Error('expected the two loggers to be different instances');
|
||||
}
|
||||
oldLogger.log('Hello OldLogger (but we want NewLogger)');
|
||||
// The newLogger wasn't called so no logs[]
|
||||
// display the logs of the oldLogger.
|
||||
this.log = newLogger.logs[0] || oldLogger.logs[0];
|
||||
}
|
||||
}
|
||||
|
||||
@Component({
|
||||
selector: 'provider-6b',
|
||||
template: template,
|
||||
providers:
|
||||
//#docregion providers-6b
|
||||
[
|
||||
NewLogger,
|
||||
// Alias OldLogger w/ reference to NewLogger
|
||||
provide(OldLogger, {useExisting: NewLogger})
|
||||
]
|
||||
//#enddocregion providers-6b
|
||||
})
|
||||
export class ProviderComponent6b {
|
||||
log:string;
|
||||
constructor(newLogger:NewLogger, oldLogger: OldLogger) {
|
||||
if (newLogger !== oldLogger){
|
||||
throw new Error('expected the two loggers to be the same instance');
|
||||
}
|
||||
oldLogger.log('Hello from NewLogger (via aliased OldLogger)');
|
||||
this.log = newLogger.logs[0];
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////
|
||||
// #docregion silent-logger
|
||||
// An object in the shape of the logger service
|
||||
let silentLogger = {
|
||||
logs: ['Silent logger says "Shhhhh!". Provided via "useValue"'],
|
||||
log: () => {}
|
||||
}
|
||||
// #enddocregion silent-logger
|
||||
|
||||
@Component({
|
||||
selector: 'provider-7',
|
||||
template: template,
|
||||
providers:
|
||||
//#docregion providers-7
|
||||
[provide(Logger, {useValue: silentLogger})]
|
||||
//#enddocregion providers-7
|
||||
})
|
||||
export class ProviderComponent7 {
|
||||
log:string;
|
||||
constructor(logger: Logger) {
|
||||
logger.log('Hello from logger provided with useValue');
|
||||
this.log = logger.logs[0];
|
||||
}
|
||||
}
|
||||
/////////////////
|
||||
|
||||
@Component({
|
||||
selector: 'provider-8',
|
||||
template: template,
|
||||
providers:[heroServiceProvider, Logger, UserService]
|
||||
})
|
||||
export class ProviderComponent8{
|
||||
// #docregion provider-8-ctor
|
||||
constructor(heroService: HeroService){ }
|
||||
// #enddocregion provider-8-ctor
|
||||
|
||||
// must be true else this component would have blown up at runtime
|
||||
log = 'Hero service injected successfully'
|
||||
}
|
||||
|
||||
/////////////////
|
||||
@Component({
|
||||
selector: 'provider-9a',
|
||||
template: template,
|
||||
providers:
|
||||
/*
|
||||
// #docregion providers-9a-interface
|
||||
// FAIL! Can't use interface as provider token
|
||||
[provide(Config, {useValue: CONFIG})]
|
||||
// #enddocregion providers-9a-interface
|
||||
*/
|
||||
// #docregion providers-9a
|
||||
// Use string as provider token
|
||||
[provide('app.config', {useValue: CONFIG})]
|
||||
// #enddocregion providers-9a
|
||||
})
|
||||
export class ProviderComponent9a {
|
||||
log: string;
|
||||
/*
|
||||
// #docregion provider-9a-ctor-interface
|
||||
// FAIL! Can't inject using the interface as the parameter type
|
||||
constructor(private _config: Config){ }
|
||||
// #enddocregion provider-9a-ctor-interface
|
||||
*/
|
||||
|
||||
// #docregion provider-9a-ctor
|
||||
// @Inject(token) to inject the dependency
|
||||
constructor(@Inject('app.config') private _config: Config){ }
|
||||
// #enddocregion provider-9a-ctor
|
||||
|
||||
ngOnInit() {
|
||||
this.log = '"app.config" Application title is ' + this._config.title;
|
||||
}
|
||||
}
|
||||
|
||||
@Component({
|
||||
selector: 'provider-9b',
|
||||
template: template,
|
||||
// #docregion providers-9b
|
||||
providers:[provide(APP_CONFIG, {useValue: CONFIG})]
|
||||
// #enddocregion providers-9b
|
||||
})
|
||||
export class ProviderComponent9b {
|
||||
log: string;
|
||||
// #docregion provider-9b-ctor
|
||||
constructor(@Inject(APP_CONFIG) private _config: Config){ }
|
||||
// #enddocregion provider-9b-ctor
|
||||
|
||||
ngOnInit() {
|
||||
this.log = 'APP_CONFIG Application title is ' + this._config.title;
|
||||
}
|
||||
}
|
||||
//////////////////////////////////////////
|
||||
// Normal required logger
|
||||
@Component({
|
||||
selector: 'provider-10a',
|
||||
template: template,
|
||||
//#docregion providers-logger
|
||||
providers: [Logger]
|
||||
//#enddocregion providers-logger
|
||||
})
|
||||
export class ProviderComponent10a {
|
||||
log:string;
|
||||
constructor(logger: Logger) {
|
||||
logger.log('Hello from the required logger.');
|
||||
this.log = logger.logs[0];
|
||||
}
|
||||
}
|
||||
|
||||
// Optional logger
|
||||
// #docregion import-optional
|
||||
import {Optional} from 'angular2/core';
|
||||
// #enddocregion import-optional
|
||||
|
||||
@Component({
|
||||
selector: 'provider-10b',
|
||||
template: template
|
||||
})
|
||||
export class ProviderComponent10b {
|
||||
// #docregion provider-10-ctor
|
||||
log:string;
|
||||
constructor(@Optional() private _logger:Logger) { }
|
||||
// #enddocregion provider-10-ctor
|
||||
|
||||
ngOnInit() {
|
||||
// #docregion provider-10-logger
|
||||
// No logger? Make one!
|
||||
if (!this._logger) {
|
||||
this._logger = {
|
||||
log: (msg:string)=> this._logger.logs.push(msg),
|
||||
logs: []
|
||||
}
|
||||
this._logger.log("Optional logger was not available.")
|
||||
}
|
||||
// #enddocregion provider-10-logger
|
||||
else {
|
||||
this._logger.log('Hello from the injected logger.')
|
||||
this.log = this._logger.logs[0];
|
||||
}
|
||||
this.log = this._logger.logs[0];
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////
|
||||
@Component({
|
||||
selector: 'my-providers',
|
||||
template: `
|
||||
<h2>Provider variations</h2>
|
||||
<div id="p1"><provider-1></provider-1></div>
|
||||
<div id="p2"><provider-2></provider-2></div>
|
||||
<div id="p3"><provider-3></provider-3></div>
|
||||
<div id="p4"><provider-4></provider-4></div>
|
||||
<div id="p5"><provider-5></provider-5></div>
|
||||
<div id="p6a"><provider-6a></provider-6a></div>
|
||||
<div id="p6b"><provider-6b></provider-6b></div>
|
||||
<div id="p7"><provider-7></provider-7></div>
|
||||
<div id="p8"><provider-8></provider-8></div>
|
||||
<div id="p9a"><provider-9a></provider-9a></div>
|
||||
<div id="p9b"><provider-9b></provider-9b></div>
|
||||
<div id="p10a"><provider-10a></provider-10a></div>
|
||||
<div id="p10b"><provider-10b></provider-10b></div>
|
||||
`,
|
||||
directives:[
|
||||
ProviderComponent1,
|
||||
ProviderComponent2,
|
||||
ProviderComponent3,
|
||||
ProviderComponent4,
|
||||
ProviderComponent5,
|
||||
ProviderComponent6a,
|
||||
ProviderComponent6b,
|
||||
ProviderComponent7,
|
||||
ProviderComponent8,
|
||||
ProviderComponent9a,
|
||||
ProviderComponent9b,
|
||||
ProviderComponent10a,
|
||||
ProviderComponent10b,
|
||||
],
|
||||
})
|
||||
export class ProvidersComponent { }
|
|
@ -0,0 +1,53 @@
|
|||
// Simulate a simple test
|
||||
// Reader should look to the testing chapter for the real thing
|
||||
|
||||
import {Component} from 'angular2/core';
|
||||
import { HeroService } from './heroes/hero.service';
|
||||
import { HeroListComponent } from './heroes/hero-list.component';
|
||||
|
||||
@Component({
|
||||
selector: 'my-tests',
|
||||
template: `
|
||||
<h2>Tests</h2>
|
||||
<p id="tests">Tests {{results.pass}}: {{results.message}}</p>
|
||||
`
|
||||
})
|
||||
export class TestComponent {
|
||||
results = runTests();
|
||||
}
|
||||
|
||||
/////////////////////////////////////
|
||||
function runTests() {
|
||||
|
||||
//#docregion spec
|
||||
let expectedHeroes = [{name: 'A'}, {name: 'B'}]
|
||||
let mockService = <HeroService> {getHeroes: () => expectedHeroes }
|
||||
|
||||
it("should have heroes when HeroListComponent created", () => {
|
||||
let hlc = new HeroListComponent(mockService);
|
||||
expect(hlc.heroes.length).toEqual(expectedHeroes.length);
|
||||
})
|
||||
//#enddocregion spec
|
||||
|
||||
return testResults;
|
||||
}
|
||||
|
||||
//////////////////////////////////
|
||||
// Fake Jasmine infrastructure
|
||||
var testName:string;
|
||||
var testResults: {pass:string; message:string};
|
||||
|
||||
function expect(actual:any) {
|
||||
return {
|
||||
toEqual: function(expected:any){
|
||||
testResults = actual === expected?
|
||||
{pass:'passed', message: `${testName}`} :
|
||||
{pass:'failed', message: `${testName}; expected ${actual} to equal ${expected}.`};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function it(label:string, test: () => void) {
|
||||
testName = label;
|
||||
test();
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
// #docregion
|
||||
import {Injectable} from 'angular2/core';
|
||||
|
||||
@Injectable()
|
||||
export class UserService {
|
||||
// Todo: get the user; don't 'new' it.
|
||||
private _alice = new User('Alice', true);
|
||||
private _bob = new User('Bob', false);
|
||||
|
||||
// initial user is Bob
|
||||
user = this._bob;
|
||||
|
||||
// swaps users
|
||||
getNewUser() {
|
||||
return this.user = this.user === this._bob ? this._alice : this._bob;
|
||||
}
|
||||
}
|
||||
|
||||
export class User {
|
||||
constructor(
|
||||
public name:string,
|
||||
public isAuthorized:boolean = false) { }
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
<!-- #docregion -->
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<title>Dependency Injection</title>
|
||||
<!-- IE required polyfills, in this exact order -->
|
||||
<script src="node_modules/es6-shim/es6-shim.min.js"></script>
|
||||
<script src="node_modules/systemjs/dist/system-polyfills.js"></script>
|
||||
|
||||
<script src="node_modules/angular2/bundles/angular2-polyfills.js"></script>
|
||||
<script src="node_modules/systemjs/dist/system.src.js"></script>
|
||||
<script src="node_modules/rxjs/bundles/Rx.js"></script>
|
||||
<script src="node_modules/angular2/bundles/angular2.dev.js"></script>
|
||||
<script>
|
||||
System.config({
|
||||
packages: {
|
||||
app: {
|
||||
format: 'register',
|
||||
defaultExtension: 'js'
|
||||
}
|
||||
}
|
||||
});
|
||||
System.import('app/main')
|
||||
.then(null, console.error.bind(console));
|
||||
</script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<my-app>Loading my-app ...</my-app>
|
||||
<my-providers>Loading my-providers ...</my-providers>
|
||||
</body>
|
||||
|
||||
</html>
|
|
@ -0,0 +1,9 @@
|
|||
{
|
||||
"description": "Dependency Injection",
|
||||
"files":[
|
||||
"!**/*.d.ts",
|
||||
"!**/*.js",
|
||||
"!**/*.[1,2].*"
|
||||
],
|
||||
"tags": ["dependency", "di"]
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
System.register(['angular2/core'], function(exports_1) {
|
||||
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
||||
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
||||
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
||||
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
||||
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
||||
};
|
||||
var __metadata = (this && this.__metadata) || function (k, v) {
|
||||
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
||||
};
|
||||
var core_1;
|
||||
var HelloWorld;
|
||||
return {
|
||||
setters:[
|
||||
function (core_1_1) {
|
||||
core_1 = core_1_1;
|
||||
}],
|
||||
execute: function() {
|
||||
HelloWorld = (function () {
|
||||
function HelloWorld() {
|
||||
// Declaring the variable for binding with initial value
|
||||
this.yourName = '';
|
||||
}
|
||||
HelloWorld = __decorate([
|
||||
core_1.Component({
|
||||
// Declare the tag name in index.html to where the component attaches
|
||||
selector: 'hello-world',
|
||||
// Location of the template for this component
|
||||
templateUrl: 'app/hello_world.html'
|
||||
}),
|
||||
__metadata('design:paramtypes', [])
|
||||
], HelloWorld);
|
||||
return HelloWorld;
|
||||
})();
|
||||
exports_1("HelloWorld", HelloWorld);
|
||||
}
|
||||
}
|
||||
});
|
||||
//# sourceMappingURL=hello_world.js.map
|
|
@ -0,0 +1,16 @@
|
|||
System.register(['angular2/platform/browser', './hello_world'], function(exports_1) {
|
||||
var browser_1, hello_world_1;
|
||||
return {
|
||||
setters:[
|
||||
function (browser_1_1) {
|
||||
browser_1 = browser_1_1;
|
||||
},
|
||||
function (hello_world_1_1) {
|
||||
hello_world_1 = hello_world_1_1;
|
||||
}],
|
||||
execute: function() {
|
||||
browser_1.bootstrap(hello_world_1.HelloWorld);
|
||||
}
|
||||
}
|
||||
});
|
||||
//# sourceMappingURL=main.js.map
|
|
@ -0,0 +1,56 @@
|
|||
System.register(['angular2/core', './ui_tabs'], function(exports_1) {
|
||||
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
||||
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
||||
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
||||
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
||||
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
||||
};
|
||||
var __metadata = (this && this.__metadata) || function (k, v) {
|
||||
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
||||
};
|
||||
var core_1, ui_tabs_1;
|
||||
var Detail, DiDemo;
|
||||
return {
|
||||
setters:[
|
||||
function (core_1_1) {
|
||||
core_1 = core_1_1;
|
||||
},
|
||||
function (ui_tabs_1_1) {
|
||||
ui_tabs_1 = ui_tabs_1_1;
|
||||
}],
|
||||
execute: function() {
|
||||
Detail = (function () {
|
||||
function Detail() {
|
||||
}
|
||||
return Detail;
|
||||
})();
|
||||
DiDemo = (function () {
|
||||
function DiDemo() {
|
||||
this.details = [];
|
||||
this.id = 0;
|
||||
}
|
||||
DiDemo.prototype.addDetail = function () {
|
||||
this.id++;
|
||||
this.details.push({
|
||||
title: "Detail " + this.id,
|
||||
text: "Some detail text for " + this.id + "..."
|
||||
});
|
||||
};
|
||||
DiDemo.prototype.removeDetail = function (detail) {
|
||||
this.details = this.details.filter(function (d) { return d !== detail; });
|
||||
};
|
||||
DiDemo = __decorate([
|
||||
core_1.Component({
|
||||
selector: 'di-demo',
|
||||
template: "\n <h4>Tabs Demo</h4>\n <ui-tabs>\n <template ui-pane title='Overview' active=\"true\">\n You have {{details.length}} details.\n </template>\n <template *ngFor=\"#detail of details\" ui-pane [title]=\"detail.title\">\n {{detail.text}} <br><br>\n <button class=\"btn\" (click)=\"removeDetail(detail)\">Remove</button>\n </template>\n <template ui-pane title='Summary'>\n Next last ID is {{id}}.\n </template>\n </ui-tabs>\n <hr>\n <button class=\"btn\" (click)=\"addDetail()\">Add Detail</button>\n ",
|
||||
directives: [ui_tabs_1.UiTabs, ui_tabs_1.UiPane]
|
||||
}),
|
||||
__metadata('design:paramtypes', [])
|
||||
], DiDemo);
|
||||
return DiDemo;
|
||||
})();
|
||||
exports_1("DiDemo", DiDemo);
|
||||
}
|
||||
}
|
||||
});
|
||||
//# sourceMappingURL=di_demo.js.map
|
|
@ -0,0 +1,16 @@
|
|||
System.register(['angular2/platform/browser', './di_demo'], function(exports_1) {
|
||||
var browser_1, di_demo_1;
|
||||
return {
|
||||
setters:[
|
||||
function (browser_1_1) {
|
||||
browser_1 = browser_1_1;
|
||||
},
|
||||
function (di_demo_1_1) {
|
||||
di_demo_1 = di_demo_1_1;
|
||||
}],
|
||||
execute: function() {
|
||||
browser_1.bootstrap(di_demo_1.DiDemo);
|
||||
}
|
||||
}
|
||||
});
|
||||
//# sourceMappingURL=main.js.map
|
|
@ -0,0 +1,85 @@
|
|||
System.register(['angular2/core'], function(exports_1) {
|
||||
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
||||
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
||||
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
||||
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
||||
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
||||
};
|
||||
var __metadata = (this && this.__metadata) || function (k, v) {
|
||||
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
||||
};
|
||||
var core_1;
|
||||
var UiPane, UiTabs;
|
||||
return {
|
||||
setters:[
|
||||
function (core_1_1) {
|
||||
core_1 = core_1_1;
|
||||
}],
|
||||
execute: function() {
|
||||
UiPane = (function () {
|
||||
function UiPane(viewContainer, templateRef) {
|
||||
this.viewContainer = viewContainer;
|
||||
this.templateRef = templateRef;
|
||||
this._active = false;
|
||||
}
|
||||
Object.defineProperty(UiPane.prototype, "active", {
|
||||
get: function () {
|
||||
return this._active;
|
||||
},
|
||||
set: function (active) {
|
||||
if (active == this._active)
|
||||
return;
|
||||
this._active = active;
|
||||
if (active) {
|
||||
this.viewContainer.createEmbeddedView(this.templateRef);
|
||||
}
|
||||
else {
|
||||
this.viewContainer.remove(0);
|
||||
}
|
||||
},
|
||||
enumerable: true,
|
||||
configurable: true
|
||||
});
|
||||
__decorate([
|
||||
core_1.Input(),
|
||||
__metadata('design:type', String)
|
||||
], UiPane.prototype, "title", void 0);
|
||||
__decorate([
|
||||
core_1.Input(),
|
||||
__metadata('design:type', Boolean),
|
||||
__metadata('design:paramtypes', [Boolean])
|
||||
], UiPane.prototype, "active", null);
|
||||
UiPane = __decorate([
|
||||
core_1.Directive({
|
||||
selector: '[ui-pane]'
|
||||
}),
|
||||
__metadata('design:paramtypes', [core_1.ViewContainerRef, core_1.TemplateRef])
|
||||
], UiPane);
|
||||
return UiPane;
|
||||
})();
|
||||
exports_1("UiPane", UiPane);
|
||||
UiTabs = (function () {
|
||||
function UiTabs() {
|
||||
}
|
||||
UiTabs.prototype.select = function (pane) {
|
||||
this.panes.toArray().forEach(function (p) { return p.active = p == pane; });
|
||||
};
|
||||
__decorate([
|
||||
core_1.ContentChildren(UiPane),
|
||||
__metadata('design:type', core_1.QueryList)
|
||||
], UiTabs.prototype, "panes", void 0);
|
||||
UiTabs = __decorate([
|
||||
core_1.Component({
|
||||
selector: 'ui-tabs',
|
||||
template: "\n <ul class=\"nav nav-tabs\">\n <li *ngFor=\"var pane of panes\"\n (click)=\"select(pane)\"\n role=\"presentation\" [class.active]=\"pane.active\">\n <a>{{pane.title}}</a>\n </li>\n </ul>\n <ng-content></ng-content>\n ",
|
||||
styles: ['a { cursor: pointer; cursor: hand; }']
|
||||
}),
|
||||
__metadata('design:paramtypes', [])
|
||||
], UiTabs);
|
||||
return UiTabs;
|
||||
})();
|
||||
exports_1("UiTabs", UiTabs);
|
||||
}
|
||||
}
|
||||
});
|
||||
//# sourceMappingURL=ui_tabs.js.map
|
|
@ -0,0 +1,16 @@
|
|||
System.register(['angular2/platform/browser', './todo_app'], function(exports_1) {
|
||||
var browser_1, todo_app_1;
|
||||
return {
|
||||
setters:[
|
||||
function (browser_1_1) {
|
||||
browser_1 = browser_1_1;
|
||||
},
|
||||
function (todo_app_1_1) {
|
||||
todo_app_1 = todo_app_1_1;
|
||||
}],
|
||||
execute: function() {
|
||||
browser_1.bootstrap(todo_app_1.TodoApp);
|
||||
}
|
||||
}
|
||||
});
|
||||
//# sourceMappingURL=main.js.map
|
|
@ -0,0 +1,8 @@
|
|||
System.register([], function(exports_1) {
|
||||
return {
|
||||
setters:[],
|
||||
execute: function() {
|
||||
}
|
||||
}
|
||||
});
|
||||
//# sourceMappingURL=todo.js.map
|
|
@ -0,0 +1,66 @@
|
|||
System.register(['angular2/core', './todo_list', './todo_form'], function(exports_1) {
|
||||
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
||||
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
||||
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
||||
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
||||
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
||||
};
|
||||
var __metadata = (this && this.__metadata) || function (k, v) {
|
||||
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
||||
};
|
||||
var core_1, todo_list_1, todo_form_1;
|
||||
var TodoApp;
|
||||
return {
|
||||
setters:[
|
||||
function (core_1_1) {
|
||||
core_1 = core_1_1;
|
||||
},
|
||||
function (todo_list_1_1) {
|
||||
todo_list_1 = todo_list_1_1;
|
||||
},
|
||||
function (todo_form_1_1) {
|
||||
todo_form_1 = todo_form_1_1;
|
||||
}],
|
||||
execute: function() {
|
||||
TodoApp = (function () {
|
||||
function TodoApp() {
|
||||
this.todos = [
|
||||
{ text: 'learn angular', done: true },
|
||||
{ text: 'build an angular app', done: false }
|
||||
];
|
||||
}
|
||||
Object.defineProperty(TodoApp.prototype, "remaining", {
|
||||
get: function () {
|
||||
return this.todos.reduce(function (count, todo) { return count + +!todo.done; }, 0);
|
||||
},
|
||||
enumerable: true,
|
||||
configurable: true
|
||||
});
|
||||
TodoApp.prototype.archive = function () {
|
||||
var _this = this;
|
||||
var oldTodos = this.todos;
|
||||
this.todos = [];
|
||||
oldTodos.forEach(function (todo) {
|
||||
if (!todo.done)
|
||||
_this.todos.push(todo);
|
||||
});
|
||||
};
|
||||
TodoApp.prototype.addTask = function (task) {
|
||||
this.todos.push(task);
|
||||
};
|
||||
TodoApp = __decorate([
|
||||
core_1.Component({
|
||||
selector: 'todo-app',
|
||||
template: "\n <h2>Todo</h2>\n <span>{{remaining}} of {{todos.length}} remaining</span>\n [ <a (click)=\"archive()\">archive</a> ]\n\n <todo-list [todos]=\"todos\"></todo-list>\n <todo-form (newTask)=\"addTask($event)\"></todo-form>",
|
||||
styles: ['a { cursor: pointer; cursor: hand; }'],
|
||||
directives: [todo_list_1.TodoList, todo_form_1.TodoForm]
|
||||
}),
|
||||
__metadata('design:paramtypes', [])
|
||||
], TodoApp);
|
||||
return TodoApp;
|
||||
})();
|
||||
exports_1("TodoApp", TodoApp);
|
||||
}
|
||||
}
|
||||
});
|
||||
//# sourceMappingURL=todo_app.js.map
|
|
@ -0,0 +1,47 @@
|
|||
System.register(['angular2/core'], function(exports_1) {
|
||||
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
||||
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
||||
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
||||
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
||||
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
||||
};
|
||||
var __metadata = (this && this.__metadata) || function (k, v) {
|
||||
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
||||
};
|
||||
var core_1;
|
||||
var TodoForm;
|
||||
return {
|
||||
setters:[
|
||||
function (core_1_1) {
|
||||
core_1 = core_1_1;
|
||||
}],
|
||||
execute: function() {
|
||||
TodoForm = (function () {
|
||||
function TodoForm() {
|
||||
this.newTask = new core_1.EventEmitter();
|
||||
this.task = '';
|
||||
}
|
||||
TodoForm.prototype.addTodo = function () {
|
||||
if (this.task) {
|
||||
this.newTask.next({ text: this.task, done: false });
|
||||
}
|
||||
this.task = '';
|
||||
};
|
||||
__decorate([
|
||||
core_1.Output(),
|
||||
__metadata('design:type', Object)
|
||||
], TodoForm.prototype, "newTask", void 0);
|
||||
TodoForm = __decorate([
|
||||
core_1.Component({
|
||||
selector: 'todo-form',
|
||||
template: "\n <form (ngSubmit)=\"addTodo()\">\n <input type=\"text\" [(ngModel)]=\"task\" size=\"30\"\n placeholder=\"add new todo here\">\n <input class=\"btn-primary\" type=\"submit\" value=\"add\">\n </form>"
|
||||
}),
|
||||
__metadata('design:paramtypes', [])
|
||||
], TodoForm);
|
||||
return TodoForm;
|
||||
})();
|
||||
exports_1("TodoForm", TodoForm);
|
||||
}
|
||||
}
|
||||
});
|
||||
//# sourceMappingURL=todo_form.js.map
|
|
@ -0,0 +1,41 @@
|
|||
System.register(['angular2/core'], function(exports_1) {
|
||||
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
||||
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
||||
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
||||
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
||||
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
||||
};
|
||||
var __metadata = (this && this.__metadata) || function (k, v) {
|
||||
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
||||
};
|
||||
var core_1;
|
||||
var TodoList;
|
||||
return {
|
||||
setters:[
|
||||
function (core_1_1) {
|
||||
core_1 = core_1_1;
|
||||
}],
|
||||
execute: function() {
|
||||
TodoList = (function () {
|
||||
function TodoList() {
|
||||
}
|
||||
__decorate([
|
||||
core_1.Input(),
|
||||
__metadata('design:type', Array)
|
||||
], TodoList.prototype, "todos", void 0);
|
||||
TodoList = __decorate([
|
||||
core_1.Component({
|
||||
selector: 'todo-list',
|
||||
styles: ["\n .done-true {\n text-decoration: line-through;\n color: grey;\n }"
|
||||
],
|
||||
template: "\n <ul class=\"unstyled\">\n <li *ngFor=\"#todo of todos\">\n <input type=\"checkbox\" [(ngModel)]=\"todo.done\">\n <span class=\"done-{{todo.done}}\">{{todo.text}}</span>\n </li>\n </ul>"
|
||||
}),
|
||||
__metadata('design:paramtypes', [])
|
||||
], TodoList);
|
||||
return TodoList;
|
||||
})();
|
||||
exports_1("TodoList", TodoList);
|
||||
}
|
||||
}
|
||||
});
|
||||
//# sourceMappingURL=todo_list.js.map
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue