I've been looking for how to create a good Component parent to improve the DRY of my code. Inheriting a Component from a Component requires repetition of the constructor(<services>){}
and this is counter to the DRY objective. I fell across a warning message from Angular which suggested inheriting from a Directive ??? So I tried it, it seems to work.
Are you aware of any risks or issues I will create with this approach?
Angular docs hint at an "abstract" directive, so perhaps there is something intentional here. In any event a working example is here on stackblitz. The key parent and child files in their entirety are below.
import { Directive, OnDestroy } from '@angular/core';
import { Tag, TagSubject } from './tag.store';
@Directive() // This was the unexpected success
export class BaseTagDirective implements OnDestroy {
subs: any = [];
tag: Tag;
constructor( // This is the constructor I did NOT want to repeat
private tagstore: TagSubject
) {
this.tag = new Tag();
}
subTag(tagname: string) {
this.subs.push(
this.tagstore.subject(tagname).asObservable().subscribe((tag: any) => {
this.tag.name = tag.name;
this.tag.value = tag.value;
})
);
}
ngOnDestroy() { // unrelated to the question, just a subscription tidy up.
for (let i = 0; i < this.subs.length; i ) {
this.subs[i].unsubscribe();
}
}
}
And the resulting child is ...
import { Component, OnInit, Input } from '@angular/core';
import { BaseTagDirective } from './base.directive';
@Component({
selector: 'app-value',
templateUrl: './value.component.html'
})
export class ValueComponent extends BaseTagDirective implements OnInit {
@Input() tagname: any;
// look no constructor :D
ngOnInit() {
this.subTag(this.tagname);
}
}
The tag store referred to by the parent includes the following items.
update(tagname: string, value: number) {
this.tags[tagname].value = value;
this.subjects[tagname].next(this.tags[tagname]);
}
subject(tagname: string) {
this.subjects[tagname] = new BehaviorSubject<Tag>(this.tags[tagname]);
this.subjects[tagname].next(this.tags[tagname]);
return this.subjects[tagname];
}
CodePudding user response:
from Angular 14 there is a handy feature for your use case - global inject
. You can now move your dependencies away from a constructor. So no repitition of injection would be required
class Parent {
service1 = inject(ServiceOne);
}
class Child extends Parent {
service2 = inject(ServiceTwo);
}
CodePudding user response:
Hey Man got something that will help you out check this Article