Significance Of Custom Table In Angular

What is the use of a custom table?

Let’s consider we are developing an application which is having multiple pages with grids. You can design it as a component and use it as Child View. There are a few benefits to this approach as mentioned below.

  • Custom table is a reusable component.
  • Easy to use and maintain.
  • Rapid development.
  • Reliable and extendable.

Example:

  1. <custom-table [records]="datas"  
  2.               [edit]="true" (childEvent)="openModal($event)">  
  3. </custom-table>  

Here, we can call a custom table component by passing the record set in our Views as per the view requirement. Let’s start from scratch.

First, let us create a component for the custom table. We will create “table-layout.component.ts”.

  1. import { Component, Input, OnChanges, EventEmitter, Output } from '@angular/core';  
  2. @Component({  
  3.     selector: 'custom-table',  
  4.     templateUrl: './table-layout.component.html'  
  5. })  
  6. export class TableLayoutComponent implements OnChanges {  
  7.     @Input() records: any[];   
  8.     keys: string[];     
  9.   
  10.     ngOnChanges() {  
  11.         if (this.records)  
  12.             this.keys = Object.keys(this.records[0]);  
  13.     }  
  14. }  

Now, we will create the “table-layout.component.html” file.

  1. <table class="table">  
  2.   
  3.     <thead>  
  4.         <tr>  
  5.             <th (click)="sort(key)" *ngFor="let key of keys">{{ key }}</th>  
  6.         </tr>  
  7.     </thead>  
  8.     <tbody>  
  9.         <tr *ngFor="let record of records">  
  10.             <td *ngFor="let key of keys">{{ record[key] }}</td>  
  11.         </tr>  
  12.     </tbody>  
  13. </table>  

Next, we have to add the reference to app module or the module where we want to use this custom table. Since I am using custom table in the app component, I am adding these references to the app module.

  1. import { BrowserModule } from '@angular/platform-browser';  
  2. import { NgModule } from '@angular/core';  
  3. import { FormsModule, ReactiveFormsModule } from '@angular/forms';  
  4.   
  5. import { AppComponent } from './app.component';  
  6. //import { CustomTableModule } from './components/custom.components/custom.table/table-layout.module';  
  7. import { TableLayoutComponent } from './components/custom.components/custom.table/table-layout.component';  
  8. import { FilterPipe } from './components/custom.components/custom.table/filter.pipe';  
  9. import {DataService} from './service';  
  10.   
  11. @NgModule({  
  12.   declarations: [  
  13.     AppComponent,  
  14.     TableLayoutComponent,  
  15.     FilterPipe  
  16.   ],  
  17.   imports: [  
  18.     BrowserModule,  
  19.     FormsModule,  
  20.     ReactiveFormsModule  
  21.   ],  
  22.   providers: [DataService],  
  23.   bootstrap: [AppComponent]  
  24. })  
  25. export class AppModule { }  

For searching, we will use pipes. We will write custom pipes for searching.

Reference Link

https://angular.io/guide/pipes

Pipes are used to transform the data when we only need that data transformed in a template.

Custom Filter pipe

  1. import { Pipe, PipeTransform, Injectable } from '@angular/core';  
  2.   
  3. @Pipe({  
  4.     name: 'filter'  
  5. })  
  6.   
  7. @Injectable()  
  8. export class FilterPipe implements PipeTransform {  
  9.     transform(items: any[], field: string, text: string): any[] {  
  10.         if (!items) {  
  11.             return [];  
  12.         }  
  13.         else if (!text) {  
  14.             return items;  
  15.         }  
  16.         else {  
  17.   
  18.             let keys = Object.keys(items[0]);  
  19.             //let type =   
  20.             let filteredItems = new Array<typeof items[0]>();  
  21.             items.forEach(item => {  
  22.   
  23.                 for (var i = 0; i < keys.length; i++) {  
  24.                     if (item[keys[i]].toString().toLowerCase().includes(text.toLowerCase())) {  
  25.                         filteredItems.push(item);  
  26.                         break;  
  27.                     }  
  28.   
  29.                 }  
  30.   
  31.             });  
  32.   
  33.             return filteredItems;  
  34.         }  
  35.     }  
  36. }  

