I would like to create extensions for some components already deployed in Angular 2, without having to rewrite them almost completely, as the base component could undergo changes and wish these changes were also reflected in its derived components.
I created this simple example to try to explain better my questions:
With the following base component app/base-panel.component.ts
:
import {Component, Input} from 'angular2/core';
@Component({
selector: 'base-panel',
template: '<div class="panel" [style.background-color]="color" (click)="onClick($event)">{{content}}</div>',
styles: [`
.panel{
padding: 50px;
}
`]
})
export class BasePanelComponent {
@Input() content: string;
color: string = "red";
onClick(event){
console.log("Click color: " + this.color);
}
}
Would you like to create another derivative component only alter, for example, a basic component behavior in the case of the example color, app/my-panel.component.ts
:
import {Component} from 'angular2/core';
import {BasePanelComponent} from './base-panel.component'
@Component({
selector: 'my-panel',
template: '<div class="panel" [style.background-color]="color" (click)="onClick($event)">{{content}}</div>',
styles: [`
.panel{
padding: 50px;
}
`]
})
export class MyPanelComponent extends BasePanelComponent{
constructor() {
super();
this.color = "blue";
}
}
Complete working example in Plunker
Note: Obviously this example is simple and could be solved otherwise no need to use inheritance, but it is intended only to illustrate the real problem.
As you can see in the implementation of the derivative component app/my-panel.component.ts
, much of the implementation was repeated, and the single part really inherited was the class
BasePanelComponent
, but the @Component
had to basically be completely repeated, not just the changed portions, as the selector: 'my-panel'
.
Is there some way to make a literally full inheritance of a component Angular2, inheriting the class
definition of the markings/annotations, as for example @Component
?
Edit 1 - Feature Request
Feature request angular2 added to the project on GitHub: Extend/Inherit angular2 components annotations #7968
Edit 2 - Closed Request
The request was closed, for this reason, that briefly would not know how to merge the decorator will be made. Leaving us with no options. So my opinion is is quoted in the Issue.
Components can be extended as same as a typescript class inheritance, just that you have to override the selector with a new name. All Input() and Output() Properties from the Parent Component works as normal
Update
@Component is a decorator,
Decorators are applied during the declaration of class not on objects.
Basically, decorators add some metadata to the class object and that cannot be accessed via inheritance.
If you want to achieve the Decorator Inheritance I would Suggest writing a custom decorator. Something like below example.
Refer: https://medium.com/@ttemplier/angular2-decorators-and-class-inheritance-905921dbd1b7
update
Component inheritance is supported since 2.3.0-rc.0
original
So far, the most convenient for me is to keep template & styles into separate
*html
&*.css
files and specify those throughtemplateUrl
andstyleUrls
, so it's easy reusable.If anyone is looking for an updated solution, Fernando's answer is pretty much perfect. Except that
ComponentMetadata
has been deprecated. UsingComponent
instead worked for me.The full Custom Decorator
CustomDecorator.ts
file looks like this:Then import it in to your new component
sub-component.component.ts
file and use@CustomComponent
instead of@Component
like this:You can use
<ng-content></ng-content>
directive for this.For example:
Header Component
Custom Header Component
<header-component>This is header</header-component>
prints This is header<custom-header-component>This is header</custom-header-component>
prints This is custom header This is header