Last active
December 21, 2023 07:42
-
-
Save UmerIftikhar/17b52dfe598f2e05e94d7bacca434f22 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
export class Constants { | |
public static apiRoot = '/api', // If there is some prefix for all the APIs, then define that in constants. | |
public static API_VERSIONS = { | |
Version1: 'version1', | |
}; | |
public static pageSettings(): PageEvent { | |
return { | |
length: 0, | |
pageIndex: 0, | |
pageSize: 10, | |
}; | |
} | |
public static pageSizeOptions: number[] = [10, 25, 50, 100]; | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<p> | |
<mat-form-field> | |
<input matInput (keyup)="applySearchFilter($event.target.value)" placeholder="Search Data"> | |
</mat-form-field> | |
<button *ngIf="displayCreateAction" mat-fab (click)="performAction(userActions.Add, {})" | |
matTooltipClass="tooltip" matTooltipPosition="left" [matTooltip]="addRowText" | |
mat-flat-button color="primary" style="float:right"> | |
<mat-icon>add</mat-icon> | |
</button> | |
</p> | |
<div class="table-container"> | |
<table mat-table [dataSource]="dataSource" matSort> | |
<caption></caption> | |
<ng-container *ngFor="let columnId of objectKeys(columnDefinition)" [matColumnDef]="columnId"> | |
<ng-container *ngIf="columnId==='CRUD_OPERATION'"> | |
<th mat-header-cell *matHeaderCellDef class="table-header" id="CRUD_OPERATION"> | |
<button mat-fab matTooltipClass="tooltip" | |
(click)="performAction(userActions.Add, {})" [matTooltip]="addRowText" | |
matTooltipPosition="left" mat-flat-button color="primary" style="float:right"> | |
<mat-icon class="mat-18">add</mat-icon> | |
</button> | |
</th> | |
<td mat-cell *matCellDef="let element"> | |
<div class="actions-buttons"> | |
<button *ngIf="displayDetailAction" mat-icon-button color="primary" matTooltipClass="tooltip" [matTooltip]="viewDetailRowText" | |
(click)="performAction(userActions.Details, element)"> | |
<mat-icon class="mat-18">reorder</mat-icon> | |
</button> | |
<button *ngIf="displayEditAction" mat-icon-button color="primary" matTooltipClass="tooltip" [matTooltip]="editRowText" | |
(click)="performAction(userActions.Update, element)"> | |
<mat-icon class="mat-18">edit</mat-icon> | |
</button> | |
<button *ngIf="displayDeleteAction" mat-icon-button color="primary" matTooltipClass="tooltip" [matTooltip]="deleteRowText" | |
(click)="performAction(userActions.Delete, element)"> | |
<mat-icon class="mat-18">delete</mat-icon> | |
</button> | |
</div> | |
</td> | |
</ng-container> | |
<th id="{{columnId}}" mat-header-cell *matHeaderCellDef mat-sort-header class="table-header"> {{columnDefinition[columnId]}} </th> | |
<td mat-cell *matCellDef="let element"> {{element[columnId] }}</td> | |
</ng-container> | |
<tr mat-header-row *matHeaderRowDef="objectKeys(columnDefinition); sticky: true" class="table-header"></tr> | |
<tr class="row-custom-class" mat-row *matRowDef="let row; columns: objectKeys(columnDefinition); let i=index" [attr.id]="i"></tr> | |
</table> | |
<mat-paginator (page)="pageChanged($event)" [pageSize]="pageProperties.pageSize" | |
[length]="pageProperties.length" | |
[pageSizeOptions]="pageSizeOptions" class="mat-paginator-sticky" showFirstLastButtons="true"></mat-paginator> | |
</div> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { Component, Input, Output, EventEmitter, ViewChild, OnChanges } from '@angular/core'; | |
import { MatTable } from '@angular/material'; | |
import { MatPaginator, PageEvent } from '@angular/material/paginator'; | |
import { MatSort } from '@angular/material/sort'; | |
import { MatTableDataSource } from '@angular/material/table'; | |
import { Constants } from './constants'; | |
import { UserActions } from './helpers/'; | |
@Component({ | |
selector: 'app-generic-table', | |
templateUrl: './generic-table.component.html', | |
styleUrls: ['./generic-table.component.scss'], | |
}) | |
export class BaseTableComponent implements OnChanges { | |
// Its a key value pair, where key should be matching the columns in the table data, where as | |
// the value should be the column display name. | |
@Input() columnDefinition: any = {}; | |
// This is an array of the table data which needs to be displayed. | |
@Input() tableData: any[]; | |
// pixles after which the table data must be over flowed. | |
@Input() tableOverFlowLimit: any; | |
dataSource: MatTableDataSource<any>; // its any since, the data type is defined at runtime by the parent component. | |
pageSize = Constants.pageSettings().pageSize; // default page size for the Table. | |
pageSizeOptions: number[] = Constants.pageSizeOptions; // This tells how many items can be displayed per page. | |
pageProperties: PageEvent = Constants.pageSettings(); | |
// Column definition for the CRUD operations. | |
actionColumnName = 'Actions'; | |
// since, its a crud table, therefore an enum has been defined representing those actions. | |
readonly userActions: typeof UserActions = UserActions; | |
readonly objectKeys = Object.keys; | |
// If this is set to true, then each time the user click the next page, an API call will be made to fetch the data. | |
@Input() enableBackendPagination = false; | |
// If this is set to true, then each time the user types something in the search text, an API call will be made to fetch the data. | |
@Input() enableBackendSearch = false; | |
// Tool Tips for the respective CRUD Operations. [define the absolute values from the parent] | |
@Input() readonly addRowText: string; | |
@Input() readonly editRowText: string; | |
@Input() readonly deleteRowText: string; | |
@Input() readonly viewDetailRowText: string; | |
// Actions to be displayed for respective Table. [dnt forget to actionCalled event if any of them is enabled] | |
@Input() readonly displayEditAction: boolean = true; | |
@Input() readonly displayDeleteAction: boolean = true; | |
@Input() readonly displayDetailAction: boolean = true; | |
@Input() readonly displayCreateAction: boolean = true; | |
// This is called to notify the parent which CRUD operation is called, along with the current row object. | |
@Output() readonly actionCalled = new EventEmitter(); | |
// This is called to notify the parent when the next, previous or items per page is clicked. | |
// If enableBackendPagination is set to true, a call is made to the Parent component, which in turn calls the API. | |
@Output() readonly pageEventCalled = new EventEmitter(); | |
// This is called to notify the parent when the user types in something in the search field. | |
// If enableBackendSearch is set to true, a call is made to the Parent component, which in turn calls the API. | |
@Output() readonly searchCalled = new EventEmitter(); | |
// Respective components as per Angular Material Design Guidelines. | |
@ViewChild(MatTable, { static: true }) table: MatTable<any>; | |
@ViewChild(MatPaginator, { static: false }) paginator: MatPaginator; | |
@ViewChild(MatSort, { static: true }) sort: MatSort; | |
constructor() { | |
this.dataSource = new MatTableDataSource([]); | |
} | |
ngOnChanges() { | |
this.columnDefinition.CRUD_OPERATION = this.actionColumnName; | |
this.dataSource.data = this.tableData || []; | |
this.dataSource.sort = this.sort; | |
if (!this.enableBackendPagination) { | |
this.dataSource.paginator = this.paginator; | |
} | |
} | |
applySearchFilter(filterValue: string) { | |
const valueToSearch = filterValue.trim().toLowerCase(); | |
if(enableBackendSearch) { | |
this.searchCalled.emit(valueToSearch); | |
} | |
if (this.enableBackendPagination) { | |
this.paginator.firstPage(); | |
} else { | |
this.dataSource.filter = valueToSearch; | |
if (this.dataSource.paginator) { | |
this.dataSource.paginator.firstPage(); | |
} | |
} | |
} | |
performAction(action, obj) { | |
// If actionCalled is not defined, then simply return. | |
// Although if actions are enabled then actionCalled should also be defined as well. | |
if (!this.actionCalled) { | |
return; | |
} | |
this.actionCalled.emit({ | |
action, | |
obj, | |
}); | |
} | |
pageChanged(pageEvent: PageEvent) { | |
if (!pageEvent || !this.pageEventCalled) { | |
return; | |
} | |
this.pageEventCalled.emit(pageEvent); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
export enum UserActions { | |
Add = 'ADD', | |
Details = 'DETAILS', | |
Update = 'UPDATE', | |
Delete = 'DELETE', | |
Cancel = 'CANCEL', | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
[generic-table.component.html]
Line 46:
<td mat-cell *matCellDef="let element"> {{element[columnId] }}</td>
Should be:
<td mat-cell *matCellDef="let element"> {{element[columnDefinition[columnId]] }}</td>