将列和数据动态加载到Angular 2中的表中

时间:2016-08-07 02:23:06

标签: angular

我有一个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]}}

7 个答案:

答案 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)

我对此问题的解决方案是 在HTML文件中编写此代码 enter image description here

将此代码写入Ts文件

<table>
<thead>
  <th *ngFor="let item of header">
    {{item}}
  </th>
</thead>
<tbody>
  <tr *ngFor="let record of test">
    <td *ngFor="let key of header">
      {{record[key]}}
    </td>
  </tr>
</tbody>