Defining generic views with TemplateRef - FadiZahhar/switchingtoangular2 GitHub Wiki
If we take a look at its implementation in ch4/ts/inputs-outputs/app.ts, we'll see that the template used to render the individual to-do items is defined inside the template of the entire to-do application. What if we want to use a different layout to render the to-do items? We can do this by creating another component called Todo, which encapsulates the responsibility of rendering them. Then, we can define separate Todo components for the different layouts we want to support. This way, we need to have n different components for n different layouts, even though we use only their templates. Angular 2 comes with a more elegant solution. Earlier in this chapter, we already discussed the template element. We said that it allows us to define a chunk of HTML that will not be processed by the browser. Angular 2 allows us to reference such template elements and use them by passing them as content children!
Here is how we can pass the custom layout to our refactored todo-app component: // ch4/ts/template-ref/app.ts In the template, we declare a variable called todo. Later in the template, we can use it to specify the way in which we want to visualize the content. Now, let's see how we can get a reference to this template in the controller of the TodoApp component: // ch4/ts/template-ref/app.ts class TodoApp { @ContentChild(TemplateRef) private itemsTemplate: TemplateRef; // … } All we do here is define a property called itemsTemplate and decorate it with the @ContentChild decorator. During the component's life cycle (more accurately, in ngAfterContentInit), the value of itemsTemplate will be set as a reference of the template that we passed as the content of the todo-app element. There is one more problem though—we need the template in the TodoList component, since that's the place where we render the individual to-do items. What we can do is define another input of the TodoList component and pass the template directly from TodoApp: // ch4/ts/template-ref/app.ts class TodoList { @Input() todos: Todo[]; @Input() itemsTemplate: TemplateRef; @Output() toggle = new EventEmitter(); }
We need to pass it as an input from the template of TodoApp: ... <todo-list [todos]="todos" [itemsTemplate]="itemsTemplate"> The only thing left is to use this template reference in the template of the TodoList application:
<template *ngFor="var todo of todos; template: itemsTemplate"></ template> We explained the extended syntax of the ngForOf directive in the previous sections of this chapter. This snippet shows one more property of this directive that we can set: the ngForTemplate property. By default, the template of the ngForOf directive is the element it is used on. By specifying a template reference to the ngForTemplate property, we can use the passed TemplateRef instead.