Dynamically loading columns and data into a table in Angular 2

I have an HTML page where I want to create a table. The columns in this table are dynamic, which means that they are selected from the server into a variable in the component using the any[]type any[]. The data in this table is also dynamic, which means that during programming, I don’t know which columns and data will get into the table.

I tried the code below, but it does not seem to work and gives no errors. It just creates a blank tdin 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>

In the above code, the columns are created successfully, but the data and collages do not work. I am sure there should be a way to achieve this in 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]}}

+6
7

<tr *ngFor="#data of data">

<tr *ngFor="#data of data" *ngModel="data[column]">
+6

Angular2 -:

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);
  }
}
+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) { }
}
+1

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>
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> , .

0

This is for those who do not want a table

Header Model:

public tempData: any[] = [{
  header: 'Import',
  field: 'import'
}, {
  header: 'Receive:',
  field: 'receive'
}, {
  header: 'Send',
  field: 'send'
}],

Current data:

public actaulData: any[] = [
{ send: 'send to data', import: 'import data', receive: 'receive data'}]

Look:

<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>

0
source

My solution to this problem is to write this code in an HTML file enter image description here

Write this code in Ts file

<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>

-1
source

Source: https://habr.com/ru/post/1650438/


All Articles