Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Class inheritance support

Tags:

angular

I am building an Angular2 application in Typescript and would like to use the class system functionality (read: class inheritance) offered by Typescript. However, it seems that Angular2 is not playing nice with derived classes. I am looking for some help in getting my application to work.

The problem I am facing is that I have a base class and derive a few child classes from there. When I am building up my component tree, I would like to be able to access the parent/children of the components (either way is fine). From what I understand, Angular2 offers two options to accomplish that:

  1. Inject the parent into the child component
  2. Use ContentChildren (or ViewChildren) to access the children of the component.

Both work fine if you know the type of the class you are working with (ChildComponent), but seem to fail when you try to use the base class of these components (BaseComponent) as selector.

To visualize it in some code (see this Plunker for a live demo), I have an application component/class as follows:

@Component({   selector: 'my-app',   template: `<parent-comp>       <child-comp1></child-comp1>       <child-comp1></child-comp1>       <child-comp2></child-comp2>     </parent-comp>`,   directives: [ParentComponent, ChildComponent1, ChildComponent2] }) export class MyApplication  { } 

The Base Class and Child Classes are defined as:

export class BaseComponent {   // Interesting stuff here }  @Component({   selector: 'child-comp2',   template: '<div>child component #2</div>' }) export class ChildComponent2 extends BaseComponent { }  @Component({   selector: 'child-comp1',   template: '<div>child component #1</div>' }) export class ChildComponent1 extends BaseComponent { } 

And the Parent class has some logic to count its children.

@Component({   selector: 'parent-comp',   template: `<div>Hello World</div>    <p>Number of Child Component 1 items: {{numComp1}}    <p>Number of Child Component 2 items: {{numComp2}}    <p>Number of Base Component items: {{numBase}}    <p><ng-content></ng-content>   ` }) export class ParentComponent implements AfterContentChecked  {    @ContentChildren(ChildComponent1) contentChild1: QueryList<ChildComponent1>   @ContentChildren(ChildComponent2) contentChild2: QueryList<ChildComponent2>   @ContentChildren(BaseComponent) contentBase: QueryList<BaseComponent>   public numComp1:number   public numComp2:number   public numBase:number    ngAfterContentChecked() {     this.numComp1 = this.contentChild1.length     this.numComp2 = this.contentChild2.length     this.numBase = this.contentBase.length   } 

(Again, you can see a live demo here)

The output for the first two counters is as expected. There are 2 ChildComponent1 and 1 ChildComponent2 children. Unfortunetely, the BaseComponent counter doesn't show the sum of these counters, but shows 0. It doesn't find any class that is of type BaseComponent in the children.

The same thing happens when ParentComponent also extends from BaseComponent and you want to Inject it into a ChildComponent. The Injector will require the specific type of the ParentComponent and can't work with the base class.

Any clues on how to work with derived classes in Angular2? Am I missing something or trying something impossible?

like image 617
Sjoerd Avatar asked Mar 17 '16 14:03

Sjoerd


People also ask

What is inheritance support in Java?

Java supports only Single, Multilevel, and Hierarchical types of inheritance. Java does not support Multiple and Hybrid inheritance.

What are the classes of inheritance?

Inheritance allows us to define a class that inherits all the methods and properties from another class. Parent class is the class being inherited from, also called base class. Child class is the class that inherits from another class, also called derived class.

Does class support multiple inheritance?

Multiple inheritance is not supported by Java using classes, handling the complexity that causes due to multiple inheritances is very complex.


1 Answers

Add a provider to each derived component, aliasing the base component to the derived component:

@Component({   selector: 'child-comp2',   template: '<div>child component #2</div>',   providers: [{provide: BaseComponent, useExisting: forwardRef(() => ChildComponent2) }] }) export class ChildComponent2 extends BaseComponent { }  @Component({   selector: 'child-comp1',   template: '<div>child component #1</div>',   providers: [{provide: BaseComponent, useExisting: forwardRef(() => ChildComponent1) }] }) export class ChildComponent1 extends BaseComponent { } 

Plunker: http://plnkr.co/edit/5gb5E4curAE2EfH2lNZQ?p=preview

like image 147
Michael Liu Avatar answered Oct 11 '22 12:10

Michael Liu