angular-cn/aio/content/examples/hierarchical-dependency-inj.../ts/plnkr.no-link.html

744 lines
20 KiB
HTML
Raw Normal View History

<html lang="en"><head></head><body><form id="mainForm" method="post" action="http://plnkr.co/edit/?p=preview" target="_self"><input type="hidden" name="files[app/app.component.ts]" value="import { Component } from '@angular/core';
@Component({
selector: 'my-app',
template: `
<label><input type=&quot;checkbox&quot; [checked]=&quot;showHeroes&quot; (change)=&quot;showHeroes=!showHeroes&quot;>Heroes</label>
<label><input type=&quot;checkbox&quot; [checked]=&quot;showVillains&quot; (change)=&quot;showVillains=!showVillains&quot;>Villains</label>
<label><input type=&quot;checkbox&quot; [checked]=&quot;showCars&quot; (change)=&quot;showCars=!showCars&quot;>Cars</label>
<h1>Hierarchical Dependency Injection</h1>
<heroes-list *ngIf=&quot;showHeroes&quot;></heroes-list>
<villains-list *ngIf=&quot;showVillains&quot;></villains-list>
<my-cars *ngIf=&quot;showCars&quot;></my-cars>
`
})
export class AppComponent {
showCars = true;
showHeroes = true;
showVillains = true;
}
/*
Copyright 2016 Google Inc. All Rights Reserved.
Use of this source code is governed by an MIT-style license that
can be found in the LICENSE file at http://angular.io/license
*/"><input type="hidden" name="files[app/app.module.ts]" value="import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { FormsModule } from '@angular/forms';
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: [
carServices,
HeroesService
],
declarations: [
AppComponent,
carComponents,
HeroesListComponent,
HeroTaxReturnComponent,
VillainsListComponent
],
bootstrap: [ AppComponent ]
})
export class AppModule { }
/*
Copyright 2016 Google Inc. All Rights Reserved.
Use of this source code is governed by an MIT-style license that
can be found in the LICENSE file at http://angular.io/license
*/"><input type="hidden" name="files[app/car.components.ts]" value="import { Component } from '@angular/core';
import {
CarService, CarService2, CarService3,
EngineService, EngineService2, TiresService
} from './car.services';
////////// CCarComponent ////////////
@Component({
selector: 'c-car',
template: `<div>C: {{description}}</div>`,
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: `
<div>B: {{description}}</div>
<c-car></c-car>
`,
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: `
<div>A: {{description}}</div>
<b-car></b-car>`
})
export class ACarComponent {
description: string;
constructor(carService: CarService) {
this.description = `${carService.getCar().description} (${carService.name})`;
}
}
////////// CarsComponent ////////////
@Component({
selector: 'my-cars',
template: `
<h3>Cars</h3>
<a-car></a-car>`
})
export class CarsComponent { }
////////////////
export const carComponents = [
CarsComponent,
ACarComponent, BCarComponent, CCarComponent
];
// generic car-related services
export const carServices = [
CarService, EngineService, TiresService
];
/*
Copyright 2016 Google Inc. All Rights Reserved.
Use of this source code is governed by an MIT-style license that
can be found in the LICENSE file at http://angular.io/license
*/"><input type="hidden" name="files[app/car.services.ts]" value="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;
}
}
/*
Copyright 2016 Google Inc. All Rights Reserved.
Use of this source code is governed by an MIT-style license that
can be found in the LICENSE file at http://angular.io/license
*/"><input type="hidden" name="files[app/hero-tax-return.component.ts]" value="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' ],
providers: [ HeroTaxReturnService ]
})
export class HeroTaxReturnComponent {
message = '';
@Output() close = new EventEmitter<void>();
@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);
}
}
/*
Copyright 2016 Google Inc. All Rights Reserved.
Use of this source code is governed by an MIT-style license that
can be found in the LICENSE file at http://angular.io/license
*/"><input type="hidden" name="files[app/hero-tax-return.service.ts]" value="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();
}
}
/*
Copyright 2016 Google Inc. All Rights Reserved.
Use of this source code is governed by an MIT-style license that
can be found in the LICENSE file at http://angular.io/license
*/"><input type="hidden" name="files[app/hero.ts]" value="
export class Hero {
id: number;
name: 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);
}
}
/*
Copyright 2016 Google Inc. All Rights Reserved.
Use of this source code is governed by an MIT-style license that
can be found in the LICENSE file at http://angular.io/license
*/"><input type="hidden" name="files[app/heroes-list.component.ts]" value="import { Component } from '@angular/core';
import { Observable } from 'rxjs/Observable';
import { Hero, HeroTaxReturn } from './hero';
import { HeroesService } from './heroes.service';
@Component({
selector: 'heroes-list',
template: `
<div>
<h3>Hero Tax Returns</h3>
<ul>
<li *ngFor=&quot;let hero of heroes | async&quot;
(click)=&quot;showTaxReturn(hero)&quot;>{{hero.name}}
</li>
</ul>
<hero-tax-return
*ngFor=&quot;let selected of selectedTaxReturns; let i = index&quot;
[taxReturn]=&quot;selected&quot;
(close)=&quot;closeTaxReturn(i)&quot;>
</hero-tax-return>
</div>
`,
styles: [ 'li {cursor: pointer;}' ]
})
export class HeroesListComponent {
heroes: Observable<Hero[]>;
selectedTaxReturns: HeroTaxReturn[] = [];
constructor(private heroesService: HeroesService) {
this.heroes = heroesService.getHeroes();
}
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);
}
});
}
closeTaxReturn(ix: number) {
this.selectedTaxReturns.splice(ix, 1);
}
}
/*
Copyright 2016 Google Inc. All Rights Reserved.
Use of this source code is governed by an MIT-style license that
can be found in the LICENSE file at http://angular.io/license
*/"><input type="hidden" name="files[app/heroes.service.ts]" value="import { Injectable } from '@angular/core';
import { Observable } from 'rxjs/Observable';
import { Observer } from 'rxjs/Observer';
import { Hero, HeroTaxReturn } from './hero';
@Injectable()
export class HeroesService {
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(): Observable<Hero[]> {
return new Observable<Hero[]>((observer: Observer<Hero[]>) => {
observer.next(this.heroes);
observer.complete();
});
}
getTaxReturn(hero: Hero): Observable<HeroTaxReturn> {
return new Observable<HeroTaxReturn>((observer: Observer<HeroTaxReturn>) => {
const htr = this.heroTaxReturns.find(t => t.hero.id === hero.id);
observer.next(htr || new HeroTaxReturn(0, hero));
observer.complete();
});
}
saveTaxReturn(heroTaxReturn: HeroTaxReturn): Observable<HeroTaxReturn> {
return new Observable<HeroTaxReturn>((observer: Observer<HeroTaxReturn>) => {
const htr = this.heroTaxReturns.find(t => t.id === heroTaxReturn.id);
if (htr) {
heroTaxReturn = Object.assign(htr, heroTaxReturn); // demo: mutate
} else {
this.heroTaxReturns.push(heroTaxReturn);
}
observer.next(heroTaxReturn);
observer.complete();
});
}
}
/*
Copyright 2016 Google Inc. All Rights Reserved.
Use of this source code is governed by an MIT-style license that
can be found in the LICENSE file at http://angular.io/license
*/"><input type="hidden" name="files[app/villains-list.component.ts]" value="import { Component } from '@angular/core';
import { Observable } from 'rxjs/Observable';
import { Villain, VillainsService } from './villains.service';
@Component({
moduleId: module.id,
selector: 'villains-list',
templateUrl: './villains-list.component.html',
providers: [ VillainsService ]
})
export class VillainsListComponent {
villaines: Observable<Villain[]>;
constructor(private villainesService: VillainsService) {
this.villaines = villainesService.getVillains();
}
}
/*
Copyright 2016 Google Inc. All Rights Reserved.
Use of this source code is governed by an MIT-style license that
can be found in the LICENSE file at http://angular.io/license
*/"><input type="hidden" name="files[app/villains.service.ts]" value="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);
}
}
/*
Copyright 2016 Google Inc. All Rights Reserved.
Use of this source code is governed by an MIT-style license that
can be found in the LICENSE file at http://angular.io/license
*/"><input type="hidden" name="files[main.ts]" value="import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { AppModule } from './app/app.module';
platformBrowserDynamic().bootstrapModule(AppModule);
/*
Copyright 2016 Google Inc. All Rights Reserved.
Use of this source code is governed by an MIT-style license that
can be found in the LICENSE file at http://angular.io/license
*/"><input type="hidden" name="files[app/hero-tax-return.component.css]" value=".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;
}
/*
Copyright 2016 Google Inc. All Rights Reserved.
Use of this source code is governed by an MIT-style license that
can be found in the LICENSE file at http://angular.io/license
*/"><input type="hidden" name="files[styles.css]" value="/* Master Styles */
h1 {
color: #369;
font-family: Arial, Helvetica, sans-serif;
font-size: 250%;
}
h2, h3 {
color: #444;
font-family: Arial, Helvetica, sans-serif;
font-weight: lighter;
}
body {
margin: 2em;
}
body, input[text], button {
color: #888;
font-family: Cambria, Georgia;
}
a {
cursor: pointer;
cursor: hand;
}
button {
font-family: Arial;
background-color: #eee;
border: none;
padding: 5px 10px;
border-radius: 4px;
cursor: pointer;
cursor: hand;
}
button:hover {
background-color: #cfd8dc;
}
button:disabled {
background-color: #eee;
color: #aaa;
cursor: auto;
}
/* Navigation link styles */
nav a {
padding: 5px 10px;
text-decoration: none;
margin-right: 10px;
margin-top: 10px;
display: inline-block;
background-color: #eee;
border-radius: 4px;
}
nav a:visited, a:link {
color: #607D8B;
}
nav a:hover {
color: #039be5;
background-color: #CFD8DC;
}
nav a.active {
color: #039be5;
}
/* items class */
.items {
margin: 0 0 2em 0;
list-style-type: none;
padding: 0;
width: 24em;
}
.items li {
cursor: pointer;
position: relative;
left: 0;
background-color: #EEE;
margin: .5em;
padding: .3em 0;
height: 1.6em;
border-radius: 4px;
}
.items li:hover {
color: #607D8B;
background-color: #DDD;
left: .1em;
}
.items li.selected {
background-color: #CFD8DC;
color: white;
}
.items li.selected:hover {
background-color: #BBD8DC;
}
.items .text {
position: relative;
top: -3px;
}
.items .badge {
display: inline-block;
font-size: small;
color: white;
padding: 0.8em 0.7em 0 0.7em;
background-color: #607D8B;
line-height: 1em;
position: relative;
left: -1px;
top: -4px;
height: 1.8em;
margin-right: .8em;
border-radius: 4px 0 0 4px;
}
/* everywhere else */
* {
font-family: Arial, Helvetica, sans-serif;
}
/*
Copyright 2016 Google Inc. All Rights Reserved.
Use of this source code is governed by an MIT-style license that
can be found in the LICENSE file at http://angular.io/license
*/"><input type="hidden" name="files[app/hero-tax-return.component.html]" value="<div class=&quot;tax-return&quot;>
<div class=&quot;msg&quot; [class.canceled]=&quot;message==='Canceled'&quot;>{{message}}</div>
<fieldset>
<span id=name>{{taxReturn.name}}</span>
<label id=tid>TID: {{taxReturn.tid}}</label>
</fieldset>
<fieldset>
<label>
Income: <input [(ngModel)]=&quot;taxReturn.income&quot; class=&quot;num&quot;>
</label>
</fieldset>
<fieldset>
<label>Tax: {{taxReturn.tax}}</label>
</fieldset>
<fieldset>
<button (click)=&quot;onSaved()&quot;>Save</button>
<button (click)=&quot;onCanceled()&quot;>Cancel</button>
<button (click)=&quot;onClose()&quot;>Close</button>
</fieldset>
</div>
<!--
Copyright 2016 Google Inc. All Rights Reserved.
Use of this source code is governed by an MIT-style license that
can be found in the LICENSE file at http://angular.io/license
-->"><input type="hidden" name="files[app/villains-list.component.html]" value="<div>
<h3>Villains</h3>
<ul>
<li *ngFor=&quot;let villain of villaines | async&quot;>{{villain.name}}</li>
</ul>
</div>
<!--
Copyright 2016 Google Inc. All Rights Reserved.
Use of this source code is governed by an MIT-style license that
can be found in the LICENSE file at http://angular.io/license
-->"><input type="hidden" name="files[index.html]" value="<!DOCTYPE html>
<html>
<head>
<title>Hierarchical Injectors</title>
<script>document.write('<base href=&quot;' + document.location + '&quot; />');</script>
<meta charset=&quot;UTF-8&quot;>
<meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1&quot;>
<link rel=&quot;stylesheet&quot; href=&quot;styles.css&quot;>
<!-- Polyfills -->
<script src=&quot;https://unpkg.com/core-js/client/shim.min.js&quot;></script>
<script src=&quot;https://unpkg.com/zone.js@0.7.4?main=browser&quot;></script>
<script src=&quot;https://unpkg.com/systemjs@0.19.39/dist/system.src.js&quot;></script>
<script src=&quot;https://cdn.rawgit.com/angular/angular.io/b3c65a9/public/docs/_examples/_boilerplate/systemjs.config.web.js&quot;></script>
<script>
System.import('main.js').catch(function(err){ console.error(err); });
</script>
</head>
<body>
<my-app>loading...</my-app>
</body>
</html>
<!--
Copyright 2016 Google Inc. All Rights Reserved.
Use of this source code is governed by an MIT-style license that
can be found in the LICENSE file at http://angular.io/license
-->"><input type="hidden" name="tags[0]" value="angular"><input type="hidden" name="tags[1]" value="example"><input type="hidden" name="tags[2]" value="dependency"><input type="hidden" name="tags[3]" value="injection"><input type="hidden" name="private" value="true"><input type="hidden" name="description" value="Angular Example - Hierachical Dependency Injection"></form><script>document.getElementById("mainForm").submit();</script></body></html>