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.

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. ngOnChanges() {
  10. if (this.records)
  11. this.keys = Object.keys(this.records[0]);
  12. }
  13. }

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

  1. <table class="table">
  2. <thead>
  3. <tr>
  4. <th (click)="sort(key)" *ngFor="let key of keys">{{ key }}</th>
  5. </tr>
  6. </thead>
  7. <tbody>
  8. <tr *ngFor="let record of records">
  9. <td *ngFor="let key of keys">{{ record[key] }}</td>
  10. </tr>
  11. </tbody>
  12. </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. import { AppComponent } from './app.component';
  5. //import { CustomTableModule } from './components/custom.components/custom.table/table-layout.module';
  6. import { TableLayoutComponent } from './components/custom.components/custom.table/table-layout.component';
  7. import { FilterPipe } from './components/custom.components/custom.table/filter.pipe';
  8. import {DataService} from './service';
  9. @NgModule({
  10. declarations: [
  11. AppComponent,
  12. TableLayoutComponent,
  13. FilterPipe
  14. ],
  15. imports: [
  16. BrowserModule,
  17. FormsModule,
  18. ReactiveFormsModule
  19. ],
  20. providers: [DataService],
  21. bootstrap: [AppComponent]
  22. })
  23. 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. @Pipe({
  3. name: 'filter'
  4. })
  5. @Injectable()
  6. export class FilterPipe implements PipeTransform {
  7. transform(items: any[], field: string, text: string): any[] {
  8. if (!items) {
  9. return [];
  10. }
  11. else if (!text) {
  12. return items;
  13. }
  14. else {
  15. let keys = Object.keys(items[0]);
  16. //let type =
  17. let filteredItems = new Array<typeof items[0]>();
  18. items.forEach(item => {
  19. for (var i = 0; i < keys.length; i++) {
  20. if (item[keys[i]].toString().toLowerCase().includes(text.toLowerCase())) {
  21. filteredItems.push(item);
  22. break;
  23. }
  24. }
  25. });
  26. return filteredItems;
  27. }
  28. }
  29. }

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, false, this.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. sortProperties(obj: any[], sortedBy: string, isNumericSort: boolean, reverse: boolean) {
  13. //sortedBy = sortedBy || 1; // by default first key
  14. var sortable = [] as any[];
  15. if (obj) {
  16. isNumericSort = !isNaN(Number(obj[0][sortedBy]))
  17. }
  18. reverse = reverse || false; // by default no reverse
  19. var reversed = (reverse) ? -1 : 1;
  20. for (var key in obj) {
  21. if (obj.hasOwnProperty(key)) {
  22. sortable.push([key, obj[key]]);
  23. }
  24. }
  25. if (isNumericSort)
  26. sortable.sort(function (a, b) {
  27. return reversed * (a[1][sortedBy] - b[1][sortedBy]);
  28. });
  29. else
  30. sortable.sort(function (a, b) {
  31. var x = a[1][sortedBy].toLowerCase(),
  32. y = b[1][sortedBy].toLowerCase();
  33. return x < y ? reversed * -1 : x > y ? reversed : 0;
  34. });
  35. return sortable; // array in format [ [ key1, val1 ], [ key2, val2 ], ... ]
  36. }

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. import { AppComponent } from './app.component';
  5. //import { CustomTableModule } from './components/custom.components/custom.table/table-layout.module';
  6. import { TableLayoutComponent } from './components/custom.components/custom.table/table-layout.component';
  7. import { FilterPipe } from './components/custom.components/custom.table/filter.pipe';
  8. import {DataService} from './service';
  9. @NgModule({
  10. declarations: [
  11. AppComponent,
  12. TableLayoutComponent,
  13. FilterPipe
  14. ],
  15. imports: [
  16. BrowserModule,
  17. FormsModule,
  18. ReactiveFormsModule
  19. ],
  20. providers: [DataService],
  21. bootstrap: [AppComponent]
  22. })
  23. 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. @Component({
  4. selector: 'app-root',
  5. templateUrl: './app.component.html',
  6. styleUrls: ['./app.component.css']
  7. })
  8. export class AppComponent {
  9. title = 'my-app';
  10. public datas: any[];
  11. constructor(private service:DataService){
  12. this.datas = this.service.getDatas();
  13. }
  14. }

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. </div>