Home > Software engineering >  How to create a generic reusable component in angular
How to create a generic reusable component in angular

Time:08-05

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

html

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

CodePudding user response:

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 >
      <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 protected]'
      }
    ];

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.

CodePudding user response:

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: '[email protected]', dob: '2001/01/01' }, 
    { name: 'Jane', email: '[email protected]', dob: '2002/02/02' }, 
    { name: 'Kane', email: '[email protected]', dob: '2003/03/03' }, 
  ]
}
  • Related