228 lines
5.5 KiB
TypeScript
228 lines
5.5 KiB
TypeScript
|
/* tslint:disable:no-unused-variable */
|
||
|
/* tslint:disable:one-line:check-open-brace*/
|
||
|
// #docplaster
|
||
|
// #docregion
|
||
|
import { Component, forwardRef, Optional, provide, SkipSelf } from 'angular2/core';
|
||
|
|
||
|
// A component base class (see AlexComponent)
|
||
|
export abstract class Base { name = 'Count Basie'; }
|
||
|
|
||
|
// Marker class, used as an interface
|
||
|
// #docregion parent
|
||
|
export abstract class Parent { name: string; }
|
||
|
// #enddocregion parent
|
||
|
|
||
|
const DifferentParent = Parent;
|
||
|
|
||
|
// #docregion provide-parent, provide-the-parent
|
||
|
// Helper method to provide the current component instance in the name of a `parentType`.
|
||
|
// #enddocregion provide-the-parent
|
||
|
// The `parentType` defaults to `Parent` when omitting the second parameter.
|
||
|
// #docregion provide-the-parent
|
||
|
const provideParent =
|
||
|
// #enddocregion provide-parent, provide-the-parent
|
||
|
// #docregion provide-parent
|
||
|
(component: any, parentType?: any) =>
|
||
|
provide(parentType || Parent, { useExisting: forwardRef(() => component) });
|
||
|
// #enddocregion provide-parent
|
||
|
|
||
|
// Simpler syntax version that always provides the component in the name of `Parent`.
|
||
|
const provideTheParent =
|
||
|
// #docregion provide-the-parent
|
||
|
(component: any) => provide(Parent, { useExisting: forwardRef(() => component) });
|
||
|
// #enddocregion provide-the-parent
|
||
|
|
||
|
|
||
|
///////// C - Child //////////
|
||
|
// #docregion carol
|
||
|
const templateC = `
|
||
|
<div class="c">
|
||
|
<h3>{{name}}</h3>
|
||
|
<p>My parent is {{parent?.name}}</p>
|
||
|
</div>`;
|
||
|
|
||
|
@Component({
|
||
|
selector: 'carol',
|
||
|
template: templateC
|
||
|
})
|
||
|
// #docregion carol-class
|
||
|
export class CarolComponent {
|
||
|
name= 'Carol';
|
||
|
// #docregion carol-ctor
|
||
|
constructor( @Optional() public parent: Parent ) { }
|
||
|
// #enddocregion carol-ctor
|
||
|
}
|
||
|
// #enddocregion carol-class
|
||
|
// #enddocregion carol
|
||
|
|
||
|
@Component({
|
||
|
selector: 'chris',
|
||
|
template: templateC
|
||
|
})
|
||
|
export class ChrisComponent {
|
||
|
name= 'Chris';
|
||
|
constructor( @Optional() public parent: Parent ) { }
|
||
|
}
|
||
|
|
||
|
////// Craig ///////////
|
||
|
/**
|
||
|
* Show we cannot inject a parent by its base class.
|
||
|
*/
|
||
|
// #docregion craig
|
||
|
@Component({
|
||
|
selector: 'craig',
|
||
|
template: `
|
||
|
<div class="c">
|
||
|
<h3>Craig</h3>
|
||
|
{{alex ? 'Found' : 'Did not find'}} Alex via the base class.
|
||
|
</div>`
|
||
|
})
|
||
|
export class CraigComponent {
|
||
|
constructor( @Optional() public alex: Base ) { }
|
||
|
}
|
||
|
// #enddocregion craig
|
||
|
|
||
|
// #docregion C_DIRECTIVES
|
||
|
const C_DIRECTIVES = [
|
||
|
CarolComponent, ChrisComponent, CraigComponent,
|
||
|
forwardRef(() => CathyComponent)
|
||
|
];
|
||
|
// #enddocregion C_DIRECTIVES
|
||
|
|
||
|
//////// B - Parent /////////
|
||
|
// #docregion barry
|
||
|
const templateB = `
|
||
|
<div class="b">
|
||
|
<div>
|
||
|
<h3>{{name}}</h3>
|
||
|
<p>My parent is {{parent?.name}}</p>
|
||
|
</div>
|
||
|
<carol></carol>
|
||
|
<chris></chris>
|
||
|
</div>`;
|
||
|
|
||
|
@Component({
|
||
|
selector: 'barry',
|
||
|
template: templateB,
|
||
|
directives: C_DIRECTIVES,
|
||
|
providers: [ provide(Parent, { useExisting: forwardRef(() => BarryComponent) }) ]
|
||
|
})
|
||
|
export class BarryComponent implements Parent {
|
||
|
name = 'Barry';
|
||
|
// #docregion barry-ctor
|
||
|
constructor( @SkipSelf() @Optional() public parent: Parent ) { }
|
||
|
// #enddocregion barry-ctor
|
||
|
}
|
||
|
// #enddocregion barry
|
||
|
|
||
|
@Component({
|
||
|
selector: 'bob',
|
||
|
template: templateB,
|
||
|
directives: C_DIRECTIVES,
|
||
|
providers: [ provideParent(BobComponent) ]
|
||
|
})
|
||
|
export class BobComponent implements Parent {
|
||
|
name= 'Bob';
|
||
|
constructor( @SkipSelf() @Optional() public parent: Parent ) { }
|
||
|
}
|
||
|
|
||
|
@Component({
|
||
|
selector: 'beth',
|
||
|
template: templateB,
|
||
|
directives: C_DIRECTIVES,
|
||
|
// #docregion beth-providers
|
||
|
providers: [ provideParent(BethComponent, DifferentParent) ]
|
||
|
// #enddocregion beth-providers
|
||
|
})
|
||
|
export class BethComponent implements Parent {
|
||
|
name= 'Beth';
|
||
|
constructor( @SkipSelf() @Optional() public parent: Parent ) { }
|
||
|
}
|
||
|
|
||
|
const B_DIRECTIVES = [ BarryComponent, BethComponent, BobComponent ];
|
||
|
|
||
|
///////// A - Grandparent //////
|
||
|
|
||
|
// #docregion alex, alex-1
|
||
|
@Component({
|
||
|
selector: 'alex',
|
||
|
template: `
|
||
|
<div class="a">
|
||
|
<h3>{{name}}</h3>
|
||
|
<cathy></cathy>
|
||
|
<craig></craig>
|
||
|
<carol></carol>
|
||
|
</div>`,
|
||
|
// #enddocregion alex-1
|
||
|
// #docregion alex-providers
|
||
|
providers: [ provide(Parent, { useExisting: forwardRef(() => AlexComponent) }) ],
|
||
|
// #enddocregion alex-providers
|
||
|
// #docregion alex-1
|
||
|
directives: C_DIRECTIVES
|
||
|
})
|
||
|
// #enddocregion alex-1
|
||
|
// Todo: Add `... implements Parent` to class signature
|
||
|
// #docregion alex-1
|
||
|
// #docregion alex-class-signature
|
||
|
export class AlexComponent extends Base
|
||
|
// #enddocregion alex-class-signature
|
||
|
{
|
||
|
name= 'Alex';
|
||
|
}
|
||
|
// #enddocregion alex, alex-1
|
||
|
|
||
|
/////
|
||
|
|
||
|
// #docregion alice
|
||
|
@Component({
|
||
|
selector: 'alice',
|
||
|
template: `
|
||
|
<div class="a">
|
||
|
<h3>{{name}}</h3>
|
||
|
<barry></barry>
|
||
|
<beth></beth>
|
||
|
<bob></bob>
|
||
|
<carol></carol>
|
||
|
</div> `,
|
||
|
directives: [ B_DIRECTIVES, C_DIRECTIVES ],
|
||
|
// #docregion alice-providers
|
||
|
providers: [ provideParent(AliceComponent) ]
|
||
|
// #enddocregion alice-providers
|
||
|
})
|
||
|
// #docregion alice-class-signature
|
||
|
export class AliceComponent implements Parent
|
||
|
// #enddocregion alice-class-signature
|
||
|
{
|
||
|
name= 'Alice';
|
||
|
}
|
||
|
// #enddocregion alice
|
||
|
|
||
|
////// Cathy ///////////
|
||
|
/**
|
||
|
* Show we can inject a parent by component type
|
||
|
*/
|
||
|
// #docregion cathy
|
||
|
@Component({
|
||
|
selector: 'cathy',
|
||
|
template: `
|
||
|
<div class="c">
|
||
|
<h3>Cathy</h3>
|
||
|
{{alex ? 'Found' : 'Did not find'}} Alex via the component class.<br>
|
||
|
</div>`
|
||
|
})
|
||
|
export class CathyComponent {
|
||
|
constructor( @Optional() public alex: AlexComponent ) { }
|
||
|
}
|
||
|
// #enddocregion cathy
|
||
|
|
||
|
///////// ParentFinder //////
|
||
|
@Component({
|
||
|
selector: 'parent-finder',
|
||
|
template: `
|
||
|
<h2>Parent Finder</h2>
|
||
|
<alex></alex>
|
||
|
<alice></alice>`,
|
||
|
directives: [ AlexComponent, AliceComponent ]
|
||
|
})
|
||
|
export class ParentFinderComponent { }
|