4

How can I understand when to use ng-template versus a Component in Angular?

Say I want to display a UI and I'll use it within the same component at several places. Should I create a template or a separate component?

<ul>
<li> ... </li>
<li> ...</li>
</ul>

An issue I am facing is that I have the above UI which I want to use at several places within a component. However, I want to give a unique id to each ul and also set attributes of li. I thought of using ng-template but I am unable to figure out how to access ul and li once the template is inserted using createEmbeddedView.

See this demo - https://stackblitz.com/edit/angular-bqm11b

My Component's HTML looks like

<ng-template #tmpl>
    <ul>
    <li> ... </li>
    <li> ...</li>
    </ul>
</ng-template>

I have created two ng-containers

<ng-container #vc1></ng-container>
<ng-container #vc2></ng-container>

I am inserting #tmpl in vc1 and vc2 but the final HTML looks like

<ul>
<li> ... </li>
<li> ...</li>
</ul>
<ul>
<li> ... </li>
<li> ...</li>
</ul>

I reckon that if I use a Component, I can set id and other attributes but if I use a template, I cannot do so because I cannot access ul and li and distinguish between the different ul and li. I don't want to mix pure JS in my code so I want a solution which is more Angular (ViewChild, ContentChild, Rendere2).

Am I correct that:

  1. In template, I cannot access ul and li and distinguish between the different ul and li.
  2. I should use template if I want vanilla UI but if I want to manipulate DOM then it is better to use a separate component?
halfer
  • 19,824
  • 17
  • 99
  • 186
Manu Chadha
  • 15,555
  • 19
  • 91
  • 184

1 Answers1

4

It's quite simple. If you want a component that will be used in other components (i.e in the same route or in different route). You can opt for Component.

If you want to display different HTML content based on some Condition in same component. You can opt for ng-template.

<ng-template #tmpl>
    <ul>
    <li> ... </li>
    <li> ...</li>
    </ul>
</ng-template>

You can use @ViewChild('tmpl'), if you want to access only one Template instance. You can use @ViewChildren('tmpl'), if you want to access more than one template instance.

Hope, this makes clear.

Suresh Kumar Ariya
  • 9,516
  • 1
  • 18
  • 27
  • Thanks. Once I have accessed `tmpl`, how do I access ul and li which are inside it? – Manu Chadha Aug 08 '18 at 09:30
  • If you console.log(this.tmpl); To access UL=> this.tmpl.nativeElement.nextElementSibling. To access LI=> this.tmpl.nativeElement.nextElementSibling.children – Suresh Kumar Ariya Aug 08 '18 at 10:11
  • Thanks but that doesn't look like a very friendly way to find elements esp if the template has several elements. Also, I have heard that directly calling methods or properties of `nativeElement` isn't encouraged due to portability issues and one should rather use `Renderer2`. – Manu Chadha Aug 08 '18 at 10:14
  • Please look at this. In summary, I passed `Context` object when instantiating a `template`, I used the values from the `context` object to assign unique ids to the elements of the template. I suppose then I can do `document.querySelector` to retrieve specfic elements (though I haven't tried it) - https://stackoverflow.com/questions/51764692/how-to-delete-a-specific-view-from-viewcontainer-angular/51770957#51770957 – Manu Chadha Aug 09 '18 at 15:37