Wir sind uns gewohnt, HTML Komponenten deklarativ zu beschreiben. Eine einfache Tabelle sieht zum Beispiel wie folgt aus:
<table>
<tr>
<th>Name</th>
<th>Age</th>
</tr>
<tr>
<td>Superman</td>
<td>18</td>
</tr>
</table>
Wäre es nicht toll, wenn wir eine Tabellenkomponente in Angular ähnlich verwenden könnten?
Folgendes Codebeispiel zeigt, wie eine Tabellenkomponente in
Angular deklarativ verwendet werden kann.
Die Tabelle besteht aus der app-table
Komponente und der app-column
Direktive.
Der Spaltentitel und der Property-Name, kann direkt auf der app-column
Direktive gesetzt werden.
Dynamischer Inhalt, wie z. B. die Anzeige eines Bildes, kann der app-column
Direktive mit einem ng-template
angegeben werden.
Im ng-template
kann einerseits mit dem Attribut let-value
auf den Spaltenwert
und andererseits mit dem Attribut let-row="row"
auf den Inhalt der gesamten Reihe zugegriffen werden.
import {Component} from '@angular/core';
@Component({
selector: 'app-root',
template: `
<app-table [data]="data">
<app-column header="Avatar" key="avatar">
<ng-template let-value>
<img [src]="value">
</ng-template>
</app-column>
<app-column header="Name" key="name"></app-column>
<app-column header="Age" key="age"></app-column>
</app-table>
`
})
export class AppComponent {
data = [{
name: 'Superman',
avatar: 'http://tiny.cc/ngz36y',
age: 18
}, {
name: 'Hulk',
avatar: 'http://tiny.cc/liz36y',
age: 36
}];
}
Wie bereits erwähnt, besteht die Tabelle aus einer Komponente und einer Direktive.
Die app-column
Direktive dient zur Beschreibung einer Spalte.
Sie hat zwei Input Werte, den key
und den header
.
Durch den ContentChild
Decorator kann die Direktive auf das ng-template
zugreifen.
import {ContentChild, Directive, Input, TemplateRef} from '@angular/core';
@Directive({
selector: 'app-column'
})
export class ColumnDirective {
@Input() key: string;
@Input() header: string;
@ContentChild(TemplateRef, {static: false}) template;
}
Die app-table
Komponente erhält die darzustellenden Daten via Input Property.
Mittels des ContentChildren
Decorators kann auf alle angegebenen app-column
Direktiven zugegriffen werden.
Über diese Liste von Direktiven wird zweimal iteriert.
Einmal um die Titel und einmal um die Werte darzustellen.
Mittels der strukturellen Direktive *ngTemplateOutlet
kann das Template einer Spalte dynamisch dargestellt werden.
import {Component, ContentChildren, Input, QueryList} from '@angular/core';
import {ColumnDirective} from '../column.directive';
@Component({
selector: 'app-table',
template: `
<table>
<tr>
<th *ngFor="let column of columns">{{column.header}}</th>
</tr>
<tr *ngFor="let row of data">
<td *ngFor="let column of columns">
<ng-container *ngIf="column.template; else rawValue" >
<ng-container
*ngTemplateOutlet="column.template; context: {row: row, $implicit: row[column.key]}">
</ng-container>
</ng-container>
<ng-template #rawValue>
{{row[column.key]}}
</ng-template>
</td>
</tr>
</table>
`
})
export class TableComponent {
@Input() data: object[];
@ContentChildren(ColumnDirective) columns: QueryList<ColumnDirective>;
}
Mit dem vorgestellten Ansatz können Tabellen und andere Komponenten deklarativ verwendet werden. Dies macht den Template Code besser lesbar und verständlicher.
Jeden Freitag nehmen wir uns eine Stunde Zeit, um Fragen rund um die Entwicklung und Pflege von Software zu beantworten.
Zu solchen und weiteren deiner Fragen helfen wir dir gerne weiter. Die Stunde steht exklusiv dir zur Verfügung. Sie ist für dich komplett kostenlos und unverbindlich. Wir benötigen dafür lediglich deine Anmeldung: