我想用Angular做一些
<my-table-component [Items]="Items">
<my-column-component Title="The Id">
{{Item.Id}}
</my-column-component>
<my-column-component Title="The Name">
<span>{{Item.Name}}</span>
</my-column-component>
<my-column-component Title="The Avatar">
<img [src]="Item.Picture" />
</my-column-component>
</my-table-component>
问题是我不希望现在此处和立即呈现每一列的内容。
提供Items
包含对象数组,例如:
Items = [
{ Id: 1, Name: "I'm One", Picture: "/picture/1.jpg" },
{ Id: 2, Name: "I'm Two", Picture: "/picture/2.jpg" },
{ Id: 3, Name: "I'm Three", Picture: "/picture/3.jpg" },
]
我想要的最终结果将是类似的
<div class="my-table-component">
<div class="my-table-component-header">
<div class="my-table-component-header-item">The Id</div>
<div class="my-table-component-header-item">The Name</div>
<div class="my-table-component-header-item">The Name</div>
</div>
<div class="my-table-component-content">
<div class="my-table-component-content-item">1</div>
<div class="my-table-component-content-item"><span>I'm One</span></div>
<div class="my-table-component-content-item"><img [src]="/picture/1.jpg" /></div>
</div>
<div class="my-table-component-content">
<div class="my-table-component-content-item">2</div>
<div class="my-table-component-content-item"><span>I'm Two</span></div>
<div class="my-table-component-content-item"><img [src]="/picture/2.jpg" /></div>
</div>
<div class="my-table-component-content">
<div class="my-table-component-content-item">3</div>
<div class="my-table-component-content-item"><span>I'm Three</span></div>
<div class="my-table-component-content-item"><img [src]="/picture/3.jpg" /></div>
</div>
</div>
因此,并不是在这里直接声明每列的绑定,而是动态地对绑定到Item
的表组件的每个Items
进行声明。
我已经尝试过使用NgTemplateOutlet进行操作,但是或者我不太了解它是如何工作的,或者这不是我想要的。
答案 0 :(得分:1)
这是一个使用结构化指令和NgTemplateOutlet来实现所需结果的解决方案。有关完整代码,请参见此StackBlitz link。
启动HTML:
({app.component.html
)
<my-table-component [Items]="Items">
<my-column-component>
<my-cell *columnHeader>The Id</my-cell>
<my-cell *columnCells="let Item">{{Item.Id}}</my-cell>
</my-column-component>
<my-column-component>
<my-cell *columnHeader>The Name</my-cell>
<my-cell *columnCells="let Item"><span>{{Item.Name}}</span></my-cell>
</my-column-component>
<my-column-component>
<my-cell *columnHeader>The Avatar</my-cell>
<my-cell *columnCells="let Item"><img src="{{Item.Picture}}" /></my-cell>
</my-column-component>
</my-table-component>
注意:
使用*columnHeader
和*columnCells
结构化指令分别表示要成为列标题和常规表单元格的单元格
要在表单元格中使用数据绑定(例如<span>{{Item.Name}}</span>
),请设置*columnCells="let myVarHere"
(例如*columnCells="let Item"
)以声明要使用的迭代变量。
最终结果:
<div class="my-table-component">
<div class="my-table-component-header">
<div class="my-table-component-header-item"><my-cell>The Id</my-cell></div>
<div class="my-table-component-header-item"><my-cell>The Name</my-cell></div>
<div class="my-table-component-header-item"><my-cell>The Avatar</my-cell></div>
</div>
<div class="my-table-component-content">
<div class="my-table-component-content-item"><my-cell>1</my-cell></div>
<div class="my-table-component-content-item"><my-cell><span>I'm One</span></my-cell></div>
<div class="my-table-component-content-item"><my-cell><img src="/picture/1.jpg" /></my-cell></div>
</div>
<div class="my-table-component-content">
<div class="my-table-component-content-item"><my-cell>2</my-cell></div>
<div class="my-table-component-content-item"><my-cell><span>I'm Two</span></my-cell></div>
<div class="my-table-component-content-item"><my-cell><img src="/picture/2.jpg" /></my-cell></div>
</div>
<div class="my-table-component-content">
<div class="my-table-component-content-item"><my-cell>3</my-cell></div>
<div class="my-table-component-content-item"><my-cell><span>I'm Three</span></my-cell></div>
<div class="my-table-component-content-item"><my-cell><img src="/picture/3.jpg" /></my-cell></div>
</div>
</div>
角度代码:
({app.component.ts
)
export class AppComponent {
Items = [
{ Id: 1, Name: "I'm One", Picture: "/picture/1.jpg" },
{ Id: 2, Name: "I'm Two", Picture: "/picture/2.jpg" },
{ Id: 3, Name: "I'm Three", Picture: "/picture/3.jpg" },
];
}
({my-table-components.component.ts
-我选择将所有与“表”相关的组件/指令放在一个文件中,但如果需要,可以将其拆分为多个文件)
import { Component, Directive, Input, TemplateRef } from '@angular/core';
@Directive({ selector: 'my-column-component' })
class MyColumnComponent { }
@Directive({ selector: 'my-cell' })
class MyCell { }
@Component({
selector: 'my-table-component',
template: `
<div class="my-table-component">
<div class="my-table-component-header">
<div class="my-table-component-header-item" *ngFor="let header of columnHeaders">
<ng-container *ngTemplateOutlet="header; context: {$implicit:Item}"></ng-container>
</div>
</div>
<div class="my-table-component-content" *ngFor="let Item of Items">
<div class="my-table-component-content-item" *ngFor="let cell of columnCells">
<ng-container *ngTemplateOutlet="cell; context: {$implicit: Item}"></ng-container>
</div>
</div>
</div>
`,
styles: []
})
class MyTableComponent {
@Input() Items: Object[];
columnHeaders: TemplateRef<void>[] = [];
columnCells: TemplateRef<void>[] = [];
}
// Structural directives
@Directive({ selector: '[columnHeader]'})
class ColumnHeader {
constructor(templateRef: TemplateRef<void>, table: MyTableComponent) {
table.columnHeaders.push(templateRef);
}
}
@Directive({ selector: '[columnCells]'})
class ColumnCell {
constructor(templateRef: TemplateRef<void>, table: MyTableComponent) {
table.columnCells.push(templateRef);
}
}
export { MyTableComponent, MyCell, MyColumnComponent, ColumnHeader, ColumnCell }
在起始HTML中,您可以使用类似的方式表示每一列:
<my-column-component>
<my-cell *columnHeader>The Id</my-cell>
<my-cell *columnCells="let Item">{{Item.Id}}</my-cell>
</my-column-component>
请注意,我们在*
和columnHeader
伪指令之前加了一个星号columnCells
前缀。这告诉Angular我们想将这些指令用作结构指令。 (结构指令是更改DOM 结构的指令,例如通过添加,删除或操作元素。例如,*ngIf
和*ngFor
是结构指令。)
在内部,Angular通过将<ng-template>
标签包裹在原始元素周围来消除星号语法的糖化。例如,这:
<my-cell *columnHeader>The Id</my-cell>
<my-cell *columnCells="let Item">{{Item.Id}}</my-cell>
将被转换为此:
<ng-template columnHeader>
<my-cell>The Id</my-cell>
</ng-template>
<ng-template columnCells let-Item>
<my-cell>{{Item.Id}}</my-cell>
</ng-template>
因此,每个带有*columnHeader
或*columnCells
指令的元素都将被<ng-template>
元素环绕。由于它们分别位于<ng-template>
内,因此我们可以Angular的TemplateRef
获取对<ng-template>
元素的引用,然后将该引用传递到MyTableComponent
中,以使用{ {1}}。
看看this diagram here,了解我的意思。
示例:
*ngTemplateOutlet
-
@Directive({ selector: '[columnCells]'})
class ColumnCell {
constructor(templateRef: TemplateRef<void>, table: MyTableComponent) {
table.columnCells.push(templateRef);
}
}
我建议您看一下this excellent video,以更好地理解结构化指令和NgTemplateOutlet,以及Angular文档中的code example。NpTemplateOutlet。