@servicemind.tis/angular-smart-data-table
v1.0.23
Published
Configurable Angular Material data table with server-side pagination, sorting, URL-synced filters, column customization, and custom cell templates.
Downloads
283
Readme
Angular Smart Data Table
@servicemind.tis/angular-smart-data-table is an Angular component library that provides a highly configurable and reusable smart table component for enterprise applications.
🌟 Features
- Customizable columns and templates
- Filter form integration with URL syncing
- Column customization templates with API integration
- Internationalization support (e.g., Transloco)
- Custom row background styling
- Built-in pagination and sorting
- Dynamic slot and template injection for full control
🚀 Installation
npm install @servicemind.tis/angular-smart-data-tablePeer Dependencies
npm install @angular/material @angular/cdk🔧 Usage Example
app.component.html
<ng-container *transloco="let t; read: 'serviceManagement.serviceRequestListComponent'">
<angular-smart-data-table
#mainTableWrapper
[columnCustomizationUrlConfig]="columnCustomizationUrlConfig"
[t]="t"
componentName="cm-service-request"
[mainTitle]="t('list')"
[breadcrumbs]="[{url: '/admin/service-management/cases', name: t('breadcrumb')}]"
[columnsCodeMapping]="columnsCodeMapping"
[searchPlaceholder]="t('searchPlaceholder')"
[loadDataApiBaseUrl]="loadDataApiBaseUrl"
[(pageSize)]="pageSize"
[(pageIndex)]="pageIndex"
[hideHeader]="true"
[rowsConfig]="rowsConfig"
[filterFormGroup]="filterFormGroup"
[keepFilterInUrl]="false"
[dataNotFoundConfig]="{
title: t('noDataFound'),
desc: t('noDataFoundDescription'),
btnText: t('addNew'),
btnUrl: '/admin/service-management/cases/add'
}"
>
<!-- Custom slots like filter buttons, filter section, templates, etc. -->
</angular-smart-data-table>
</ng-container>app.component.ts
import { Component, TemplateRef, ViewChild } from '@angular/core';
import { FormGroup, FormControl } from '@angular/forms';
import {
SmartTableWrapperColumnsConfig,
SmartTableWrapperRowsConfig,
AngularSmartDataTableComponent,
ColumnCustomizationUrlConfig
} from 'angular-smart-data-table';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss']
})
export class AppComponent {
@ViewChild('mainTableWrapper') tableListViewWrapperComponent!: AngularSmartDataTableComponent;
columnsCodeMapping: SmartTableWrapperColumnsConfig[] = [
{ name: 'action', serverKeyCode: 'action', type: 'action', sort: false, template: this.actionColumnTemplate },
{ name: 'description', serverKeyCode: 'description', type: 'string', sort: true, template: this.descriptionColumnTemplate },
{ name: 'sourceOfRequest', serverKeyCode: 'sourceOfRequest', type: 'string', template: this.sourceOfReColumnTemplate },
{ name: 'status', serverKeyCode: 'cmStatusId', type: 'string', template: this.statusColumnTemplate },
// Add more columns as needed...
];
@ViewChild('actionColumnTemplate') set actionColumnTemplate(tpl: TemplateRef<any>) {
this.setColumnTemplate('action', tpl);
}
@ViewChild('descriptionColumnTemplate') set descriptionColumnTemplate(tpl: TemplateRef<any>) {
this.setColumnTemplate('description', tpl);
}
@ViewChild('sourceOfReColumnTemplate') set sourceOfReColumnTemplate(tpl: TemplateRef<any>) {
this.setColumnTemplate('sourceOfRequest', tpl);
}
@ViewChild('statusColumnTemplate') set statusColumnTemplate(tpl: TemplateRef<any>) {
this.setColumnTemplate('status', tpl);
}
filterFormGroup!: FormGroup;
isShowFilter = false;
pageSize = 10;
pageIndex = 0;
loadDataApiBaseUrl = 'https://mocki.io/v1/2f34e933-74dc-4433-83ac-b66991f7e472';
columnCustomizationUrlConfig: ColumnCustomizationUrlConfig = {
list: '/user-customization/get-columns-templates',
add: '/user-customization/add-columns-template',
update: '/user-customization/update-columns-template',
delete: '/user-customization/delete-columns-template',
getSelectedTemplate: '/user-customization/get-selected-columns-template',
updateSelectedTemplate: '/user-customization/update-selected-columns-template'
};
rowsConfig: SmartTableWrapperRowsConfig = {
backgroundApplyFunction: (row: any) => row.viewsCount === 0 ? '#f2f6fc' : null
};
ngOnInit() {
this.filterFormGroup = new FormGroup({
type: new FormControl(null)
});
}
setColumnTemplate(name: string, template: TemplateRef<any>) {
const col = this.columnsCodeMapping.find(c => c.name === name);
if (col) col.template = template;
this.columnsCodeMapping = [...this.columnsCodeMapping];
}
filterRecords() {
this.tableListViewWrapperComponent.filterRecords();
this.changeFilterVisibility();
}
changeFilterVisibility() {
this.isShowFilter = !this.isShowFilter;
this.tableListViewWrapperComponent.isShowFilter = this.isShowFilter;
}
onReset() {
this.filterFormGroup.reset();
this.filterRecords();
}
}🧠 Key Interfaces
SmartTableWrapperColumnsConfig
export interface SmartTableWrapperColumnsConfig {
name: string;
type: 'string' | 'number' | 'quantity' | 'money' | 'date' | 'date-time' | 'date-time-with-seconds' | 'action';
align?: 'left' | 'right' | 'center' | null;
serverKeyCode: string;
valueKey?: string;
template?: TemplateRef<any>;
sort: boolean;
clickFn?: (rec: any, event?: MouseEvent) => void;
filterFormKey?: string;
transformQueryParamFn?: Function;
}SmartTableWrapperRowsConfig
export interface SmartTableWrapperRowsConfig {
backgroundApplyFunction?: (row: any) => string | null;
}SelectedFilterDisplayValueType
export type SelectedFilterDisplayValueType = {
value: any | any[] | null;
labelKey?: string | number | null;
valueKey: any | null;
formControlName: string;
formControlType: 'input' | 'radio' | 'date' | 'date-time' | 'toggle' | 'checkbox' | 'chip' | 'select' | 'search-select';
isSingleValue?: boolean;
selectedObjData?: any;
};SelectedFilterDisplayValuesType
export type SelectedFilterDisplayValuesType = SelectedFilterDisplayValueType[];AnyKeyValueObject
export type AnyKeyValueObject = Record<string, any>;SelectedFiltersGroupedValuesType
export type SelectedFiltersGroupedValuesType = {
formControlName: string;
formControlType: string;
arrValues: SelectedFilterDisplayValueType[];
};ColumnCustomizationUrlConfig
export interface ColumnCustomizationUrlConfig {
list: string;
add: string;
update: string;
delete: string;
getSelectedTemplate: string;
updateSelectedTemplate: string;
}DataNotFoundConfig
export type DataNotFoundConfig = {
title: string;
desc: string;
btnText?: string | null;
btnUrl?: string | null;
btnClick?: null | ((rec: any, event?: MouseEvent) => void);
secondBtnText?: string | null;
secondBtnUrl?: string | null;
secondBtnClick?: null | ((rec: any, event?: MouseEvent) => void);
};📦 Module Setup
Make sure to import AngularSmartDataTableModule and necessary Angular Material modules in your app module or standalone components.
Theming
Set these CSS variables on :root or body. All have fallbacks — unset tokens keep the library defaults.
:root {
--angular-primary: #3838a2;
--angular-danger: #bb333b;
--angular-heading-color: #212121;
--angular-light: #f5f5f5;
--angular-on-primary: #ffffff;
--angular-cancel: var(--angular-danger);
--angular-delete-icon: var(--angular-danger);
--angular-edit-icon: var(--angular-primary);
--angular-page-bg: #ffffff;
--angular-surface: #ffffff;
--angular-dialog-header-bg: #e0e0e0;
--angular-text-muted: #757575;
--angular-text-subtle: #9e9e9e;
--angular-text-body: rgba(0, 0, 0, 0.87);
--angular-breadcrumb-separator: #6c757d;
--angular-icon-muted: rgba(0, 0, 0, 0.54);
--angular-filter-badge-color: #424242;
--angular-table-border: var(--mat-table-row-item-outline-color, var(--mat-sys-outline, rgba(0, 0, 0, 0.12)));
--angular-divider: rgba(0, 0, 0, 0.12);
--angular-border-width: 1px;
--angular-radius: 5px;
--angular-page-padding: 15px;
--angular-page-title-size: 24px;
--angular-search-bg: #ffffff;
--angular-search-border: #d0d0d0;
--angular-search-icon: var(--angular-heading-color);
--angular-search-placeholder: var(--angular-text-subtle);
--angular-columns-btn-bg: #eeeeee;
--angular-columns-btn-color: var(--angular-heading-color);
--angular-header-bg: #f5f5f5;
--angular-header-color: #212121;
--angular-table-paginator-bg: #f5f5f5;
--angular-table-paginator-color: #212121;
--angular-search-radius: 4px;
--angular-search-height: 40px;
--angular-paginator-height: 25px;
--angular-paginator-width: 56px;
}🤝 Contributing
- Clone the repo
- Run
npm install - Use the demo app to test (
projects/directory) - Submit a PR or issue with details
🚀 Publishing to npm
git tag v1.0.0
git push origin v1.0.0GitHub Actions will build and publish to npm automatically if configured.
📬 Support / Questions
For bugs, suggestions, or feature requests, please open an issue on the GitHub repository.
Made with ❤️ by Thai Informatic Systems Co. Ltd
