Ключ ее в том, что вам нужно найти вложенный шаблон во внешних шаблонах, а затем выполнить итерацию этих внешних шаблонов.
вы можете заручиться помощью другой директивы здесь (рекомендуется, но не обязательно, см. ПРИМЕЧАНИЕ ниже), давайте назовем ее директивой datatable-cell
, это очень просто, объявить и экспортировать ее:
@Directive({
selector: '[datatable-cell]'
})
export class DatatableCellDirective {
constructor(public templateRef: TemplateRef<any>) { }
}
просто предоставляет шаблон ref, больше ничего не делает.
далее, если вы используете директиву, вы добавляете ее во все ваши столбцы к шаблонам (и просто объявляете let-row
, если используете $implicit
context ... или придерживаетесь let-row="row"
, если вам нужен явный контекст):
<datatable-column>
<ng-template datatable-cell let-row>
<label> {{ row.value }} </label>
</ng-template>
</datatable-column>
в компоненте столбца, используйте эту директиву, чтобы найти и открыть шаблон ячейки с помощью ContentChild
:
@ContentChild(DatatableCellDirective)
cell: DatatableCellDirective
ПРИМЕЧАНИЕ: вы можете сделать это без DatatableCellDirective
и просто установите @ContentChild(TemplateRef) cell: TemplateRef<any>
в столбце, но это немного менее гибко, и я рекомендую использовать директиву (объяснено ниже).
в компоненте таблицы, найдите столбцы с ContentChildren
как их много, Получите их шаблоны ячеек:
@ContentChildren(DatatableColumnComponent)
columns: QueryList<DatatableColumnComponent>;
cellTemplates: TemplateRef<any>[] = []
// content children available in this hook
ngAfterContentInit() {
this.cellTemplates = this.columns.toArray().map(c => c.cell.templateRef);
// like this if not using the cell directive and using TemplateRef directly
// this.cellTemplates = this.columns.toArray().map(c => c.cell);
}
, затем в вашей таблице html выполните итерации как строк данных, так и шаблонов ячеек, так как вам нужна ячейка, отображаемая для каждого столбца в каждой строке, устанавливая контекст для $implicit
здесь, но используйте любой подходящий контекст (например, {row: row}
вместо явного контекста):
<tr *ngFor="let row of tableData?.data">
<ng-container *ngFor="let tpl of cellTemplates">
<ng-container *ngTemplateOutlet="tpl; context: {$implicit: row}"></ng-container>
</ng-container>
</tr>
Вы также можете поместить теги <td></td>
внутри итерации столбца, чтобы иметь реальные ячейки таблицы, которые применять ширину столбцов.
это довольно гибкая система ... вы можете предусмотреть ее расширение, чтобы вы могли предоставлять настраиваемые заголовки столбцов в столбцах вместе с директивой datatable-header
для облегчения, и вы могли бы найти эти Шаблоны в ваших компонентах столбцов и таблиц аналогичны тем, как находятся ячейки, чтобы итерировать и отображать их в строке заголовка. Использование директивы также позволяет вам использовать другие вещи, кроме ng-template
, для создания шаблона (например, тег td
) и потенциально может позволить вам добавить больше контекста к вашим ячейкам с помощью входных данных.
blitz: https://stackblitz.com/edit/angular-gj5ean
незначительное редактирование, понял, что ContentChildren
итеративны, так что вы можете пропустить часть ngAfterContentInit
в компоненте таблицы, выполнив:
@ContentChildren(DatatableColumnComponent)
columns: QueryList<DatatableColumnComponent>;
и просто сделайте это в шаблоне ...
<ng-container *ngFor="let col of columns">
<ng-container *ngTemplateOutlet="col.cell.templateRef; context: {$implicit: row}"></ng-container>
</ng-container>
, что обеспечивает лучшее обнаружение изменений в случае изменения самих столбцов (например, добавление / удаление столбцов)