inherit two component in angular with different constructor
I would suggest a different approach.
Make the class available to DI by annotating it with @Injectable
Then extend your parent component as usual: ChildComponent extend MyCom1Component
and inject your MyClass1
using the constructor of ChildComponent
Finally call the parent's constructor with the instance of the class you just injected.
constructor(public myclass1: MyClass1) {
super(myclass1);
}
Angular doesn't allow Multiple Inheritance
. You can extend only one class
in angular, although you can implement multiple interfaces
. But there is a way you can do multiple inheritance (only in say)
using TypeScript Mixins
.
The only downside
with mixins
is that you will have to define all the used base class methods in the child class
. [ Note - This is not actual inheritance. Basically, You are adding all Base class attributes to Child Class. ]
Also, you will have to declare
a mixin
method somewhere in your code which will do all the heavy-lifting. (Preferrably the app.module to have global access)
.
PFB the mixin
method:
function applyMixins(derivedCtor: any, baseCtors: any[]) {
baseCtors.forEach(baseCtor => {
Object.getOwnPropertyNames(baseCtor.prototype).forEach(name => {
if (name !== 'constructor') {
derivedCtor.prototype[name] = baseCtor.prototype[name];
}
});
});
}
REFERENCE - https://www.stevefenton.co.uk/2014/02/TypeScript-Mixins-Part-One/
PFB the snippet for your ChildComponent
. I have added the mixin
method in your ChildComponent
itself. You can place the same anywhere in your code.
export class ChildComponent {
propertyClass1: string;
propertyComp1:string;
sayHelloClass: (value) => void;
init: (value) => void;
sayHelloComponent: (value) => void;
constructor(private service: Service1Service) {
// super()
}
ngOnInit() {
this.applyMixins(ChildComponent, [MyCom1Component,MyClass1]);
this.sayHelloClass(this.propertyClass1);
this.init("hoohoho");
this.sayHelloClass(this.propertyClass1);
this.sayHelloComponent(this.propertyComp1);
}
applyMixins(derivedCtor: any, baseCtors: any[]) {
baseCtors.forEach(baseCtor => {
Object.getOwnPropertyNames(baseCtor.prototype).forEach(name => {
if (name !== 'constructor') {
derivedCtor.prototype[name] = baseCtor.prototype[name];
}
});
});
}
}
You can do it using Typescript mixins. Angular Material does it in its project, you can check it's source code
But this approach is far from perfect, since it adds a lot of boilerplate and complexity to the code that you may not need. So if you can avoid that, better.
Said that, I have forked your stackblitz project adding this solution mentioned.
In your code, you are also trying to do Typescript mixins, but you are never extending the class MyCom1Component, it seems that, but in this code below, MyCom1Component acts as a variable name! not as a class!
const addMyClassOneInheritance = <T extends new(...args: any[]) => any>(MyCom1Component: T) => {
return class extends MyCom1Component /* THIS IS A VARIABLE NAME */ {
constructor(...args: any[]) {
super(...args);
}
};
};
In resume, what you have to do with this approach, is separate the class logic in the respective mixins, like:
export function mixinMyCom1Component<T extends Constructor<{}>>(base: T): MyCom1ComponentCtor & T {
return class extends base {
propertyComp1 = "MyCom1";
constructor(...args: any[]) { super(...args); }
sayHelloComponent(value:string){console.log('component say'+ value)}
};
}
export function mixinMyClass1<T extends Constructor<{}>>(base: T): MyClass1Ctor & T {
return class extends base {
propertyClass1 = "MyClass1"
constructor(...args: any[]) { super(...args); }
init(value:string){
this.propertyClass1 = value;
}
sayHelloClass(value:string){console.log('class say'+ value)}
};
}
After that, you can compose the ChildComponent like this:
export class ChildComponentBase {
constructor() {}
}
export const _ChildComponentMixinBase = mixinMyClass1(mixinMyCom1Component(ChildComponentBase));
@Component({...})
export class ChildComponent extends _ChildComponentMixinBase {
constructor(private service: Service1Service) {
super()
}
}
PD: See the stackblitz example, since in this code posted there is missing some of the boilerplate and typings needed to achieve it correctly.
Hope this can help somehow!