Is it possible to write reusable ng-template
? A lot of my components use exactly the same ng-template
.
For example:
<kendo-grid>
<kendo-grid-column field="group">
<ng-template kendoGridEditTemplate let-dataItem="dataItem" let-formGroup="form">
<kendo-dropdownlist #listGroups [data]="groups"
textField="title"
valueField="id"
[valuePrimitive]="true"
[filterable]="true"
[formControl]="form.get('groupId')">
</kendo-dropdownlist>
</ng-template>
</kendo-grid-column>
</kendo-grid>
I do not want to repeat this template and logic behind in all my components. I could write custom component and shrink this code to:
<kendo-grid>
<kendo-grid-column field="group">
<ng-template kendoGridEditTemplate let-dataItem="dataItem" let-formGroup="form">
<my-custom-component [formControl]="form.get('groupId')">
</my-custom-component>
</ng-template>
</kendo-grid-column>
</kendo-grid>
but I want to do more:
<kendo-grid>
<kendo-grid-column field="group">
<ng-template [ngTemplateOutlet]="templateFromAnotherSource">
</ng-template>
</kendo-grid-column>
</kendo-grid>
I found this thread and this which describes ngTemplateOutlet
, but not how to share templates between multiple components.
Using this template can be done by using the ngTemplateOutlet directive on an ng-container component. We can add a context object to ngTemplateOutlet which allows us to provide it with a value to use as the item we have defined on our ng-template.
You can simply extend your base component and overwrite the template. This allows you to have different components with the exact same functionality, but different templates.
Note Although it's possible for a component to render multiple templates, we recommend using an if:true|false directive to render nested templates conditionally instead. Create multiple HTML files in the component bundle.
TemplateReflinkRepresents an embedded template that can be used to instantiate embedded views. To instantiate embedded views based on a template, use the ViewContainerRef method createEmbeddedView() .
The problem is that ng-template
has to be compiled. To understand why read Here is what you need to know about dynamic components in Angular.
Now, a template can only be compiled as part of a component right now. So you need to define a component with this template and then you can get access to this template factory either using viewChild
or a directive. With viewChild
you depend on life-cycle hooks and change detection so I'd go with directive approach. Here is the pseudocode:
@Component() {
template: '<ng-template requestor>...</ng-template>'
}
class NgTemplateProviderComponent {
t: TemplateRef;
register(t) {
this.t = t;
}
}
@Directive() {
selector: 'requestor;
}
class TemplateRequestor {
constructor(t: TemplateRef, p: NgTemplateProviderComponent) {
p.register(t);
}
}
To learn more about this approach of using a directive to get templateRef read Here is how to get ViewContainerRef before @ViewChild query is evaluated.
Then, you need to get access to the NgTemplateProviderComponent
component factory, create its instance to get the templateRef
:
class SomeComponent {
constructor(r: ComponentFactoryResolver, i: Injector) {
const f = r.resolveComponentFactory(NgTemplateProviderComponent);
const templateRef =f.create(i).instance.t;
}
}
and only then you can use ngTemplateOutlet
directive to render the template.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With