In Angular 8 I was able to create base components (classes the actual component inhert from) with an “@Injectable” attribute. The Angular 9 compiler tells me:

The component YourComponent inherits its constructor from BaseComponent, but the latter does not have an Angular decorator of its own. Dependency injection will not be able to resolve the parameters of BaseComponent’s constructor. Either add a @Directive decorator to BaseComponent, or add an explicit constructor to RoleSelectDialogComponent.

What is the Angular 9 way of doing these things now? This works but looks somehow hacky:

@Component({
    selector: 'baseComponent',
    template: 'no-ui'
})

3

The clue is in the message

Either add a @Directive decorator to BaseComponent

Adding a @Directive() to it should do the trick.

I’m just going through an upgrade now, and my base component automatically has the @Directive() decorator added.

4

This is probably going to hit more people now that Angular 10 is out and the warning is now an error.

error NG2007: Class is using Angular features but is not decorated. Please add an explicit Angular decorator.

This blog entry shows some examples https://volosoft.com/blog/what-is-new-in-angular-10


In addition please note that ‘Angular features’ doesn’t just mean dependency injection. Even the presence of ngOnDestroy() in your base class will trigger this.

I solved it by renaming ngOnDestroy() to _ngOnDestroy() and called it from the subclass on destruction of the actual @Injectable(). This seems a little dangerous if I were to ever subclass it again and forgot to call _ngOnDestroy() but I’m not sure I had much choice.

2

As @Simon_Weaver said you may have a parent class such as :

export class BaseComponent implements OnDestroy {
  protected subscriptions: Subscription[] = [];

  ngOnDestroy(): void {
    this.subscriptions.filter(sub => !!sub).forEach(subscription => {
      subscription.unsubscribe();
    });
  }
}

Instead of adding ngOnDestroy to each children you can do that :

/* tslint:disable */
@Directive()
export class BaseComponent implements OnDestroy {
  protected subscriptions: Subscription[] = [];

  ngOnDestroy(): void {
    this.subscriptions.filter(sub => !!sub).forEach(subscription => {
      subscription.unsubscribe();
    });
  }
}

You will either need to add a decorator (@Directive) to the base class or remove any Angular interface implemented by the base class. This error started appearing after I upgraded an application to Angular 10. An abstract base class was implementing Angular OnInit interface. This class was later extended by actual component classes. Instead of adding an irrelevant decorator, I removed the OnInit implementation from the base class that fixed the error.

Make sure to export the base class

Ran into this again! This time I’d tried to get clever with my base class by deliberately not exporting it.

@Directive()
abstract class _SnippetDirective<P>

Angular said no!

The directive SnippetDirective inherits its constructor from _SnippetDirective, but the latter does not have an Angular decorator of its own. Dependency injection will not be able to resolve the parameters of _SnippetDirective’s constructor. Either add a @Directive decorator to _SnippetDirective, or add an explicit constructor to SnippetDirective.

But of course it DID have a directive. I think what’s happening is it doesn’t even recognize the base class as being a directive because it doesn’t have visibility into it. That’s a guess but logically it makes sense. Exporting the base class fixed it.