【发布时间】:2017-02-12 08:00:03
【问题描述】:
我正在尝试使用 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>
我实际上设法以一种非常 hacky 的方式完成了这项工作,它生成了一个包含我在 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>
不仅如此,我还希望能够为 FileListColumn 组件本身中的列定义 html,以使代码更有条理。
我尝试的其中一件事是在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
即使这可行,我也不知道如何将我的 items 数组中的项目实际绑定到 FileListColumn 内容。
有人知道我如何实现这些目标吗?
我整天都在寻找解决这个问题的方法,但找不到任何有用的东西,大多数教程都是无关紧要的,因为它们是使用旧 API 为 Angular 2 的旧 beta 编写的。
在此先感谢您的帮助,很抱歉发了这么长的帖子。
更新 1:
因此,我根据 Günter Zöchbauer 的链接之一尝试使用 #columnTemplate 尝试从 <td> 内部的 FileListColumn 加载模板:
<tr *ngFor="let item of items">
<td *ngFor="let col of columns">
<template [ngTemplateOutlet]="col.columnTemplate" [ngOutletContext]="item"></template>
</td>
</tr>
模板在每个 cel 中加载,但仍然存在两个问题:
- 我可以从模板访问的唯一属性是列属性,我无法从外部
ngFor访问项目属性。 - 当我通过执行
<file-list-column><div>Content here</div></file-list-column>将内容添加到FileListColumn以加载到列模板的<ng-content>中时,此内容仅显示在最后行中,这意味着它不是在所有行中重复。
【问题讨论】:
标签: javascript angular data-binding transclusion ngfor