2

I have an Angular 13 app & building a common reusable component named app-table

html

    <table class="table table-striped">
    <thead>
        <tr>
            <th>Name</th>
            <th>Email</th>
            <th>DOB</th>
        </tr>
    </thead>
    <tbody>
        <tr *ngFor="let item of tableItems">
            <td> {{ item.name }}</td>
            <td> {{ item.email } </td>
            <td> {{ item.dob }} </td>
        </tr>
    </tbody>
</table>

component.ts

    import { Component, Input, OnInit} from '@angular/core';
    import { TableItem } from './model/tableItem';

    @Component({
     selector: 'app-table',
     templateUrl: './table.component.html',
     styleUrls: ['./table.component.css'],
    })

    export class TableComponent implements OnInit {
     @Input() tableItems: TableItem[] = [];
   
     constructor() {}

     ngOnInit(): void {}
     }

Currently, this is reusable across 4-5 places, however reusability of this component is tied to name, email, dob fields. I want to make it generic so that any model could be linked to this component & can be reused across the app.

Please suggest. Thanks!

JoSSte
  • 2,953
  • 6
  • 34
  • 54
Kgn-web
  • 7,047
  • 24
  • 95
  • 161
  • 1
    I use [this datatable](https://github.com/MintPlayer/mintplayer-ng-bootstrap/tree/master/libs%2Fmintplayer-ng-bootstrap%2Fsrc%2Flib%2Fcomponents%2Fdatatable), which allows you to fully customize the cells (eg. put a `routerLink` in one cell, checkbox in another, ...). You can use it as inspiration – Pieterjan Aug 04 '22 at 18:25
  • I completely agree with Munzer. Please consider "upvoting" and/or "accepting" his [response](https://stackoverflow.com/a/73240663/421195). See also: https://www.damirscorner.com/blog/posts/20211210-GenericBaseComponentsInAngular.html – paulsm4 Aug 04 '22 at 18:28

2 Answers2

3

There are a lot of ways to do it, the simplest one would be add another input which accepts a list of columns, then you can populate your table header based on that list. something like this.

    <table class="table table-striped">
      <thead>
          <tr>
            <ng-container *ngFor="let column of columns">
              <th>{{column}}</th>
            </ng-container>
          </tr>
      </thead>
      <tbody>
          <tr *ngFor="let item of tableItems">
            <ng-container *ngFor="let column of columns">
              <td>{{item[column]}}</td>
            </ng-container>
          </tr>
      </tbody>
    </table>  

and your component will look like this.

    columns = ['name','email','dob']
    tableItems = [
      {
        name: 'test',
        dob: '31/12/1990',
        email: 'email@test.com'
      }
    ];

but table components are really difficult to maintain and extend, they require a lot of effort, it's not something you casually do. I would suggest finding a library that built a really good table component and using it, depending on your requirements, few examples would be ngx easy table, angular cdk table, and so on.

JoSSte
  • 2,953
  • 6
  • 34
  • 54
Munzer
  • 2,216
  • 2
  • 18
  • 25
1

You can get the column names from object keys and iterate over them using *ngFor, for example:

In your TableComponent template file

<table>
  <thead>
    <tr>
      <th *ngFor="let header of data[0] | keyvalue: sortNull">{{ header.key }}</th>
    </tr>
  </thead>
  <tbody>
    <tr *ngFor="let row of data">
      <td *ngFor="let cell of row | keyvalue: sortNull">{{ cell.value }}</td>
    </tr>
  </tbody>
</table>

And in typescript file

export class TableComponent {
  @Input() data: any[] = [];

  sortNull() { return 0; }
}

sortNull() is just a compartor function that always return 0 to maintain the order of insertion for your key/value pairs

And for usage

@Component({
  selector: 'app-user-list',
  template: `<app-table [data]="data"></app-table>`
})
export class UserListComponent {

  data = [ 
    { name: 'John', email: 'john@example.com', dob: '2001/01/01' }, 
    { name: 'Jane', email: 'jane@example.com', dob: '2002/02/02' }, 
    { name: 'Kane', email: 'kane@example.com', dob: '2003/03/03' }, 
  ]
}
fujy
  • 5,168
  • 5
  • 31
  • 50