我有一个HTML页面,我想在其中创建一个表格。此表中的列是动态的,这意味着它们使用any[]
类型从服务器提取到组件中的变量中。此表中的数据也是动态的,这意味着在编程时我不知道哪些列和数据将被绑定到表中。
我尝试过下面的代码,但它似乎无法正常工作或给出任何错误。它只会在td
中创建空tbody
。
Expense.component.html
<div class="panel panel-default" style="margin-top:10px;">
<div class="panel-heading">
Expenses
</div>
<div class="panel-body" style="position:relative">
<div class="table-responsive">
<table class="table">
<thead>
<tr>
<th *ngFor="#column of columns">
{{column}}
</th>
</tr>
</thead>
<tbody>
<tr *ngFor="#data of data">
<td *ngFor="#column of columns">
{{data.column}}
</td>
</tr>
</tbody>
</table>
</div>
</div>
在上面的代码中,列已成功创建,但数据和列mashup无法正常工作。我相信在Angular 2中必须有一种方法来实现这一目标。
Expense.component.ts
export class ExpenseComponent implements OnInit {
errorMessage: any[];
columns: string[];
data: any[];
constructor(private _commonService: CommonService, private _expenseService: ExpenseService) {
}
ngOnInit(): void {
this._commonService.getColumnNames('condomanagement', 'expenses')
.subscribe(data => this.promise(data), error => this.errorMessage = <any>error);
}
private promise(data: string[]) {
this.columns = data;
this._expenseService.getExpenses('condomanagement', this.columns)
.subscribe(data => this.anotherPromise(data), error => this.errorMessage = <any>error);
}
private anotherPromise(data: any[]) {
this.data = data;
console.log(this.columns);
console.log(this.data);
}
private handleError(error: Response) {
console.error(error);
return Observable.throw(error.json().error || 'Server error');
}
}
数据已在上述代码中登录到控制台,但根据我的试用版无法在HTML中使用。有什么想法吗?
更新:刚刚使用这样的插值,它起作用了
{{mydata[column]}}
答案 0 :(得分:7)
而不是使用
<tr *ngFor="#data of data">
你应该使用
<tr *ngFor="#data of data" *ngModel="data[column]">
答案 1 :(得分:1)
在Angular2 Beta版本中:
<强> grid.html 强>
<mat-table #table [dataSource]="dataSource">
<ng-container [matColumnDef]="columnName" *ngFor="let columnName of displayedColumns">
<mat-header-cell *matHeaderCellDef> {{columnName}} </mat-header-cell>
<mat-cell *matCellDef="let element"> {{element[columnName]}} </mat-cell>
</ng-container>
<mat-header-row *matHeaderRowDef="displayedColumns"></mat-header-row>
<mat-row *matRowDef="let row; columns: displayedColumns;"></mat-row>
</mat-table>
<强> grid.ts 强>
export class GridDynamicComponent {
rows = new Array<CorporateEmployee>();
dataSource: any;
displayedColumns = [];
yourFunction(...) {
rows = ... // Update your model
this.displayedColumns = rows.length > 0 ? Object.keys(rows[0]) : [];
this.dataSource = new MatTableDataSource(rows);
}
}
答案 2 :(得分:1)
它可用于 Angular 2,5,6,7 。我们应该创建一个组件,以便随时可以使用任何类型的数据。我测试了它并且正在工作。
文件: dynamic-table.component.ts
import { Component, OnInit, Input, Output, OnChanges, SimpleChanges } from '@angular/core';
@Component({
selector: 'dynamic-table',
templateUrl: './dynamic-table.component.html',
styleUrls: ['./dynamic-table.component.scss']
})
export class DynamicTableComponent implements OnInit, OnChanges {
@Input() tableHeads: Array<String> = new Array<String>();
@Input() tableDatas: Array<any> = new Array<any>();
@Input() tableColName: Array<String> = new Array<String>();
private tableColNameGenerated: Array<String> = new Array<String>();
private isTableColNameSet: Boolean = false;
constructor() { }
ngOnInit() {
}
ngOnChanges(changes: SimpleChanges) {
if (changes['tableHeads']) {
if (this.tableHeads.length > 0) {
// console.log('tableHeads');
}
}
if (changes['tableDatas']) {
if (!this.isTableColNameSet) {
if (this.tableDatas.length > 0) {
this.tableColNameGenerated = this.getKeys(this.tableDatas[0]);
if (!this.isHeadAndColLengthSame(this.tableHeads, this.tableColNameGenerated)) {
console.error('Table column row is not same as with property name in self generated');
}
}
}
}
if (changes['tableColName']) {
if (this.tableColName.length > 0) {
this.tableColNameGenerated = this.tableColName;
this.isTableColNameSet = true;
if (!this.isHeadAndColLengthSame(this.tableHeads, this.tableColName)) {
console.error('Table column row is not same as with property name provided');
}
}
}
}
/**
* This method will fetch all the property name and convert it into a list of String.
* @param {Array<String>} head Pass in the list of String, which contains table header values
* @param {Array<String>} col Pass in the list of String, which contains column property
* name, which was received from Input or generated using this.getKeys()
*/
private isHeadAndColLengthSame(head: Array<String>, col: Array<String>): Boolean {
return (head.length === col.length);
}
/**
* This method will fetch all the property name and convert it into a list of String.
* @param {any} value Pass Instance of Object eg. new User()
*/
private getKeys(value: any): Array<String> {
return Object.keys(value);
}
}
文件: dynamic-table.component.html
<table>
<thead>
<tr class="table-head">
<th *ngFor="let tableHead of tableHeads">{{tableHead}}</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let tableData of tableDatas">
<td *ngFor="let colName of tableColNameGenerated"> {{tableData[colName]}}</td>
</tr>
</tbody>
</table>
在某个视图文件中实现此组件调用
文件: view-table.component.html
<div>
<dynamic-table [tableHeads]="tableHead"
[tableDatas]="userDetails"
[tableColName]="tableColName">
</dynamic-table>
</div>
文件: view-table.component.ts
export class ViewTable implements OnInit{
// fetch or create an Object of UserDetails type and pass it to dynamic-table
private userDetails: Array<UserDetails>;
// required to provide the table header, you can call an api or hard code the column name.
private tableHead: Array<String>;
// optional, you can hard code the property name or just send the data of an object and dynamic-table component will figure out.
private tableColName: Array<String>;
constructor(){
this.tableHead = new Array<String>('Name', 'Age', 'Gender');
// this.tableColName = new Array<String>('name', 'age', 'gender');
this.userDetails = new Array<UserDetails>();
}
ngOnInit() {
this.userDetails.push(new UserDetails('Apple', 18, 'Male'));
this.userDetails.push(new UserDetails('Banana', 24, 'Female'));
this.userDetails.push(new UserDetails('Mango', 34, 'Male'));
this.userDetails.push(new UserDetails('Orange', 13, 'Female'));
this.userDetails.push(new UserDetails('Guava', 56, 'Male'));
}
}
export class UserDetails{
constructor(public name: String, public age: Number, public gender: String) { }
}
答案 3 :(得分:0)
我的解决方案是使用Input()将列和行作为数组提供给数据表组件,它只呈现我想要看到的列和行:
组件中的:
@Input('cols')
set cols(value: string){
this._cols = value;
}
get cols(){
return this._cols;
}
Input('rows')
set rows(value: string){
this._rows = value;
}
get rows(){
return this._rows;
}
在视图中:
<app-data-table *ngIf="hotels"
[cols]="['Hotel Name','Status','Phone','Actions']"
[rows]="['HotelListTitle','HotelListSaleActive','HotelListPhone']"
[data]="hotels"
[excelData]="excelData"></app-data-table>
答案 4 :(得分:0)
这是我对Angular 5.x +的解决方案:
<div class="table-responsive">
<table class="table">
<thead>
<tr>
<th *ngFor="let cols of columnsData">{{ cols.displayName }}</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let data of tableData" >
<td *ngFor="let col of columnsData">
<input [(ngModel)]="data[col.name]" type="text" />
</td>
</tr>
</tbody>
</table>
</div>
假设您有columnsData设置像
[{displayName: 'First Name', name: 'name'}, {displayName: 'Last Name', name: 'surname'}]
当然,您可以根据需要自定义这些内容。
如果您的字段不可编辑,则可以只插入{{ data[col.name] }}
而不使用<input>
标签。
答案 5 :(得分:0)
这是给那些不想摆桌子的人
标题模型:
public tempData: any[] = [{
header: 'Import',
field: 'import'
}, {
header: 'Receive:',
field: 'receive'
}, {
header: 'Send',
field: 'send'
}],
实际数据:
public actaulData: any[] = [
{ send: 'send to data', import: 'import data', receive: 'receive data'}]
查看:
<section class="p-grid p-col-12 p-nogutter" *ngFor="let data of actaulData">
<h6 class="p-col-4 border-right">
<div *ngFor="let item of tempData">
<p>
<strong>{{ item.header }}</strong>: {{ data[item.field] }}
</p>
</div>
</h6>
答案 6 :(得分:-1)