How can I repeat a piece of HTML multiple times without ngFor and without another @Component?

I want to repeat a piece of HTML, multiple times in my template.

But I want it to be repeated at different places on my page. This means that ngFor is not the solution as the pieces would be repeated directly one after the other.

A 'working solution' would be to define a specific @Component for my repeated HTML, and do something like that :

<p>Whatever html</p>
<my-repeated-html></my-repeated-html>
<h4>Whatever</h4>
<my-repeated-html></my-repeated-html>

But I find it overkill to create a dedicated component for doing something like that, it has no functional meaning and is only required by the HTML structure I want to set up.

Is there really nothing in ng2 template engine to allow me to define an "inner template" and use it wherever I need it in the current template?


update Angular 5

ngOutletContext was renamed to ngTemplateOutletContext

See also https://github.com/angular/angular/blob/master/CHANGELOG.md#500-beta5-2017-08-29

original

The recently added ngTemplateOutlet might be what you want

<template [ngTemplateOutlet]="templateRefExpression" [ngOutletContext]="objectExpression"></template>

It can currently be used like

<template #templateRef>
    <pre>{{self | json }}</pre>
</template>

<template [ngTemplateOutlet]="templateRef"></template>

A template can also be passed to a child component to be rendered there

@Component({
  selector: 'some-child',
  providers: [],
  template: `
    <div>
      <h2>Child</h2>
<template [ngTemplateOutlet]="template" ></template>
<template [ngTemplateOutlet]="template" ></template>
    </div>
  `,
  directives: []
})
export class Child {
  @ContentChild(TemplateRef) template:TemplateRef;
}

to be used like

<some-child>
  <template>
    <pre>{{self | json }}</pre>
  </template>
</some-child>

stackblitz example

Another Plunker example
that uses data passed as

<template [ngTemplateOutlet]="..." [ngOutletContext]="templateData"

This way ngOutletContext can be used in the template like

<template let-image="image">
 {{image}}

where image is a property of templateData

If $implicit is used

<template [ngTemplateOutlet]="..." [ngOutletContext]="{$implicit: templateData}"

the ngOutletContext can be used in the template like

<template let-item>
 {{item}}

<campaign-channels-list (onItemSelected)="_onItemSelected($event)" [customTemplate]="customTemplate" (onDragComplete)="_onDragComplete($event)" [items]="m_blockList"></campaign-channels-list>
        <template #customTemplate let-item>
            <a href="#" [attr.data-block_id]="item.blockID">
                <i class="fa {{item.blockFontAwesome}}"></i>
                <span>{{item.blockName}}</span>
                <i class="dragch fa fa-arrows-v"></i>
                <span class="lengthTimer hidden-xs"> 
                    {{item.length | FormatSecondsPipe}}
                </span>
            </a>
        </template>

and in rx component:

<div class="sortableList">
                    <li (click)="_onItemSelected(item, $event, i)" *ngFor="let item of m_items; let i = index" class="listItems list-group-item" [ngClass]="{'selectedItem': m_selectedIdx == i}">
                        <template [ngTemplateOutlet]="customTemplate" [ngOutletContext]="{$implicit: item}">
                        </template>
                    </li>
                </div>

pay attention to:

[ngOutletContext]="{$implicit: item}"

as well as

<template #customTemplate let-item>