我需要使用没有模型的角材料表,因为我不知道服务会带来什么。
所以我在组件中动态初始化我的
MatTableDataSource
和 displayedColumns
:
表格组件:
ngOnInit() {
this.vzfPuanTablo = [] //TABLE DATASOURCE
//GET SOMETHING FROM SERVICE
this.listecidenKisi = this.listeciServis.listecidenKisi;
this.listecidenVazife = this.listeciServis.listecidenVazife;
//FILL TABLE DATASOURCE
var obj = {};
for (let i in this.listecidenKisi ){
for( let v of this.listecidenVazife[i].vazifeSonuclar){
obj[v.name] = v.value;
}
this.vzfPuanTablo.push(obj);
obj={};
}
//CREATE DISPLAYED COLUMNS DYNAMICALLY
this.displayedColumns = [];
for( let v in this.vzfPuanTablo[0]){
this.displayedColumns.push(v);
}
//INITIALIZE MatTableDataSource
this.dataSource = new MatTableDataSource(this.vzfPuanTablo);
}
代码最重要的部分在这里:
for( let v in this.vzfPuanTablo[0]) { this.displayedColumns.push(v); }
我在这里动态创建
displayedColumns
,这意味着;即使我不知道服务会带来什么,我也可以在表格中显示出来。
例如
displayedColumns
可以是这样的:
或
但这不是问题,因为我可以处理。
但是当我想用HTML显示它时,我无法正确显示,因为
matCellDef
事情:
表格Html:
<mat-table #table [dataSource]="dataSource" class="mat-elevation-z8">
<ng-container *ngFor="let disCol of displayedColumns; let colIndex = index" matColumnDef="{{disCol}}">
<mat-header-cell *matHeaderCellDef>{{disCol}}</mat-header-cell>
<mat-cell *matCellDef="let element "> {{element.disCol}}
</mat-cell>
</ng-container>
<mat-header-row *matHeaderRowDef="displayedColumns"></mat-header-row>
<mat-row *matRowDef="let row; columns: displayedColumns;"></mat-row>
</mat-table>
我的问题在这里:
<mat-cell *matCellDef="let element "> {{element.disCol}} < / mat-cell>
其实我想在单元格中显示
element."disCol's value"
,但我不知道该怎么做。
否则,除了这个
element."disCol's value"
事情,一切都好。
当我使用
{{element.disCol}}
显示 value of element that has disCols's value
时,所有单元格都是空的:
仅使用
{{element}}
的其他示例:
也如您所见:
表数据源是动态变化的。这意味着我无法轻松使用
{{element.ColumnName}}
,因为我什至不知道它是什么。
matHeaderCellDef
是正确的,因为它直接使用{{disCol}}。
但是我需要读取disCol的值,并在单元格中显示
element.(disCol's value)
。
我该怎么做?
我找到了解决方案:) 这非常非常简单,但我一开始看不到:) 就这样:
<mat-cell *matCellDef="let element "> {{element[disCol]}} </mat-cell>
我必须仅在 HTML 中使用
{{element[disCol]}}
。
现在,一切都好:)
查看基于@mevaka 的完整工作示例
其中
jobDetails$
是项目数组。
columns$
相当于 Object.keys(jobDetails$[0])
所以只是 string[]
<table mat-table [dataSource]="jobDetails$ | async">
<ng-container *ngFor="let disCol of (columns$ | async); let colIndex = index" matColumnDef="{{disCol}}">
<th mat-header-cell *matHeaderCellDef>{{disCol}}</th>
<td mat-cell *matCellDef="let element">{{element[colIndex]}}</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="(columns$ | async)"></tr>
<tr mat-row *matRowDef="let row; columns: (columns$ | async)"></tr>
</table>
我已尽力将动态表简化到最低限度。此示例将显示给定具有任意键的平面对象数组的任意列。请注意第一个对象如何具有额外的“foo”属性,该属性会导致创建整个列。 DATA const 可能是您从服务获取的一些数据。另外,如果您知道一些将获得 JSON 的常见属性名称,您可以添加“列 ID -> 标签”映射到此。请参阅 stachblitz 此处。
import {Component, ViewChild, OnInit} from '@angular/core';
const DATA: any[] = [
{position: 1, name: 'sdd', weight: 1.0079, symbol: 'H', foo: 'bar'},
{position: 2, name: 'Helium', weight: 4.0026, symbol: 'He'},
{position: 3, name: 'Lithium', weight: 6.941, symbol: 'Li'},
{position: 4, name: 'Beryllium', weight: 9.0122, symbol: 'Be'},
{position: 5, name: 'Boron', weight: 10.811, symbol: 'B'},
{position: 6, name: 'Carbon', weight: 12.0107, symbol: 'C'}
];
@Component({
selector: 'dynamic-table-example',
styleUrls: ['dynamic-table-example.css'],
templateUrl: 'dynamic-table-example.html',
})
export class DynamicTableExample implements OnInit {
columns:Array<any>
displayedColumns:Array<any>
dataSource:any
ngOnInit() {
// Get list of columns by gathering unique keys of objects found in DATA.
const columns = DATA
.reduce((columns, row) => {
return [...columns, ...Object.keys(row)]
}, [])
.reduce((columns, column) => {
return columns.includes(column)
? columns
: [...columns, column]
}, [])
// Describe the columns for <mat-table>.
this.columns = columns.map(column => {
return {
columnDef: column,
header: column,
cell: (element: any) => `${element[column] ? element[column] : ``}`
}
})
this.displayedColumns = this.columns.map(c => c.columnDef);
// Set the dataSource for <mat-table>.
this.dataSource = DATA
}
}
<mat-table #table [dataSource]="dataSource">
<ng-container *ngFor="let column of columns" [cdkColumnDef]="column.columnDef">
<mat-header-cell *cdkHeaderCellDef>{{ column.header }}</mat-header-cell>
<mat-cell *cdkCellDef="let row">{{ column.cell(row) }}</mat-cell>
</ng-container>
<mat-header-row *matHeaderRowDef="displayedColumns"></mat-header-row>
<mat-row *matRowDef="let row; columns: displayedColumns;"></mat-row>
</mat-table>
我需要动态渲染列,我还希望将单元格值渲染为复选框。我的代码是从带有过滤的Angular示例表编辑的,并从@Jack获得了动态渲染部分。希望下面附上的代码可以为像我这样的初学者提供一个简单的想法。
<td mat-cell... </td>
包裹
<div *ngIf="condition"></div>
<div *ngIf="disCol === 'username'">
<td mat-cell *matCellDef="let element"> {{element[disCol]}}</td>
</div>
<div *ngIf="disCol !== 'username'">
<td mat-cell *matCellDef="let element">
<input *ngIf="element[disCol] == 'Yes'" type="checkbox" />
<input *ngIf="element[disCol] == 'No'" type="checkbox" checked/>
</td>
</div>
'@angular/material'
import { MatButtonModule } from '@angular/material/button';
import { MatFormFieldModule } from '@angular/material/form-field';
import { MatInputModule } from '@angular/material/input';
import { MatRippleModule } from '@angular/material/core';
import { MatTableModule } from '@angular/material/table';
<div class="example-container mat-elevation-z8">
<mat-table #table [dataSource]="dataSource">
<ng-container *ngFor="let disCol of displayedColumns; let colIndex = index" matColumnDef="{{disCol}}">
<th mat-header-cell *matHeaderCellDef>{{disCol}}</th>
<div *ngIf="disCol === 'username'">
<td mat-cell *matCellDef="let element"> {{element[disCol] == undefined ? "-NA-" : element[disCol]}}</td>
</div>
<div *ngIf="disCol !== 'username'">
<td mat-cell *matCellDef="let element">
<input *ngIf="element[disCol] == 'Yes'" type="checkbox" />
<input *ngIf="element[disCol] == 'No'" type="checkbox" checked/>
</td>
</div>
</ng-container>"
<mat-header-row *matHeaderRowDef="displayedColumns"></mat-header-row>
<mat-row *matRowDef="let row; columns: displayedColumns;"></mat-row>
</mat-table>
</div>
import { Component, OnInit } from '@angular/core';
import { MatTableDataSource } from '@angular/material/table';
@Component({
selector: 'app-dynamic-tb',
templateUrl: './dynamic-tb.component.html',
styleUrls: ['./dynamic-tb.component.css']
})
export class DynamicTbComponent implements OnInit {
displayedColumns: string[] = [];
dataSource: any;
ELEMENT_DATA: any[] | undefined;
ngOnInit(): void {
this.displayedColumns = ['username', 'feature_1', 'feature_2', 'feature_3'];
this.ELEMENT_DATA = [
{ username: "Jonah", feature_1: 'Yes', feature_2: 'No', feature_3: 'No' },
{ username: "Alan", feature_1: 'Yes', feature_2: 'No', feature_3: 'Yes' },
{ username: "John", feature_1: 'No', feature_2: 'Yes', feature_3: 'No' },
{ username: "Ann", feature_1: 'Yes', feature_2: 'No', feature_3: 'Yes' },
{ username: "Lee", feature_1: 'No', feature_2: 'No', feature_3: 'No' },
{ username: "Royce", feature_1: 'Yes', feature_2: 'Yes', feature_3: 'No' },
{ username: "Suzzy", feature_1: 'No', feature_2: 'No', feature_3: 'No' },
];
this.dataSource = new MatTableDataSource(this.ELEMENT_DATA);
}
}
import { NgModule } from '@angular/core';
import { DynamicTbComponent } from './profiles.component';
import { CommonModule } from '@angular/common';
import { MatButtonModule } from '@angular/material/button';
import { MatFormFieldModule } from '@angular/material/form-field';
import { MatInputModule } from '@angular/material/input';
import { MatRippleModule } from '@angular/material/core';
import { MatTableModule } from '@angular/material/table';
@
NgModule
({
declarations: [
DynamicTbComponent
],
imports: [
CommonModule,
MatButtonModule,
MatFormFieldModule,
MatInputModule,
MatRippleModule,
MatTableModule,
],
exports: [
DynamicTbComponent
]
})
export class DynamicTbModule {}
/* Structure */
.example-container {
display: flex;
flex-direction: column;
min-width: 300px;
}
.example-header {
min-height: 64px;
padding: 8px 24px 0;
}
.mat-form-field {
font-size: 14px;
width: 100%;
}
.mat-table {
overflow: auto;
max-height: 500px;
}
/**
Added by me
*/
th, td {
width: 100px;
}