132

Lets suppose we have html block in file:

<div id="text">Text</div>

How can I reuse this html code below in the same file, I mean something like this:

<re-use id="text"></re-use>

Is it possible?

0

5 Answers 5

237

I think you wanted to reuse the same html block again. If i understand you correctly, below code should help

<ng-template #MsgRef >
        {{ mycontent }}
</ng-template>

To reuse above block in the same template,

 <ng-template [ngTemplateOutlet]="MsgRef"></ng-template> //reuse any number of times
Sign up to request clarification or add additional context in comments.

6 Comments

You can user ng-content to show the template instead
Any idea how to make this work outside the component/template html that defines the ng-template ref?
This is great solution but somehow am not able to create more the 2 ng template on one component
For the first block (with content definition) to be shown as well, you may want to add [ngIf]="true" to it, e.g. <ng-template #MsgRef [ngIf]="true">
@Krishnan to use it in multiple components I would say extract that logic in a separate component.
|
97

Creating a new component is the most common way, but sometimes you only need some local markup to be repeated and ng-template allows that.

What is interesting is that it's even possible to pass a context to be able to use data binding:

<ng-template #tplPerson let-person>
    <span class="person-id">{{person.id}}</span>
    <span class="person-alias" *ngIf="!!person.alias">"{{person.alias}}"</span>
    <span class="person-name">{{person.name}}</span>
</ng-template>

let-person without a value defines the context variable person with the value set to $implicit when instantiating the template:

<ng-template *ngTemplateOutlet="tplPerson; context: {$implicit: thePerson}"></ng-template>

See more options in the documentation of NgTemplateOutlet.

2 Comments

Excellent tip about pass a variable to the template, just what I need
This looks pretty similar to knockoutjs xD
36

I might be late to the party. There are some answers though, but I couldn't achieve it with what is described in above answers I still felt that someone might need a bit of direction.

Key points that are not defined in any of the answers clearly.

  1. Consider you have a template which is binding some values in it. So you have to attach a context object in order make template binding work.
<ng-template #invoicesTemplate let-paymentInvoices="paymentInvoices">
    ...
</ng-template>

note that let-anyVariableName for template and "paymentInvoices" is the class variable that you are passing.

in usage

<ng-template *ngTemplateOutlet="invoicesTemplate; context: {paymentInvoices : paymentInvoices} "></ng-template>
  1. You have to define template first and then use it anywhere you want to. Just think of a function declaration. But until unless you don't call function it wont have any affect.

Overall code declaration of template

<ng-template #invoicesTemplate let-paymentInvoices="paymentInvoices">
  <div class="row">
    <div class="col-sm-12">
      <div class="tags-group">
        <div class="tag" *ngFor="let invoice of paymentInvoices">
          <div class="tag-body">
            <span>{{invoice.invoiceNo }}</span>
            <span (click)="removeInvoice(invoice)"><i title="remove" >x</i></span>
          </div>
        </div>
      </div>
    </div>
  </div>
</ng-template>

calling/usage

<ng-template *ngTemplateOutlet="invoicesTemplate; context: {paymentInvoices : paymentInvoices} "></ng-template>

You can use it any number of times you want.

3 Comments

maybe late, but really contributed well, your explanation was the most elaborate and understandable, this should be the top answer
working well in 2022
Works still on Angular 17. Don't forget to import NgTemplateOutlet (@angular/common) in your component.
8

You can create a custom html-tag using angular then import that component in your module that wants to use those custom-tags. Then you'll be allowed to use the same tag in your html page. Created a small example that can maybe help you understand ?

https://stackblitz.com/edit/angular-stackoverflow

2 Comments

this method sadly means you can't use it a TemplateRef though
this is not what's asked. You have showcased how to reuse a component.
1

This can be done with help of a custom directive in a more standard way.

In directive.ts

import { Directive } from '@angular/core';
@Directive({
  selector: '[cardItem]'
})
export class CardItemDirective {}

In component.ts

import { Component, ContentChild, Input, TemplateRef } from '@angular/core';
import { CardItemDirective } from './card-item.directive';
import { ListItemDirective } from './list-item.directive';

@Component({
  selector: 'card-or-list-view',
  templateUrl: './card-or-list-view.component.html'
})
export class CardOrListViewComponent {

  @Input() items: any[] = [];

  @Input() mode: 'card' | 'list' = 'card';

  // Read in our structural directives as TemplateRefs
  @ContentChild(CardItemDirective, {read: TemplateRef}) cardItemTemplate;
  @ContentChild(ListItemDirective, {read: TemplateRef}) listItemTemplate;

}

in component.html

<ng-container [ngSwitch]="mode">
<ng-container *ngSwitchCase="'card'">
  <ng-container *ngFor="let item of items">
    <ng-container *ngTemplateOutlet="cardItemTemplate"></ng-container>
  </ng-container>
</ng-container>
<ul *ngSwitchCase="'list'">
  <li *ngFor="let item of items">
    <ng-container *ngTemplateOutlet="listItemTemplate"></ng-container>
  </li>
</ul>
</ng-container> 

You can find more details in this link

1 Comment

When would you use this technique vs. just creating a component and re-using it in the same loop, as needed?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.