Я создаю компонент таблицы данных, который разработан как очень общий компонент.
Идея состоит в том, чтобы определить таблицу следующим образом:
<app-datatable [items]="currentPageResult">
<app-datatable-column attribute="id"
header="ID"></app-datatable-column>
<app-datatable-column attribute="name"
header="First Name"></app-datatable-column>
<app-datatable-column attribute="last_name"
header="Last Name"></app-datatable-column>
</app-datatable>
Таким образом, мы можем указать массив в компоненте datatable, и, определив столбцы datatable, мы можем решить, какие атрибуты должны отображать таблицу. Внутри таблица будет выполнять ngFor по столбцам и еще один ngFor по элементам.
Эта часть была простой, и теперь она работает очень хорошо, эта вещь становится сложной, когда я хочу, чтобы пользовательский контент html в td; Что-то вроде этого:
<app-datatable [items]="currentPageResult">
<app-datatable-column attribute="id"
header="ID"
[template]="titleTemplate">
<ng-template #titleTemplate>
<a role="button" [routerLink]="[data.id]">
{{data.id}}
</a>
</ng-template>
</app-datatable-column>
<app-datatable-column attribute="name"
header="First Name"></app-datatable-column>
<app-datatable-column attribute="last_name"
header="Last Name"></app-datatable-column>
</app-datatable>
Обратите внимание, что я использую data
в качестве переменной итерации, но на самом деле это не работает, я просто показываю, что я хочу сделать.
Чтобы решить эту проблему, я использовал «$ data» как простую строку и настраиваемую директиву для замены «$ data» на соответствующее значение столбца / строки.
В компоненте datatable я использую директиву appDatatableContent
для каждой tbody td
передачи данных row
и настроек colum
(директива применяется только в том случае, если в настройках столбца есть шаблон):
<table class="table">
<thead>
<tr>
<th *ngFor="let col of columns" [ngClass]="getColumnHeaderClasses(col)" (click)="onReorder(col)">{{col.header}}</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let row of items.Items">
<td *ngFor="let col of columns" appDatatableContent [column]="col" [row]="row">
<ng-container *ngIf="!col.template; else col.template">
{{row[col.attribute]}}
</ng-container>
</td>
</tr>
</tbody>
</table>
И директива в основном ищет элемент, содержащий внутри '$ data', и заменяет '$ sdata' на соответствующее значение столбца следующим образом:
ngAfterViewInit() {
if (!this.column.template) {
return;
}
const element: HTMLElement = this.element.nativeElement;
const value = this.row[this.column.attribute];
const children = element.getElementsByTagName('*');
const length = children.length;
for (let i = 0; i < length; i++) {
const currentNode = children[i];
if (!currentNode.children || !currentNode.children.length) {
const originalHTML: string = currentNode.innerHTML;
const fixedHTML = originalHTML.replace('$data', value);
currentNode.innerHTML = fixedHTML;
}
}
}
Также обратите внимание, что каждая ячейка имеет <ng-container *ngIf="!col.template; else col.template">
, поэтому, если есть какой-либо привязанный шаблон, содержимое ячейки будет отображать этот шаблон, но проблема в том, как передать аргументы (в частности, объект строки) в шаблон, чтобы шаблон мог использовать интерполяцию с этим параметром. .
См. Рабочий плункер: https://plnkr.co/edit/84jhiquT5q3OQaCxTa5i
Но это не кажется лучшим подходом, потому что я не могу получить преимущества большой мощности angular, так как я просто заменяю строковое значение.
Итак, ¿Как я могу определить динамический шаблон, который может использовать переменную итерации для отображения содержимого настраиваемой ячейки?