For sorting, we will add the following method in custom table's component.ts class.

  1. sort(col: string) {  
  2.         if (this.records) {  
  3.             let res = this.sortProperties(this.records, col, falsethis.rev);  
  4.             this.records = [];  
  5.             for (let key in res) {  
  6.                 this.records.push(res[key][1]);  
  7.                 // Use `key` and `value`  
  8.             }  
  9.             this.rev = !this.rev;  
  10.         }  
  11.     }  
  12.   
  13.     sortProperties(obj: any[], sortedBy: string, isNumericSort: boolean, reverse: boolean) {  
  14.         //sortedBy = sortedBy || 1; // by default first key  
  15.         var sortable = [] as any[];  
  16.         if (obj) {  
  17.             isNumericSort = !isNaN(Number(obj[0][sortedBy]))  
  18.         }  
  19.   
  20.         reverse = reverse || false// by default no reverse  
  21.   
  22.         var reversed = (reverse) ? -1 : 1;  
  23.   
  24.         for (var key in obj) {  
  25.             if (obj.hasOwnProperty(key)) {  
  26.                 sortable.push([key, obj[key]]);  
  27.             }  
  28.         }  
  29.         if (isNumericSort)  
  30.             sortable.sort(function (a, b) {  
  31.                 return reversed * (a[1][sortedBy] - b[1][sortedBy]);  
  32.             });  
  33.         else  
  34.             sortable.sort(function (a, b) {  
  35.                 var x = a[1][sortedBy].toLowerCase(),  
  36.                     y = b[1][sortedBy].toLowerCase();  
  37.                 return x < y ? reversed * -1 : x > y ? reversed : 0;  
  38.             });  
  39.         return sortable; // array in format [ [ key1, val1 ], [ key2, val2 ], ... ]  
  40.     }  

Now, we have to add the reference of custom table component, Filterpipe in the app module.

  1. import { BrowserModule } from '@angular/platform-browser';  
  2. import { NgModule } from '@angular/core';  
  3. import { FormsModule, ReactiveFormsModule } from '@angular/forms';  
  4.   
  5. import { AppComponent } from './app.component';  
  6. //import { CustomTableModule } from './components/custom.components/custom.table/table-layout.module';  
  7. import { TableLayoutComponent } from './components/custom.components/custom.table/table-layout.component';  
  8. import { FilterPipe } from './components/custom.components/custom.table/filter.pipe';  
  9. import {DataService} from './service';  
  10.   
  11. @NgModule({  
  12.   declarations: [  
  13.     AppComponent,  
  14.     TableLayoutComponent,  
  15.     FilterPipe  
  16.   ],  
  17.   imports: [  
  18.     BrowserModule,  
  19.     FormsModule,  
  20.     ReactiveFormsModule  
  21.   ],  
  22.   providers: [DataService],  
  23.   bootstrap: [AppComponent]  
  24. })  
  25. export class AppModule { }  

Note
I have created dataservice for data fetching. We can use HTTP for using server APIs.

  1. import { Injectable } from '@angular/core';  
  2. @Injectable()  
  3. export class DataService {  
  4.     private apiUrl: string | "";  
  5.     getDatas() {  
  6.         let data = [{Id:1, Name:'Purushottam', Salary:100},  
  7.         {Id:2, Name:'Ram', Salary:110},  
  8.         {Id:3, Name:'Shayam', Salary:200}];  
  9.         return data;  
  10.     }  
  11. }  

We have seen that we can achieve a custom table design by following the described steps and we can reuse it in different Views also.

The final code of app component.ts is something like it.

  1. import { Component, OnInit } from '@angular/core';  
  2. import { DataService } from './service';  
  3.   
  4. @Component({  
  5.   selector: 'app-root',  
  6.   templateUrl: './app.component.html',  
  7.   styleUrls: ['./app.component.css']  
  8. })  
  9. export class AppComponent {  
  10.   title = 'my-app';  
  11.   public datas: any[];  
  12.   
  13.   constructor(private service:DataService){  
  14.     this.datas = this.service.getDatas();  
  15.   }    
  16.     
  17. }  

And this is the code for app.component.html.

  1. <!--The content below is only a placeholder and can be replaced.-->  
  2. <div style="text-align:center">  
  3.   <h1>  
  4.     Welcome to {{ title }}!   
  5.   </h1>  
  6.   <custom-table [records]="datas"  
  7.   [edit]="true" (childEvent)="openModal($event)">  
  8.   </custom-table>  
  9.   
  10. </div>