1

In the update process of Angular 8 to Angular 9 the update script add's component decorators to baseclasses. This is documented in https://angular.io/guide/migration-undecorated-classes

In the documented example the selector is set in the base class decorator.

But how do you proceed if you want two different selectors in child components of the base class component?

Before:

class BaseMenu {}

@Component({
  selector: 'a-menu',
  template: '<div></div>'
})
export class AMenu extends BaseMenu {}

@Component({
  selector: 'b-menu',
  template: '<div></div>'
})
export class BMenu extends BaseMenu {}

After:

@Component(???)
class BaseMenu {}

@Component({
  selector: 'a-menu',
  template: '<div></div>'
})
export class AMenu extends BaseMenu {}

@Component({
  selector: 'b-menu',
  template: '<div></div>'
})
export class BMenu extends BaseMenu {}

The component decorator expects a 'selector'.

LuJaks
  • 1,047
  • 1
  • 10
  • 21

2 Answers2

3

Use the @Directive decorator, as specified in the link you posted. @Directive doesn't require a selector.

@Directive()
class BaseMenu {}

@Component({
  selector: 'a-menu',
  template: '<div></div>'
})
export class AMenu extends BaseMenu {}

@Component({
  selector: 'b-menu',
  template: '<div></div>'
})
export class BMenu extends BaseMenu {}
Kurt Hamilton
  • 12,490
  • 1
  • 24
  • 40
  • This causes a lint error "...should end with the suffix Directive". Also extending a component from a directive seems a bit dirty. – LuJaks Mar 19 '20 at 11:11
  • Disabling the lint rules for this part would work as a workaround. Thanks for your help. – LuJaks Mar 19 '20 at 11:34
3

Angular made heavy of decorators and meta-data (@Component, @Directive, @NgModule, ...). This meta-data and decorators are not inherited by the child components. So, you can just use a placeholder selector just to fill it in. See https://blog.bitsrc.io/component-inheritance-in-angular-acd1215d5dd8

@Component({
  selector: 'x-menu',
  template: '<div></div>'
})
class BaseMenu {}

@Component({
  selector: 'a-menu',
  template: '<div></div>'
})
export class AMenu extends BaseMenu {}

@Component({
  selector: 'b-menu',
  template: '<div></div>'
})
export class BMenu extends BaseMenu {}
  • This unfortunately causes a build error "1. If 'a-menu' is an Angular component then verify that it is part of this module." – LuJaks Mar 19 '20 at 11:11
  • Have you checked your NgModule for declarations? – Adson Rocha Mar 19 '20 at 11:16
  • See https://stackoverflow.com/questions/43937387/if-selector-is-an-angular-component-then-verify-that-it-is-part-of-this-mod – Adson Rocha Mar 19 '20 at 11:18
  • 1
    Listing the base component in the app.module declarations solved it. As stated in the error. I was not listed originally, because before the update the base class had not decorator. Added a decorator makes it mandatory to add it to the module declarations even if is just used as a base class. – LuJaks Mar 19 '20 at 11:33