I am currently importing a third party component. For my use case I need to override that specific component template.
Since this is a third party component, and imported via npm package, I don't want to change the component so I don't have to update it everytime the package is updated.
Is there any way to overwrite the template of another component?
I know you can use <ng-content>
if you want to inject some element. But here is not viable.
The html is something like this:
<third-party-component [items]="items" [example]="example">
The controller is something like this:
import {THIRD_PARTY_DIRECTIVES} from 'ng2-select/ng2-select';
@Component({
selector: 'example-component',
directives: [THIRD_PARTY_DIRECTIVES]
})
export class Example {
private items: Array<string> = [
'whatever', 'whatever2', 'whatever3'
];
}
Is there any way I can specify the template I want for <third-party-component>
without editing that specific component declaration? Or even extend it only ?
After playing around with it. A simple extend will work for my use case.
Basically I created a class that extends the thirdPartyClass
.
What happens here is that I am overwriting the template for the thirdPartyClass
by creating my own selector and importing only the class.
Something like this:
import {component} from 'angular2/core';
import {thirdPartyClass} from 'example/example';
@Component({
selector: 'my-selector',
template: '<div>my template</div>'
})
export class MyOwnComponent extends thirdPartyClass {
constructor() {
super()
}
}
Notes:
- If you are using this method, don't forget to import any pipes that are used in the
thirdPartyClass
template.
- If the functionality is updated in the
thirdPartyClass
that depends upon the template, you'll need to update by hand.
- I prefered this solution to refering to the ReflectMetaData because its a simple extend instead of accessing the annotations and force changing it.
You can use Reflect to change metadata of component. Here's the super simple example:
import {Component} from 'angular2/core'
@Component({
selector: 'thing',
template: `Hi!`,
})
export class Thing {}
annotations = Reflect.getMetadata('annotations', Thing);
for (let i = 0; i < annotations.length; i += 1) {
if (annotations[i].constructor.name === 'ComponentMetadata') {
annotations[i].template = 'Ho!';
break;
}
}
@Component({
selector: 'my-app',
directives: [Thing],
template: `<thing></thing>`,
})
export class App {}
Just make sure you update template before injecting it into parent component. Also check which metadata you need to access, might be DirectiveMetadata
in your case.