Я пытаюсь написать простое представление списка (представление сетки?) с несколькими столбцами, используя Angular 2, которое я могу создать следующим образом:
<file-list [items]="items">
<file-list-column title="Id" field="id"></file-list-column>
<file-list-column title="Name" field="name"></file-list-column>
</file-list>
На самом деле мне удалось заставить это работать очень хакерским способом, он генерирует таблицу с информационными данными, которые я установил в компоненте FileListColumn.
Вот что у меня есть на данный момент:
Компонент FileListColumn, в котором определяются метаданные столбца:
import {Component, Input, TemplateRef, ViewChild} from '@angular/core';
@Component({
selector: 'file-list-column',
template: ''
})
export class FileListColumn {
@Input()
public title: string;
@Input()
public field: string;
ngOnInit() {
}
}
Компонент FileList, это основной компонент представления списка:
import {Component, Input, ContentChildren, QueryList, AfterContentInit, forwardRef} from '@angular/core';
import {FileListColumn} from './file.list.column';
import {IItem} from 'models';
@Component({
selector: 'file-list',
template: require('./file.list.html')
})
export class FileList implements AfterContentInit {
@ContentChildren(forwardRef(() => FileListColumn))
public columns: QueryList<FileListColumn>;
@Input()
public items: IItem[];
constructor() {
}
public ngAfterContentInit() {
}
public getProperty(item:{[key:string]:any}, name:string) {
return item[name];
}
}
Это это представление для компонента FileList
:
<table>
<thead>
<tr>
<th *ngFor="let col of columns">
{{col.title}}
</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let item of items">
<td *ngFor="let col of columns">
{{getProperty(item, col.field)}}
</td>
</tr>
</tbody>
</table>
Хакерская вещь, которую я упомянул, заключается в том, что, как это работает, для каждого столбца каждого элемента единственное, что он делает, это вызывает функцию getProperty, передавая элемент и имя поля, и возвращает значение этого поля, которое является далеко не идеальное решение.
Что я хочу сделать сейчас, так это установить содержимое в моих столбцах, как показано ниже, и отобразить это содержимое в моей таблице:
<file-list [items]="items">
<file-list-column title="Id" field="id"></file-list-column>
<file-list-column title="Name">
<span>{{$item.name}}</span>
</file-list-column>
<file-list-column title="Some other column">
<some-component item="$item"></some-component>
</file-list-column>
</file-list>
Не только это, но я также хочу иметь возможность определять html для столбца в самом компоненте FileListColumn
, чтобы код был немного более организованным.
Одна из вещей, которые я пробовал, заключалась в том, чтобы добавить шаблон в представление компонента FileListColumn
:
<template #columnTemplate>
<span>text to see if worked</span>
<ng-content></ng-content>
</template>
Затем я попытался получить его ссылку в компоненте FileListColumn
с помощью: @ViewChild('columnTemplate') columnTemplate: TemplateRef<any>;
И затем я попытался загрузить его в представлении компонента FileList
, используя:
<td *ngFor="let col of columns" *ngForTemplate="col.columnTemplate">
</td>
Но я получаю сообщение об ошибке в браузере:
Error: Template parse errors:(…) "Error: Template parse errors:
Can't have multiple template bindings on one element. Use only one attribute named 'template' or prefixed with * ("
<tbody>
<tr *ngFor="let item of items">
<td *ngFor="let col of columns" [ERROR ->]*ngForTemplate="col.columnTemplate">
</td>
</tr>
"): FileList@10:44
Даже если бы это сработало, я бы понятия не имел, как на самом деле связать элемент в моем массиве элементов с содержимым FileListColumn
.
У кого-нибудь есть идеи о том, как я могу достичь этих вещей?
Я искал способ решить эту проблему весь день, но не смог найти ничего полезного, большинство руководств не имеют значения, поскольку они были написаны для старых бета-версий Angular 2 с использованием более старых API.
Заранее спасибо за помощь и извините за длинный пост.
Обновление 1:
Итак, мне удалось загрузить шаблон из FileListColumn
внутри <td>
в FileList
, используя попытку #columnTemplate, сделав это на основе одной из ссылок Гюнтера Цохбауэра:
<tr *ngFor="let item of items">
<td *ngFor="let col of columns">
<template [ngTemplateOutlet]="col.columnTemplate" [ngOutletContext]="item"></template>
</td>
</tr>
Шаблон загружается внутри каждой ячейки, но есть две проблемы:
- Единственные свойства, к которым я могу получить доступ из шаблона, — это свойства столбца, у меня нет доступа к свойствам элемента из внешнего
ngFor
. - Когда я добавляю содержимое в
FileListColumn
, выполняя<file-list-column><div>Content here</div></file-list-column>
для загрузки в<ng-content>
шаблона столбца, это содержимое отображается только в последней строке, то есть оно не повторяется во всех строках.