How to get the same instance of a directive when using injection tokens in Angular?

Discussão em 'Angular' iniciado por marked-down, Dezembro 18, 2024.

  1. marked-down

    marked-down Guest

    I'm building a component, FeatureComponent, for a library I distribute in Angular. This component has a directive that is dependency-injected into its constructor that provides some custom animation logic on the component. This is good, and it works, but it hardcodes the component to requiring a dependency to this specific directive, like so:

    @Directive({
    selector: 'animDirective'
    })
    export class AnimDirective { ... }

    @Component({
    selector: '[feature-component]'
    })
    export class FeatureComponent {

    // Provides a reference to the `AnimDirective` instance on the component selector in the temple.
    constructor(private animDirective: AnimDirective) {}
    }


    This is then consumed, and FeatureComponent receives the instance of AnimDirective in its constructor that is bound to its selector:

    @Component({
    selector: 'app',
    template: `<form [animDirective] feature-component></form>`
    })
    export class AppComponent { ... }


    What I want is to make this relationship more loosely coupled, and for FeatureComponent to accept any compatible directive by using an InjectionToken in its constructor, rather than directly injecting a concrete instance of AnimDirective. For example, I want to inject an interface, AnimatesFeatures instead, so I could have multiple choices in how the FeatureComponent is animated:

    export class AnimDirective implements AnimatesFeatures {}
    export class FlashyDirective implements AnimatesFeatures {}


    I've tried doing this to FeatureComponent:

    @Component({
    selector: '[feature-component]'
    })
    export class FeatureComponent {
    constructor(@Inject('ANIMATES_FEATURES') directive: AnimatesFeatures) {}
    }


    And then consuming it like so by providing FlashyDirective from my parent AppComponent:

    @Component({
    selector: 'app',
    template: `<form [flashyDirective] feature-component></form>`,
    providers: [{
    provide: 'ANIMATES_FEATURES', useClass: FlashyDirective
    }]
    })
    export class AppComponent { ... }


    However, the instance of the directive that FeatureComponent receives is of a different instance to the one provided in the AppComponent template, and therefore, the FeatureComponent is unable to manipulate its appearance properly. How can I use an injection token to loosely couple this functionality, while still ensuring the FeatureComponent receives the same instance of the directive that is in the AppComponent template?

    Continue reading...

Compartilhe esta Página