Using hostDirectives inside Directives easily leads to error NG0309

See original GitHub issue

Which @angular/* package(s) are relevant/related to the feature request?

core

Description

By using the shiny new hostDirectives API, I’ve found myself easily running into error NG0309.

NG0309: Directive MyDirective matches multiple times on the same element. Directives can only match an element once.

In my case I am using a DestroyDirective (for handling rxjs subscriptions). Sample repository: https://github.com/TomTomB/multiple-same-host-directive-issue

In it is a component with a template, that uses 2 directives on the same element (app-a and app-b)

<div app-a app-b></div>

Both directives have the following logic:

@Directive({
  selector: '[app-a]',
  standalone: true,
  hostDirectives: [DestroyDirective],
})
export class ADirective {
  private readonly _destroy$ = inject(DestroyDirective).destroy$;
}

This results in the error mentioned above. The error is, of cause, not only specific to this exact use case. I fact, it’s a pretty big road block when thinking the new “composition way” of reusing code. Also, the error is really not that helpful for explaining, why this code is not working. This could especially be true when using 3rd party packages that use hostDirectives on their own.

Proposed solution

Using hostDirecitves inside a directive should never result in a NG0309 error.

Alternatives considered

Removing hostDirecitves from the Directive decorator - but that would be a big bummer imho.

Issue Analytics

  • State:closed
  • Created 10 months ago
  • Reactions:7
  • Comments:9 (3 by maintainers)

github_iconTop GitHub Comments

2reactions
alxhubcommented, Dec 9, 2022

I consider tricks like DestroyDirective to be an anti-pattern in the first place. The purpose of hostDirectives is not to provide some kind of injection mechanism for lifecycle hooks, but for one directive to compose behaviors from another. In that sense, it’s perfectly valid to disallow multiple directives attempting to apply the same host directive.

1reaction
TomTomBcommented, Dec 9, 2022

Hey @alxhub, I think just focusing on my example DestroyDirective is a litte short-sighted, since this issue applies to all directives. Let’s use the angular/components library as an other example. They are currently using class mixins for things like a disabled boolean. So with hostDirectives I would assume that we should now be able to create a CanDisableDirective. Applying this to my issue repo would yield the same result - NG0309. So composition is a thing now, but not really.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Use directive in host of another Directive - angular
I want to add a directive to an element from another directive by using the host property, but there doesn't seem to be...
Read more >
Squeezing Angular Directives. Beyond the boundaries - Medium
In this article, we'll examine the features and limitations of every type of directive and how to mix all their features into one...
Read more >
Angular Directive Tutorial With Example | Custom Directives
This blog will introduce you to Angular Directive with sample codes for better understanding. You will also learn about Custom Directives in ......
Read more >
Missing directives should cause Template Error #20588 - GitHub
Current behavior. When trying to use a directive that is not included in the module, the angular-compiler fails silently, this is not the...
Read more >
What is the use @error and @debug directives in SASS
It completely stops the Sass compiler and displays the SassScript expression values as fatal errors. We can use this directive to send a...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found