Search code examples
angularangularjs-ng-repeatngfor

How can I use Angular4 *ngFor to create a data table?


I am working on a project using Angular4 to get data from an API and using*ngFor to render a data table. Because I still have more aips with same structure, I want to use (key, value) pair to display them. In AngularJS, I have correctly rendered the table like this:

<!--This is Good in AngularJS-->
 <table>
    <thead>
        <tr>
            <th ng-repeat="(key, value) in data.items[0]"> {{key}}
            </th>
        </tr>
    </thead>
    <tbody>
        <tr  ng-repeat ="data in data.items >
        <td ng-repeat="(key,value) in data">{{ value }}</td>           
        </tr>
    </tbody>
</table>

However, the table doesn't show in Angular4 correctly. The original json data from API shows like:

{
    items: [
    {
        status: "Sold - Payment Received",
        count: 30,
        loans: 8,
        dl_loans: 8,
        avg_available: 149.5,
        min: 28,
        max: 346,
        principal: 13452.37,
        closed: 0,
        chrg_of_balance: 0,
        final_balance: 0
    },
    {
        status: "At Auction - Awaiting Info",
        count: 4,
        loans: 4,
        dl_loans: 4,
        avg_available: 70.45,
        min: 36,
        max: 102,
        principal: 11727.8,
        closed: 0,
        chrg_of_balance: 0,
        final_balance: 0
    },
    ...
}

Here is my app.component.ts:

ngOnInit(): void {
    this.dataService.getData().subscribe(
      (data) => {
        this.data = data.items;
        this.titles = data.items[0];
      }
    );
}

I have created a pip.ts for filter key and value:

import { PipeTransform, Pipe } from '@angular/core';
@Pipe({name: 'keys'})
export class KeysPipe implements PipeTransform {
  transform(value, args:string[]) : any {
    let keys = [];
    for (let key in value) {
      keys.push({key: key, value: value[key]});
    }
    return keys;
  }
}

In Angular4 HTML:

<!--This is Bad in Angular4-->
<table>
 <thead align="center">
     <tr>
         <th *ngFor = "let item of titles | keys"> 
           {{item.key}}
         </th>
     </tr>
 </thead>
 <tbody>
     <tr>
      <td *ngFor = "let item of data | keys "> 
        {{item.value | json }}
      </td>           
     </tr>
 </tbody>
</table>

However the thead in UI shows fine, but the tbody part shows including the whole object (partly):

    status 
---------------------------------------
{
    status: "Sold - Payment Received",
    count: 30,
    loans: 8,
    dl_loans: 8,
    avg_available: 149.5,
    min: 28,
    max: 346,
    principal: 13452.37,
    closed: 0,
    chrg_of_balance: 0,
    final_balance: 0
 }
--------------------------------------

Anyone knows how can I render this table correctly? Thank you in advanced!


Solution

  • Use a different pipe instead of what you are using that will just return the keys of your object

    import { PipeTransform, Pipe } from '@angular/core'; 
    @Pipe({name: 'keys'})
    export class KeysPipe implements PipeTransform {
      transform(value, args:string[]) : any {
        let keys = [];
        for (let key in value) {
          keys.push(key);
        }
        return keys;
      }
    }
    

    You should change your template code as

    <thead align="center">
        <tr>
            <th *ngFor = "let item of titles | keys"> 
                {{item}}
            </th>
        </tr>
    </thead>
    <tbody>
        <tr *ngFor = "let item of data ">
            <td *ngFor = "let key of item | keys " > 
                {{item[key]}}
            </td>
        </tr>
    </tbody>
    

    This should do the trick