Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular reusable template

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.

like image 313
Makla Avatar asked Sep 06 '17 10:09

Makla


People also ask

How to reuse HTML template in Angular?

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.

Can Angular component have multiple templates?

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.

Can a component have multiple 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.

What is Templateref in Angular?

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() .


1 Answers

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.

like image 127
Max Koretskyi Avatar answered Oct 09 '22 23:10

Max Koretskyi