Templating in Angular 2

Templating in Angular 2

Published by: Maarten Mensink on: woensdag 21 december 2016

Templates in a nutshell

When creating controls we want to keep the display logic which is specific to a application out of the control. You can think of controls like ListView, AutoComplete, Select.

In this blog post we will talk about how we can achieve this in Angular 2

Templating to the rescue

In many frameworks templating the way to separate the view from the logic. In this case we use templating to separate application specific layout from a control.

We will use several core components to achieve this.

  1. ContentChild
  2. TemplateRef
  3. ngTemplateOutlet

The basic idea of a template

In the sample below you see the basic idea the usage of a template. In this case we will build a ListView to which a template is provided for displaying the ListViewItem.

<listview>
    <template>item view definition</template>
</listview>

The ListView

Our ListView will have a header template and a item template both can be supplied to the ListView component.

<listview [items]='items'>
   <template #headerTemplate>
        <div class='header'>I am the most awesome header ever</div>
   </template>
    <template #itemTemplate let-item="item">
        <div class="item">
          <h3>{{item.name}}</h3>
          <h4>{{item.description}}</h4>
        </div>
    </template>
</listview

The ListView as a Angular compoment

In the ListView compoment 2 ContentChild references are defined. These are the TemplateRef. The references provide us access to the templates defined in the HTML template. (Note: the #id of the templates match the selector of the ContentChild)

The TemplateRef is passed to the ngTemplateOutlet directive. Data can be passed to the template by setting [ngOutletContext]="{item: item}" the keys of the object being passed will be available as local variables inside the template.

import { Component, ContentChild, TemplateRef, Input } from '@angular/core';

@Component({
  selector: 'listview',
  template: `<div class="listview">
        <template [ngTemplateOutlet]="headerTemplate"></template>
        <div class='items' *ngFor="let item of items">
          <template [ngTemplateOutlet]="itemTemplate" [ngOutletContext]="{item: item}" ></template>
        </div>
  </div>`
})
export class ListViewComponent {
  @ContentChild('headerTemplate',{read: TemplateRef}) headerTemplate:TemplateRef;
  @ContentChild('itemTemplate',{read: TemplateRef}) itemTemplate:TemplateRef;
  @Input() items: Array<any> = [];
}

Bringing it all together

We made a plunker sample that you can play around with.