126

I have some components like CricketComponent, FootballComponent, TennisComponent etc. All These Classes have some common properties :- TeamName, teamSize, players etc which are @Input().

Now I created a BaseComponent class, defined all these properties in there and this baseComponent class will be extended by cricket/football/tennis/etcComponents.

baseComponent.ts

export class BaseComponent {

    @Input() TeamName: string;
    @Input() teamSize: number;
    @Input() players: any;

}

CricketComponent.ts

@Component({
  selector: 'app-cricket',
  templateUrl: './cricket.component.html',
  styleUrls: ['./cricket.component.scss']
})
export class cricketComponent extends BaseComponent implements OnInit {

  constructor() {
    super();
  }

  ngOnInit(): void {
  }

}

I am getting this error:

ERROR in src/app/base-screen.ts:4:14 - error NG2007:

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

abhay tripathi
  • 3,547
  • 4
  • 20
  • 25
  • 1
    export abstract class BaseComponent { @Input() TeamName: string; @Input() teamSize: number; @Input() players: any; } - try to add abstract – critrange Jul 28 '20 at 02:18
  • I am not using any abstract class I have just created new component but i am getting "Class is using Angular features but is not decorated. Please add an explicit Angular decorator.(-992007)" Could you please guide me on above – sharma_kunal Feb 11 '23 at 17:29

8 Answers8

136

You'll need to add a @Component decorator to that base class (which should probably also be declared abstract).

This is the bare minimum you can get away with in Angular 9:

import { Component } from '@angular/core';

@Component({
  template: ''
})
export abstract class BaseComponent {

    @Input() teamName: string;
    @Input() teamSize: number;
    @Input() players: any;
}

For Angular 10+, see this answer.

Mauricio Gracia Gutierrez
  • 10,288
  • 6
  • 68
  • 99
Robby Cornelissen
  • 91,784
  • 22
  • 134
  • 156
101

From Angular 10, you can fix this issue by adding the decorator @Injectable() to your abstract base class like this:

@Injectable()
export abstract class BaseComponent {    
    @Input() teamName: string;
    @Input() teamSize: number;
    @Input() players: any;
}
Anh Hoang
  • 2,242
  • 3
  • 22
  • 23
  • I seem to get build errors with this solution when my extending component has an attribute selector, like `li[ng-list-item]`. I get something like `Attribute "teamName" does not exist on li`. Using Directive worked. – nomadoda Dec 07 '20 at 10:05
  • This is the only solution which worked for me! – JSON Derulo Dec 18 '20 at 12:33
  • 2
    This is a big one for Angular 10 as they changed how strict the compiler is for classes without decorators https://angular.io/guide/migration-injectable – Brad K Jan 06 '21 at 21:27
  • 5
    This was making `@Input()`s defined by my base class `undefined`. I had to switch to `@Directive()` instead. This is what I see in Angular 11 at least, not sure about others. – adamdport Jan 21 '22 at 20:56
  • 15
    The correct annotation is `@Directive()`. See https://angular.io/guide/migration-undecorated-classes or the answer https://stackoverflow.com/a/68823687/318317 – Daniel Rose Apr 13 '22 at 11:53
  • 1
    : Cannot find name 'Injectable'. – Saige Zhang Jun 09 '22 at 21:17
  • @SaigeZhang it'll be `import { Injectable } from '@angular/core';` – Joel Balmer Nov 24 '22 at 10:00
  • I am not using any abstract class I have just created new component but i am getting "Class is using Angular features but is not decorated. Please add an explicit Angular decorator.(-992007)" Could you please guide me on above – – sharma_kunal Feb 11 '23 at 17:30
  • if you need lifecycle hooks in this class then you will see lint errors with @Injectable – Vyacheslav Zhabitsky Apr 25 '23 at 08:16
38

While the accepted answer is correct in using @Component, one minor downside is that it requires all constructor argument types to be resolvable by DI. So if your base class constructor takes a constant/literal - say, an enum - as a flag, you're going to have to set up a corresponding DI provider/token just to get it to compile.

You can however also resolve NG2007 using the @Directive decorator instead, which doesn't require DI compatibility

David G
  • 541
  • 4
  • 11
  • The `@Directive` decorator is what Angular's schematics (ie. [`ng update`](https://angular.io/cli/update)) will automatically add – adamdport Jan 21 '22 at 20:05
21

See also: Missing @Directive()/@Component() decorator migration

Before:

export class BaseComponent {
    @Input() TeamName: string;
    @Input() teamSize: number;
    @Input() players: any;
}

After:

@Directive()
export class BaseComponent {
    @Input() TeamName: string;
    @Input() teamSize: number;
    @Input() players: any;
}
Community
  • 1
  • 1
FXLima
  • 337
  • 2
  • 5
1

If you are experiencing this in Angular 15, use an exact version of TypeScript. 4.8.2 worked for me.

npm i typescript@4.8.2 -D --save-exact
elonaire
  • 1,846
  • 1
  • 11
  • 17
1

Just add @Injectable() decorator to your class, and you can import it from the following path, import { Injectable } from '@angular/core';

0

I had a similar situation when running ng serve. I was getting that error for 3rd party libraries and for all my Angular components even though they were decorated.

If you're having this problem, see this answer for Angular 11 'error NG2007: Class is using Angular features but is not decorated.' But the class is Decorated

colossatr0n
  • 2,215
  • 1
  • 12
  • 18
0

For These errors : NG6001: The class 'XComponent' is listed in the declarations of the NgModule 'AppModule', but is not a directive, a component, or a pipe. Either remove it from the NgModule's declarations, or add an appropriate Angular decorator.

NG2003: No suitable injection token for parameter 'A' of class 'Y'.

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

You may be writing the new class between @Component declaration and Component class.

ex.

// export class Y{ // }

@Component({
  selector: 'app-X',
  templateUrl: './X.component.html',
  styleUrls: ['./X.component.css']
})



export class XComponent implements OnInit {

todos : Y[]  = [
  new Y(1 ),
  new Y(2 ),
  new Y(3 )
]
  
  constructor() { }

  ngOnInit(): void {
  }

}

//export class Y{ //}

i.e. if you have more than one class . let say class XComponent and Class Y, where class Y is being used in class XComponent , then write code for class Y either above @Component({}) or below class XComponent