diff --git a/public/docs/_examples/hierarchical-dependency-injection/e2e-spec.ts b/public/docs/_examples/hierarchical-dependency-injection/e2e-spec.ts
index 738e304d1b..4630453f78 100644
--- a/public/docs/_examples/hierarchical-dependency-injection/e2e-spec.ts
+++ b/public/docs/_examples/hierarchical-dependency-injection/e2e-spec.ts
@@ -1,56 +1,103 @@
-import { browser, element, by } from 'protractor';
+'use strict'; // necessary for es6 output in node
-describe('Hierarchical dependency injection', function () {
+import { browser, by, element } from 'protractor';
- beforeEach(function () {
+describe('Hierarchical dependency injection', () => {
+
+ beforeAll(() => {
browser.get('');
});
- it('should open with a card view', function () {
- expect(element.all(by.cssContainingText('button', 'edit')).get(0).isDisplayed()).toBe(true,
- 'edit button should be displayed');
- });
+ describe('Heroes Scenario', () => {
+ let page = {
+ heroName: '',
+ income: '',
- it('should have multiple heroes listed', function () {
- expect(element.all(by.css('heroes-list li')).count()).toBeGreaterThan(1);
- });
+ // queries
+ heroEl: element.all(by.css('heroes-list li')).get(0), // first hero
+ heroCardEl: element(by.css('heroes-list hero-tax-return')), // first hero tax-return
+ taxReturnNameEl: element.all(by.css('heroes-list hero-tax-return #name')).get(0),
+ incomeInputEl: element.all(by.css('heroes-list hero-tax-return input')).get(0),
+ cancelButtonEl: element(by.cssContainingText('heroes-list hero-tax-return button', 'Cancel')),
+ closeButtonEl: element(by.cssContainingText('heroes-list hero-tax-return button', 'Close')),
+ saveButtonEl: element(by.cssContainingText('heroes-list hero-tax-return button', 'Save'))
+ };
- it('should change to editor view after selection', function () {
- let editButtonEle = element.all(by.cssContainingText('button', 'edit')).get(0);
- editButtonEle.click().then(function() {
- expect(editButtonEle.isDisplayed()).toBe(false, 'edit button should be hidden after selection');
+ it('should list multiple heroes', () => {
+ expect(element.all(by.css('heroes-list li')).count()).toBeGreaterThan(1);
+ });
+
+ it('should show no hero tax-returns at the start', () => {
+ expect(element.all(by.css('heroes-list li hero-tax-return')).count()).toBe(0);
+ });
+
+ it('should open first hero in hero-tax-return view after click', () => {
+ page.heroEl.getText()
+ .then(val => {
+ page.heroName = val;
+ })
+ .then(() => page.heroEl.click())
+ .then(() => {
+ expect(page.heroCardEl.isDisplayed()).toBe(true);
+ });
+ });
+
+ it('hero tax-return should have first hero\'s name', () => {
+ // Not `page.tax-returnNameInputEl.getAttribute('value')` although later that is essential
+ expect(page.taxReturnNameEl.getText()).toEqual(page.heroName);
+ });
+
+ it('should be able to cancel change', () => {
+ page.incomeInputEl.clear()
+ .then(() => page.incomeInputEl.sendKeys('777'))
+ .then(() => {
+ expect(page.incomeInputEl.getAttribute('value')).toBe('777', 'income should be 777');
+ return page.cancelButtonEl.click();
+ })
+ .then(() => {
+ expect(page.incomeInputEl.getAttribute('value')).not.toBe('777', 'income should not be 777');
+ });
+ });
+
+ it('should be able to save change', () => {
+ page.incomeInputEl.clear()
+ .then(() => page.incomeInputEl.sendKeys('999'))
+ .then(() => {
+ expect(page.incomeInputEl.getAttribute('value')).toBe('999', 'income should be 999');
+ return page.saveButtonEl.click();
+ })
+ .then(() => {
+ expect(page.incomeInputEl.getAttribute('value')).toBe('999', 'income should still be 999');
+ });
+ });
+
+ it('should be able to close tax-return', () => {
+ page.saveButtonEl.click()
+ .then(() => {
+ expect(element.all(by.css('heroes-list li hero-tax-return')).count()).toBe(0);
+ });
});
- });
- it('should be able to save editor change', function () {
- testEdit(true);
});
- it('should be able to cancel editor change', function () {
- testEdit(false);
+ describe('Villains Scenario', () => {
+ it('should list multiple villains', () => {
+ expect(element.all(by.css('villains-list li')).count()).toBeGreaterThan(1);
+ });
});
- function testEdit(shouldSave: boolean) {
- // select 2nd ele
- let heroEle = element.all(by.css('heroes-list li')).get(1);
- // get the 2nd span which is the name of the hero
- let heroNameEle = heroEle.all(by.css('hero-card span')).get(1);
- let editButtonEle = heroEle.element(by.cssContainingText('button', 'edit'));
- editButtonEle.click().then(function() {
- let inputEle = heroEle.element(by.css('hero-editor input'));
- return inputEle.sendKeys('foo');
- }).then(function() {
- let buttonName = shouldSave ? 'save' : 'cancel';
- let buttonEle = heroEle.element(by.cssContainingText('button', buttonName));
- return buttonEle.click();
- }).then(function() {
- if (shouldSave) {
- expect(heroNameEle.getText()).toContain('foo');
- } else {
- expect(heroNameEle.getText()).not.toContain('foo');
- }
- });
- }
+ describe('Cars Scenario', () => {
+ it('A-component should use expected services', () => {
+ expect(element(by.css('a-car')).getText()).toContain('C1-E1-T1');
+ });
+
+ it('B-component should use expected services', () => {
+ expect(element(by.css('b-car')).getText()).toContain('C2-E2-T1');
+ });
+ it('C-component should use expected services', () => {
+ expect(element(by.css('c-car')).getText()).toContain('C3-E2-T1');
+ });
+ });
});
diff --git a/public/docs/_examples/hierarchical-dependency-injection/ts/app/app.component.ts b/public/docs/_examples/hierarchical-dependency-injection/ts/app/app.component.ts
new file mode 100644
index 0000000000..a58b684434
--- /dev/null
+++ b/public/docs/_examples/hierarchical-dependency-injection/ts/app/app.component.ts
@@ -0,0 +1,21 @@
+import { Component } from '@angular/core';
+
+@Component({
+ selector: 'my-app',
+ template: `
+
+
+
+
+
Hierarchical Dependency Injection
+
+
+
+
+ `
+})
+export class AppComponent {
+ showCars = true;
+ showHeroes = true;
+ showVillains = true;
+}
diff --git a/public/docs/_examples/hierarchical-dependency-injection/ts/app/app.module.ts b/public/docs/_examples/hierarchical-dependency-injection/ts/app/app.module.ts
index 80047b8e32..6ea18655af 100644
--- a/public/docs/_examples/hierarchical-dependency-injection/ts/app/app.module.ts
+++ b/public/docs/_examples/hierarchical-dependency-injection/ts/app/app.module.ts
@@ -1,43 +1,33 @@
// #docregion
-import { NgModule } from '@angular/core';
+import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
-import { FormsModule } from '@angular/forms';
+import { FormsModule } from '@angular/forms';
-import { HeroesListComponent } from './heroes-list.component';
-import { HeroEditorComponent } from './hero-editor.component';
-import { HeroCardComponent } from './hero-card.component';
-import { HeroesService } from './heroes.service';
+import { AppComponent } from './app.component';
+import { HeroTaxReturnComponent } from './hero-tax-return.component';
+import { HeroesListComponent } from './heroes-list.component';
+import { HeroesService } from './heroes.service';
+import { VillainsListComponent } from './villains-list.component';
+
+import { carComponents, carServices } from './car.components';
@NgModule({
imports: [
BrowserModule,
FormsModule
],
- providers: [ HeroesService ],
+ providers: [
+ carServices,
+ HeroesService
+ ],
declarations: [
+ AppComponent,
+ carComponents,
HeroesListComponent,
- HeroCardComponent,
- HeroEditorComponent
+ HeroTaxReturnComponent,
+ VillainsListComponent
],
- bootstrap: [ HeroesListComponent ]
+ bootstrap: [ AppComponent ]
})
export class AppModule { }
-/* Documentation artifact below
-// #docregion bad-alternative
-// Don't do this!
-@NgModule({
- imports: [
- BrowserModule,
- FormsModule
- ],
- providers: [ HeroesService, RestoreService ],
- declarations: [ HeroesListComponent ],
- bootstrap: [
- HeroesListComponent,
- HeroCardComponent,
- HeroEditorComponent
- ]
-})
-// #enddocregion bad-alternative
-*/
diff --git a/public/docs/_examples/hierarchical-dependency-injection/ts/app/car.components.ts b/public/docs/_examples/hierarchical-dependency-injection/ts/app/car.components.ts
new file mode 100644
index 0000000000..2ae18954ad
--- /dev/null
+++ b/public/docs/_examples/hierarchical-dependency-injection/ts/app/car.components.ts
@@ -0,0 +1,74 @@
+import { Component } from '@angular/core';
+
+import {
+ CarService, CarService2, CarService3,
+ EngineService, EngineService2, TiresService
+} from './car.services';
+
+////////// CCarComponent ////////////
+@Component({
+ selector: 'c-car',
+ template: `C: {{description}}
`,
+ providers: [
+ { provide: CarService, useClass: CarService3 }
+ ]
+})
+export class CCarComponent {
+ description: string;
+ constructor(carService: CarService) {
+ this.description = `${carService.getCar().description} (${carService.name})`;
+ }
+}
+
+////////// BCarComponent ////////////
+@Component({
+ selector: 'b-car',
+ template: `
+ B: {{description}}
+
+ `,
+ providers: [
+ { provide: CarService, useClass: CarService2 },
+ { provide: EngineService, useClass: EngineService2 }
+ ]
+})
+export class BCarComponent {
+ description: string;
+ constructor(carService: CarService) {
+ this.description = `${carService.getCar().description} (${carService.name})`;
+ }
+}
+
+////////// ACarComponent ////////////
+@Component({
+ selector: 'a-car',
+ template: `
+ A: {{description}}
+ `
+})
+export class ACarComponent {
+ description: string;
+ constructor(carService: CarService) {
+ this.description = `${carService.getCar().description} (${carService.name})`;
+ }
+}
+////////// CarsComponent ////////////
+@Component({
+ selector: 'my-cars',
+ template: `
+ Cars
+ `
+})
+export class CarsComponent { }
+
+////////////////
+
+export const carComponents = [
+ CarsComponent,
+ ACarComponent, BCarComponent, CCarComponent
+];
+
+// generic car-related services
+export const carServices = [
+ CarService, EngineService, TiresService
+];
diff --git a/public/docs/_examples/hierarchical-dependency-injection/ts/app/car.services.ts b/public/docs/_examples/hierarchical-dependency-injection/ts/app/car.services.ts
new file mode 100644
index 0000000000..5851b1e595
--- /dev/null
+++ b/public/docs/_examples/hierarchical-dependency-injection/ts/app/car.services.ts
@@ -0,0 +1,95 @@
+import { Injectable } from '@angular/core';
+
+/// Model ///
+export class Car {
+ name = 'Avocado Motors';
+ constructor(public engine: Engine, public tires: Tires) { }
+
+ get description() {
+ return `${this.name} car with ` +
+ `${this.engine.cylinders} cylinders and ${this.tires.make} tires.`;
+ }
+}
+
+export class Engine {
+ cylinders = 4;
+}
+
+export class Tires {
+ make = 'Flintstone';
+ model = 'Square';
+}
+
+//// Engine services ///
+@Injectable()
+export class EngineService {
+ id = 'E1';
+ getEngine() { return new Engine(); }
+}
+
+@Injectable()
+export class EngineService2 {
+ id = 'E2';
+ getEngine() {
+ const eng = new Engine();
+ eng.cylinders = 8;
+ return eng;
+ }
+}
+
+//// Tire services ///
+@Injectable()
+export class TiresService {
+ id = 'T1';
+ getTires() { return new Tires(); }
+}
+
+/// Car Services ///
+@Injectable()
+export class CarService {
+ id = 'C1';
+ constructor(
+ protected engineService: EngineService,
+ protected tiresService: TiresService) { }
+
+ getCar() {
+ return new Car(
+ this.engineService.getEngine(),
+ this.tiresService.getTires());
+ }
+
+ get name() {
+ return `${this.id}-${this.engineService.id}-${this.tiresService.id}`;
+ }
+}
+
+@Injectable()
+export class CarService2 extends CarService {
+ id = 'C2';
+ constructor(
+ protected engineService: EngineService,
+ protected tiresService: TiresService) {
+ super(engineService, tiresService);
+ }
+ getCar() {
+ const car = super.getCar();
+ car.name = 'BamBam Motors, BroVan 2000';
+ return car;
+ }
+}
+
+@Injectable()
+export class CarService3 extends CarService2 {
+ id = 'C3';
+ constructor(
+ protected engineService: EngineService,
+ protected tiresService: TiresService) {
+ super(engineService, tiresService);
+ }
+ getCar() {
+ const car = super.getCar();
+ car.name = 'Chizzamm Motors, Calico UltraMax Supreme';
+ return car;
+ }
+}
+
diff --git a/public/docs/_examples/hierarchical-dependency-injection/ts/app/edit-item.ts b/public/docs/_examples/hierarchical-dependency-injection/ts/app/edit-item.ts
deleted file mode 100644
index 31602112f2..0000000000
--- a/public/docs/_examples/hierarchical-dependency-injection/ts/app/edit-item.ts
+++ /dev/null
@@ -1,6 +0,0 @@
-// #docregion
-export class EditItem {
- editing: boolean;
- constructor (public item: T) {}
-}
-// #docregion
diff --git a/public/docs/_examples/hierarchical-dependency-injection/ts/app/hero-card.component.ts b/public/docs/_examples/hierarchical-dependency-injection/ts/app/hero-card.component.ts
deleted file mode 100644
index a888168848..0000000000
--- a/public/docs/_examples/hierarchical-dependency-injection/ts/app/hero-card.component.ts
+++ /dev/null
@@ -1,17 +0,0 @@
-// #docregion
-import { Component, Input } from '@angular/core';
-
-import { Hero } from './hero';
-
-@Component({
- selector: 'hero-card',
- template: `
-
- Name:
- {{hero.name}}
-
`
-})
-export class HeroCardComponent {
- @Input() hero: Hero;
-}
-// #docregion
diff --git a/public/docs/_examples/hierarchical-dependency-injection/ts/app/hero-editor.component.ts b/public/docs/_examples/hierarchical-dependency-injection/ts/app/hero-editor.component.ts
deleted file mode 100644
index b45960b179..0000000000
--- a/public/docs/_examples/hierarchical-dependency-injection/ts/app/hero-editor.component.ts
+++ /dev/null
@@ -1,47 +0,0 @@
-// #docregion
-import { Component, EventEmitter, Input, Output } from '@angular/core';
-
-import { RestoreService } from './restore.service';
-import { Hero } from './hero';
-
-@Component({
- selector: 'hero-editor',
- // #docregion providers
- providers: [RestoreService],
- // #enddocregion providers
- template: `
-
-
Name:
-
-
-
-
-
-
`
-})
-
-export class HeroEditorComponent {
- @Output() canceled = new EventEmitter();
- @Output() saved = new EventEmitter();
-
- constructor(private restoreService: RestoreService) {}
-
- @Input()
- set hero (hero: Hero) {
- this.restoreService.setItem(hero);
- }
-
- get hero () {
- return this.restoreService.getItem();
- }
-
- onSaved () {
- this.saved.emit(this.restoreService.getItem());
- }
-
- onCanceled () {
- this.hero = this.restoreService.restoreItem();
- this.canceled.emit(this.hero);
- }
-}
-// #enddocregion
diff --git a/public/docs/_examples/hierarchical-dependency-injection/ts/app/hero-tax-return.component.css b/public/docs/_examples/hierarchical-dependency-injection/ts/app/hero-tax-return.component.css
new file mode 100644
index 0000000000..9df776e228
--- /dev/null
+++ b/public/docs/_examples/hierarchical-dependency-injection/ts/app/hero-tax-return.component.css
@@ -0,0 +1,22 @@
+.tax-return { border: thin dashed green; margin: 1em; padding: 1em; width: 18em; position: relative }
+#name { font-weight: bold;}
+#tid { float: right; }
+input { font-size: 100%; padding-left: 2px; width: 6em; }
+input.num { text-align: right; padding-left: 0; padding-right: 4px; width: 4em;}
+fieldset { border: 0 none;}
+
+.msg {
+ color: white;
+ font-size: 150%;
+ position: absolute;
+ /*opacity: 0.3;*/
+ left: 2px;
+ top: 3em;
+ width: 98%;
+ background-color: green;
+ text-align: center;
+}
+.msg.canceled {
+ color: white;
+ background-color: red;
+}
diff --git a/public/docs/_examples/hierarchical-dependency-injection/ts/app/hero-tax-return.component.html b/public/docs/_examples/hierarchical-dependency-injection/ts/app/hero-tax-return.component.html
new file mode 100644
index 0000000000..dbed6c7f5b
--- /dev/null
+++ b/public/docs/_examples/hierarchical-dependency-injection/ts/app/hero-tax-return.component.html
@@ -0,0 +1,20 @@
+
+
{{message}}
+
+
+
+
+
diff --git a/public/docs/_examples/hierarchical-dependency-injection/ts/app/hero-tax-return.component.ts b/public/docs/_examples/hierarchical-dependency-injection/ts/app/hero-tax-return.component.ts
new file mode 100644
index 0000000000..42e813f69b
--- /dev/null
+++ b/public/docs/_examples/hierarchical-dependency-injection/ts/app/hero-tax-return.component.ts
@@ -0,0 +1,44 @@
+// #docregion
+import { Component, EventEmitter, Input, Output } from '@angular/core';
+import { HeroTaxReturn } from './hero';
+import { HeroTaxReturnService } from './hero-tax-return.service';
+
+@Component({
+ moduleId: module.id,
+ selector: 'hero-tax-return',
+ templateUrl: './hero-tax-return.component.html',
+ styleUrls: [ './hero-tax-return.component.css' ],
+ // #docregion providers
+ providers: [ HeroTaxReturnService ]
+ // #enddocregion providers
+})
+export class HeroTaxReturnComponent {
+ message = '';
+ @Output() close = new EventEmitter();
+ @Input()
+ get taxReturn(): HeroTaxReturn {
+ return this.heroTaxReturnService.taxReturn;
+ }
+ set taxReturn (htr: HeroTaxReturn) {
+ this.heroTaxReturnService.taxReturn = htr;
+ }
+
+ constructor(private heroTaxReturnService: HeroTaxReturnService ) { }
+
+ onCanceled() {
+ this.flashMessage('Canceled');
+ this.heroTaxReturnService.restoreTaxReturn();
+ };
+
+ onClose() { this.close.emit(); };
+
+ onSaved() {
+ this.flashMessage('Saved');
+ this.heroTaxReturnService.saveTaxReturn();
+ }
+
+ flashMessage(msg: string) {
+ this.message = msg;
+ setTimeout(() => this.message = '', 500);
+ }
+}
diff --git a/public/docs/_examples/hierarchical-dependency-injection/ts/app/hero-tax-return.service.ts b/public/docs/_examples/hierarchical-dependency-injection/ts/app/hero-tax-return.service.ts
new file mode 100644
index 0000000000..d6ff0f7fff
--- /dev/null
+++ b/public/docs/_examples/hierarchical-dependency-injection/ts/app/hero-tax-return.service.ts
@@ -0,0 +1,30 @@
+// #docregion
+import { Injectable } from '@angular/core';
+import { HeroTaxReturn } from './hero';
+import { HeroesService } from './heroes.service';
+
+@Injectable()
+export class HeroTaxReturnService {
+ private currentTaxReturn: HeroTaxReturn;
+ private originalTaxReturn: HeroTaxReturn;
+
+ constructor(private heroService: HeroesService) { }
+
+ set taxReturn (htr: HeroTaxReturn) {
+ this.originalTaxReturn = htr;
+ this.currentTaxReturn = htr.clone();
+ }
+
+ get taxReturn (): HeroTaxReturn {
+ return this.currentTaxReturn;
+ }
+
+ restoreTaxReturn() {
+ this.taxReturn = this.originalTaxReturn;
+ }
+
+ saveTaxReturn() {
+ this.taxReturn = this.currentTaxReturn;
+ this.heroService.saveTaxReturn(this.currentTaxReturn).subscribe();
+ }
+}
diff --git a/public/docs/_examples/hierarchical-dependency-injection/ts/app/hero.ts b/public/docs/_examples/hierarchical-dependency-injection/ts/app/hero.ts
index 76f808b1c5..4ad6ccd8eb 100644
--- a/public/docs/_examples/hierarchical-dependency-injection/ts/app/hero.ts
+++ b/public/docs/_examples/hierarchical-dependency-injection/ts/app/hero.ts
@@ -1,6 +1,31 @@
// #docregion
+
export class Hero {
+ id: number;
name: string;
- power: string;
+ tid: string; // tax id
+}
+
+//// HeroTaxReturn ////
+let nextId = 100;
+
+export class HeroTaxReturn {
+ constructor(
+ public id = nextId++,
+ public hero: Hero,
+ public income = 0 ) {
+ if (id === 0) { id = nextId++; }
+ }
+
+ get name() { return this.hero.name; }
+ get tax() { return this.income ? .10 * this.income : 0; }
+ get tid() { return this.hero.tid; }
+
+ toString() {
+ return `${this.hero.name}`;
+ }
+
+ clone() {
+ return new HeroTaxReturn(this.id, this.hero, this.income);
+ }
}
-// #enddocregion
diff --git a/public/docs/_examples/hierarchical-dependency-injection/ts/app/heroes-list.component.ts b/public/docs/_examples/hierarchical-dependency-injection/ts/app/heroes-list.component.ts
index af1ece3376..36cb5ec1c3 100644
--- a/public/docs/_examples/hierarchical-dependency-injection/ts/app/heroes-list.component.ts
+++ b/public/docs/_examples/hierarchical-dependency-injection/ts/app/heroes-list.component.ts
@@ -1,51 +1,48 @@
// #docregion
-import { Component } from '@angular/core';
+import { Component } from '@angular/core';
+import { Observable } from 'rxjs/Observable';
-import { EditItem } from './edit-item';
-import { HeroesService } from './heroes.service';
-import { Hero } from './hero';
+import { Hero, HeroTaxReturn } from './hero';
+import { HeroesService } from './heroes.service';
@Component({
selector: 'heroes-list',
template: `
+
Hero Tax Returns
- -
-
-
-
-
-
+
- {{hero.name}}
-
`
+
+
+
+ `,
+ styles: [ 'li {cursor: pointer;}' ]
})
export class HeroesListComponent {
- heroes: Array>;
- constructor(heroesService: HeroesService) {
- this.heroes = heroesService.getHeroes()
- .map(item => new EditItem(item));
+ heroes: Observable;
+ selectedTaxReturns: HeroTaxReturn[] = [];
+
+ constructor(private heroesService: HeroesService) {
+ this.heroes = heroesService.getHeroes();
}
- onSaved (editItem: EditItem, updatedHero: Hero) {
- editItem.item = updatedHero;
- editItem.editing = false;
+ showTaxReturn(hero: Hero) {
+ this.heroesService.getTaxReturn(hero)
+ .subscribe(htr => {
+ // show if not currently shown
+ if (!this.selectedTaxReturns.find(tr => tr.id === htr.id)) {
+ this.selectedTaxReturns.push(htr);
+ }
+ });
}
- onCanceled (editItem: EditItem) {
- editItem.editing = false;
+ closeTaxReturn(ix: number) {
+ this.selectedTaxReturns.splice(ix, 1);
}
}
-
-
-// #enddocregion
diff --git a/public/docs/_examples/hierarchical-dependency-injection/ts/app/heroes.service.ts b/public/docs/_examples/hierarchical-dependency-injection/ts/app/heroes.service.ts
index 2f211e8799..72433b29f7 100644
--- a/public/docs/_examples/hierarchical-dependency-injection/ts/app/heroes.service.ts
+++ b/public/docs/_examples/hierarchical-dependency-injection/ts/app/heroes.service.ts
@@ -1,12 +1,47 @@
-import { Hero } from './hero';
+import { Injectable } from '@angular/core';
+import { Observable } from 'rxjs/Observable';
+import { Subscriber } from 'rxjs/Subscriber';
+
+import { Hero, HeroTaxReturn } from './hero';
+
+@Injectable()
export class HeroesService {
- heroes: Array = [
- { name: 'RubberMan', power: 'flexibility'},
- { name: 'Tornado', power: 'Weather changer'}
+ heroes: Hero[] = [
+ { id: 1, name: 'RubberMan', tid: '082-27-5678'},
+ { id: 2, name: 'Tornado', tid: '099-42-4321'}
+ ];
+
+ heroTaxReturns: HeroTaxReturn[] = [
+ new HeroTaxReturn(10, this.heroes[0], 35000),
+ new HeroTaxReturn(20, this.heroes[1], 1250000)
];
- getHeroes () {
- return this.heroes;
+ getHeroes(): Observable {
+ return new Observable((subscriber: Subscriber) => {
+ subscriber.next(this.heroes);
+ subscriber.complete();
+ });
+ }
+
+ getTaxReturn(hero: Hero): Observable {
+ return new Observable((subscriber: Subscriber) => {
+ const htr = this.heroTaxReturns.find(t => t.hero.id === hero.id);
+ subscriber.next(htr || new HeroTaxReturn(0, hero));
+ subscriber.complete();
+ });
+ }
+
+ saveTaxReturn(heroTaxReturn: HeroTaxReturn): Observable {
+ return new Observable((subscriber: Subscriber) => {
+ const htr = this.heroTaxReturns.find(t => t.id === heroTaxReturn.id);
+ if (htr) {
+ heroTaxReturn = Object.assign(htr, heroTaxReturn); // demo: mutate
+ } else {
+ this.heroTaxReturns.push(heroTaxReturn);
+ }
+ subscriber.next(heroTaxReturn);
+ subscriber.complete();
+ });
}
}
diff --git a/public/docs/_examples/hierarchical-dependency-injection/ts/app/restore.service.ts b/public/docs/_examples/hierarchical-dependency-injection/ts/app/restore.service.ts
deleted file mode 100644
index 667b8a053d..0000000000
--- a/public/docs/_examples/hierarchical-dependency-injection/ts/app/restore.service.ts
+++ /dev/null
@@ -1,25 +0,0 @@
-// #docregion
-export class RestoreService {
- originalItem: T;
- currentItem: T;
-
- setItem (item: T) {
- this.originalItem = item;
- this.currentItem = this.clone(item);
- }
-
- getItem (): T {
- return this.currentItem;
- }
-
- restoreItem (): T {
- this.currentItem = this.originalItem;
- return this.getItem();
- }
-
- clone (item: T): T {
- // super poor clone implementation
- return JSON.parse(JSON.stringify(item));
- }
-}
-// #enddocregion
diff --git a/public/docs/_examples/hierarchical-dependency-injection/ts/app/villains-list.component.html b/public/docs/_examples/hierarchical-dependency-injection/ts/app/villains-list.component.html
new file mode 100644
index 0000000000..955a58078e
--- /dev/null
+++ b/public/docs/_examples/hierarchical-dependency-injection/ts/app/villains-list.component.html
@@ -0,0 +1,6 @@
+
diff --git a/public/docs/_examples/hierarchical-dependency-injection/ts/app/villains-list.component.ts b/public/docs/_examples/hierarchical-dependency-injection/ts/app/villains-list.component.ts
new file mode 100644
index 0000000000..dcdbb9d0be
--- /dev/null
+++ b/public/docs/_examples/hierarchical-dependency-injection/ts/app/villains-list.component.ts
@@ -0,0 +1,21 @@
+// #docregion
+import { Component } from '@angular/core';
+import { Observable } from 'rxjs/Observable';
+
+import { Villain, VillainsService } from './villains.service';
+
+// #docregion metadata
+@Component({
+ moduleId: module.id,
+ selector: 'villains-list',
+ templateUrl: './villains-list.component.html',
+ providers: [ VillainsService ]
+})
+// #enddocregion metadata
+export class VillainsListComponent {
+ villaines: Observable;
+
+ constructor(private villainesService: VillainsService) {
+ this.villaines = villainesService.getVillains();
+ }
+}
diff --git a/public/docs/_examples/hierarchical-dependency-injection/ts/app/villains.service.ts b/public/docs/_examples/hierarchical-dependency-injection/ts/app/villains.service.ts
new file mode 100644
index 0000000000..f839bf24c1
--- /dev/null
+++ b/public/docs/_examples/hierarchical-dependency-injection/ts/app/villains.service.ts
@@ -0,0 +1,17 @@
+import { Injectable } from '@angular/core';
+
+import { of } from 'rxjs/observable/of';
+
+export interface Villain { id: number; name: string; }
+
+@Injectable()
+export class VillainsService {
+ villains: Villain[] = [
+ { id: 1, name: 'Dr. Evil'},
+ { id: 2, name: 'Moriarty'}
+ ];
+
+ getVillains() {
+ return of(this.villains);
+ }
+}
diff --git a/public/docs/_examples/hierarchical-dependency-injection/ts/index.html b/public/docs/_examples/hierarchical-dependency-injection/ts/index.html
index a3b63554b3..749c72f098 100644
--- a/public/docs/_examples/hierarchical-dependency-injection/ts/index.html
+++ b/public/docs/_examples/hierarchical-dependency-injection/ts/index.html
@@ -19,9 +19,7 @@
-
- loading...
-
+ loading...