216 lines
		
	
	
		
			5.1 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
			
		
		
	
	
			216 lines
		
	
	
		
			5.1 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
/* tslint:disable:no-unused-variable component-selector-name one-line check-open-brace */
 | 
						|
/* tslint:disable:*/
 | 
						|
// #docplaster
 | 
						|
// #docregion
 | 
						|
import { Component, forwardRef, Optional, SkipSelf } from '@angular/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) => {
 | 
						|
    return { 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) => {
 | 
						|
    return { 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
 | 
						|
 | 
						|
//////// 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,
 | 
						|
  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,
 | 
						|
  providers:  [ provideParent(BobComponent) ]
 | 
						|
})
 | 
						|
export class BobComponent implements Parent {
 | 
						|
  name= 'Bob';
 | 
						|
  constructor( @SkipSelf() @Optional() public parent: Parent ) { }
 | 
						|
}
 | 
						|
 | 
						|
@Component({
 | 
						|
  selector:   'beth',
 | 
						|
  template:   templateB,
 | 
						|
// #docregion beth-providers
 | 
						|
  providers:  [ provideParent(BethComponent, DifferentParent) ]
 | 
						|
// #enddocregion beth-providers
 | 
						|
})
 | 
						|
export class BethComponent implements Parent {
 | 
						|
  name= 'Beth';
 | 
						|
  constructor( @SkipSelf() @Optional() public parent: Parent ) { }
 | 
						|
}
 | 
						|
 | 
						|
///////// 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
 | 
						|
})
 | 
						|
// #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> `,
 | 
						|
// #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>`
 | 
						|
})
 | 
						|
export class ParentFinderComponent { }
 |