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:
- <custom-table [records]="datas"
- [edit]="true" (childEvent)="openModal($event)">
- </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”.
- import { Component, Input, OnChanges, EventEmitter, Output } from '@angular/core';
- @Component({
- selector: 'custom-table',
- templateUrl: './table-layout.component.html'
- })
- export class TableLayoutComponent implements OnChanges {
- @Input() records: any[];
- keys: string[];
-
- ngOnChanges() {
- if (this.records)
- this.keys = Object.keys(this.records[0]);
- }
- }
Now, we will create the “table-layout.component.html” file.
- <table class="table">
-
- <thead>
- <tr>
- <th (click)="sort(key)" *ngFor="let key of keys">{{ key }}</th>
- </tr>
- </thead>
- <tbody>
- <tr *ngFor="let record of records">
- <td *ngFor="let key of keys">{{ record[key] }}</td>
- </tr>
- </tbody>
- </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.
- import { BrowserModule } from '@angular/platform-browser';
- import { NgModule } from '@angular/core';
- import { FormsModule, ReactiveFormsModule } from '@angular/forms';
-
- import { AppComponent } from './app.component';
-
- import { TableLayoutComponent } from './components/custom.components/custom.table/table-layout.component';
- import { FilterPipe } from './components/custom.components/custom.table/filter.pipe';
- import {DataService} from './service';
-
- @NgModule({
- declarations: [
- AppComponent,
- TableLayoutComponent,
- FilterPipe
- ],
- imports: [
- BrowserModule,
- FormsModule,
- ReactiveFormsModule
- ],
- providers: [DataService],
- bootstrap: [AppComponent]
- })
- 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
- import { Pipe, PipeTransform, Injectable } from '@angular/core';
-
- @Pipe({
- name: 'filter'
- })
-
- @Injectable()
- export class FilterPipe implements PipeTransform {
- transform(items: any[], field: string, text: string): any[] {
- if (!items) {
- return [];
- }
- else if (!text) {
- return items;
- }
- else {
-
- let keys = Object.keys(items[0]);
-
- let filteredItems = new Array<typeof items[0]>();
- items.forEach(item => {
-
- for (var i = 0; i < keys.length; i++) {
- if (item[keys[i]].toString().toLowerCase().includes(text.toLowerCase())) {
- filteredItems.push(item);
- break;
- }
-
- }
-
- });
-
- return filteredItems;
- }
- }
- }
For sorting, we will add the following method in custom table's component.ts class.
- sort(col: string) {
- if (this.records) {
- let res = this.sortProperties(this.records, col, false, this.rev);
- this.records = [];
- for (let key in res) {
- this.records.push(res[key][1]);
-
- }
- this.rev = !this.rev;
- }
- }
-
- sortProperties(obj: any[], sortedBy: string, isNumericSort: boolean, reverse: boolean) {
-
- var sortable = [] as any[];
- if (obj) {
- isNumericSort = !isNaN(Number(obj[0][sortedBy]))
- }
-
- reverse = reverse || false;
-
- var reversed = (reverse) ? -1 : 1;
-
- for (var key in obj) {
- if (obj.hasOwnProperty(key)) {
- sortable.push([key, obj[key]]);
- }
- }
- if (isNumericSort)
- sortable.sort(function (a, b) {
- return reversed * (a[1][sortedBy] - b[1][sortedBy]);
- });
- else
- sortable.sort(function (a, b) {
- var x = a[1][sortedBy].toLowerCase(),
- y = b[1][sortedBy].toLowerCase();
- return x < y ? reversed * -1 : x > y ? reversed : 0;
- });
- return sortable;
- }
Now, we have to add the reference of custom table component, Filterpipe in the app module.
- import { BrowserModule } from '@angular/platform-browser';
- import { NgModule } from '@angular/core';
- import { FormsModule, ReactiveFormsModule } from '@angular/forms';
-
- import { AppComponent } from './app.component';
-
- import { TableLayoutComponent } from './components/custom.components/custom.table/table-layout.component';
- import { FilterPipe } from './components/custom.components/custom.table/filter.pipe';
- import {DataService} from './service';
-
- @NgModule({
- declarations: [
- AppComponent,
- TableLayoutComponent,
- FilterPipe
- ],
- imports: [
- BrowserModule,
- FormsModule,
- ReactiveFormsModule
- ],
- providers: [DataService],
- bootstrap: [AppComponent]
- })
- export class AppModule { }
Note
I have created dataservice for data fetching. We can use HTTP for using server APIs.
- import { Injectable } from '@angular/core';
- @Injectable()
- export class DataService {
- private apiUrl: string | "";
- getDatas() {
- let data = [{Id:1, Name:'Purushottam', Salary:100},
- {Id:2, Name:'Ram', Salary:110},
- {Id:3, Name:'Shayam', Salary:200}];
- return data;
- }
- }
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.
- import { Component, OnInit } from '@angular/core';
- import { DataService } from './service';
-
- @Component({
- selector: 'app-root',
- templateUrl: './app.component.html',
- styleUrls: ['./app.component.css']
- })
- export class AppComponent {
- title = 'my-app';
- public datas: any[];
-
- constructor(private service:DataService){
- this.datas = this.service.getDatas();
- }
-
- }
And this is the code for app.component.html.
- <!--The content below is only a placeholder and can be replaced.-->
- <div style="text-align:center">
- <h1>
- Welcome to {{ title }}!
- </h1>
- <custom-table [records]="datas"
- [edit]="true" (childEvent)="openModal($event)">
- </custom-table>
-
- </div>