Angular Component inherits without repeating the constructor

Discussão em 'Angular' iniciado por jwal, Março 15, 2025.

  1. jwal

    jwal Guest

    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. 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.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];
    }

    Continue reading...

Compartilhe esta Página