Angular — Communicating between templates with function-like HTML segments
--
The function-like HTML segment refers to a block of HTML with the ability to accept context variables (in other words, parameters). A typical Angular component has two major parts of logic, a HTML template and a Typescript class. The capability to utilize this kind of function-like HTML segment is essential for a good shared component. It is because a shared component with only a fixed HTML template is very difficult to fit all the needs among all different use cases. Trying to satisfy all potential use cases with a single and fixed HTML template will usually end up with a large template with lots of conditional statements (like *ngIf
), which is painful to read and maintain.
Here I would like to explain with an example, about how we can utilize TemplateRef
to define function-like HTML segments for communication between templates, which is a good solution to deal with the large template problem.
Getting started
Assume that there is a shared component DataListComponent
, which takes an array of data and displays them in the view:
export interface DataTableRow {
dataType: string;
value: any;
}@Component({
selector: 'data-list',
template: `
<div *ngFor="let row of data" [ngSwitch]="row.dataType">
<div *ngSwitchCase="'string'">{{row.value}}</div>
<div *ngSwitchCase="'number'"># {{row.value | number}}</div>
<div *ngSwitchCase="'date'">{{row.value | date}}</div>
</div>
`
})
export class DataListComponent {
@Input() data: DataTableRow[] = [];
}
It understands only three types of data now, which are string
, number
and date
. When we want to add more types to it, the easiest way is to simply add more switch cases. It is totally fine when such new types are generic enough that have universal representations. Yet, for data that is depending on the users, adding more switch cases can make the code very dirty.
Say we want to add the new type boolean
which displays true/false
in FirstComponent
, yes/no
in SecondComponent
. If we simply go for the more-switch-cases solution, it may have something like this:
<div *ngSwitchCase="'boolean-firstComponent'">
{{ row.value ? 'true' : 'false }}…