Security News
CISA Brings KEV Data to GitHub
CISA's KEV data is now on GitHub, offering easier access, API integration, commit history tracking, and automated updates for security teams and researchers.
@tavanasystem/tips-mat-table
Advanced tools
tips-mat-table is an Angular component for presenting large and complex data with a lightning fast performance (at least 10x faster) and excellent level of control over the presentation.
Dynamic Table built with Angular Material.
Version(1.1.4): Checkout this Repo!
Checkout this Demo! in stackblitz.com
A full demo can be found on the github repository.
Install with npm:
npm i @tavanasystem/tips-mat-table
After installation include TipsMatTableModule
in your module imports:
import { TipsMatTableModule } from '@tavanasystem/tips-mat-table';
...
imports: [
TipsMatTableModule
],
...
Column types are defined as follow:
export interface AbstractField {
index?: number;
name: string; // The key of the data
type?: "text" | "number" | "date" | "category"; // Type of data in the field
width?: number; // width of column
header?: string; // The title of the column
print?: boolean; // disply in printing view by defualt is true
isKey?: boolean;
inlineEdit?: boolean;
display?: "visible" | "hiden" | "prevent-hidden"; // Hide and visible this column
sticky?: "start" | "end" | "none"; // sticky this column to start or end
filter?: "client-side" | "server-side" | "none";
sort?: "client-side" | "server-side" | "none";
cellClass?: string; // Apply a class to a cell, class name must be in the data
footerClass?: string;
cellStyle?: any;
footerStyle?: any;
classNames?: string;
rowClass?: string | AtClassFunc;
customSortFunction?: AtSortFunc<R>;
customFilterFunction?: AtSortFunc<R>;
toPrint?: ToPrint;
toExport?: ToExport;
inputFieldConfig?: InputFieldConfig;
btnGroupConfig?: BtnGroupConfig;
footerFn?: string | ((allData?: any[]) => string);
}
Source data must be an BehaviorSubject:
let data = [
{ "row": 1, "name": "Element #4", "weight": "65 KG", "color": "Magenta", "brand": "Zanjan Benz", "type": "Van" }, ...];
this.dataSource = new BehaviorSubject<any[]>(data);
and for updating data just next
your new data
let newData = [
{ "row": 2, "name": "Element #5", "weight": "75 KG", "color": "Magenta", "brand": "Zanjan Benz2", "type": "Van" }, ...];
this.dataSource.next(newData);
In the HTML add the selector:
<tips-mat-table
tableName="Tips Mat Table"
[columns]="fields"
[dataSource]="dataSource$"
[pending]="pending"
[tableSetting]="tableSetting"
[rowContextMenuItems]="contextMenuItems"
[rowActionMenuItems]="contextMenuItems"
[toolbarItems]="toolbarItems"
[pagination]="pagination"
[rowSelectionMode]="rowSelectionMode"
[rowSelectionModel]="selectionModel"
[expandComponent]="expandComponentRef"
(onTableEvent)="tableEvent($event)"
>
</tips-mat-table>
columns
= Column definitions
dataSource
= Table data in BehaviorSubject
pending
= pending progress on table
rowSelectionMode
= active selection row ('single' | 'multi' | 'none')
rowSelectionModel
= new SelectionModel() from Angular Material Select
pagination
= configuration for pagination. eg: { pageIndex: 0, pageSize: 10, pageSizeOptions: [ 5, 10, 100, 1000], length:30 }
tableSetting
= many general setting of table include styles and features configuration
rowContextMenuItems
= a menu that shown in right click
rowActionMenuItems
= a menu that shown in end of the row in ActionMenu
toolbarItems
= at the footer of table, with right configuration it can be very usefull
expandComponent
= you can use this to show your extra data bitween two row as expanded
onTableEvent
= all the events of table witch included in TableEvents enum can be listen from this event
export interface ContextMenuItem {
name: string;
text: string;
color?: ThemePalette | string;
icon?: string;
disabled?: boolean | ((row: any) => boolean);
visible?: boolean | ((row: any) => boolean);
divider?: boolean;
styles?: any;
keyboardKey?: string; //Ctrl+ ( keyboard key like KeyS = 's')
}
this.rowActionMenuItems = [
{
name: "Edit",
text: "Edit",
color: "primary",
icon: "edit",
disabled: (row) => row.valid, //it also can be just a value or like this a function
visible: true, //it also can be just a value or like this a function
},
{
name: "Delete",
text: "Delete Record",
color: "warn",
icon: "delete",
disabled: false, //it also can be just a value or like this a function
visible: true, //it also can be just a value or like this a function
},
];
For more examples run the demo application.
to support new language you must declare new class and implement LanguagePack for example this is persian language:
import { MatPaginatorIntl } from "@angular/material/paginator";
import {
FilterLabels,
LanguagePack,
MenuLabels,
TableLabels,
} from "@tavanasystem/tips-mat-table";
export class PersionLanguage implements LanguagePack {
constructor() {}
menuLabels: MenuLabels = {
saveData: "ذخیره داده ها ",
columnSetting: "تنظیمات ستون ها ",
saveTableSetting: "ذخیره تنظیمات جدول",
clearFilter: "فیلتر را پاک کنید",
jsonFile: "Json فایل",
csvFile: "CSV فایل",
printTable: "چاپ جدول",
filterMode: "نوع فیلتر",
filterLocalMode: "محلی",
filterServerMode: "سرور",
sortMode: "حالت مرتب سازی",
sortLocalMode: "سمت کاربر",
sortServerMode: "سمت سرور",
printMode: "حالت چاپ",
printYesMode: "بله",
printNoMode: "خیر",
pinMode: "حالت پین ",
pinNoneMode: "هیچ کدام",
pinStartMode: "شروع",
pinEndMode: "پایان",
};
paginatorLabels: MatPaginatorIntl = {
changes: null,
itemsPerPageLabel: "ایتم های هر صفحه:",
nextPageLabel: "صفحه بعدی:",
previousPageLabel: "صفحه قبلی:",
firstPageLabel: "اولین صفحه:",
lastPageLabel: "آخرین صفحه:",
getRangeLabel: (page: number, pageSize: number, length: number) => {
if (length === 0 || pageSize === 0) {
return `0 از ${length}`;
}
length = Math.max(length, 0);
const startIndex = page * pageSize;
const endIndex =
startIndex < length
? Math.min(startIndex + pageSize, length)
: startIndex + pageSize;
return `${startIndex + 1} - ${endIndex} از ${length}`;
},
};
tableLabels: TableLabels = {
NoData: "هیچ رکوردی پیدا نشد",
};
filterLabels: FilterLabels = {
Clear: "پاک کردن",
Search: "جستجو",
And: "و",
Or: "یا",
/* Text Compare */
Text: "متن",
TextContains: "دربرگرفتن",
TextEmpty: "خالی بودن",
TextStartsWith: "شروع شدن با",
TextEndsWith: " پایان گرفتن با",
TextEquals: "مساوی بودن",
TextNotEmpty: "خالی نبودن",
/* Number Compare */
Number: "تعداد",
NumberEquals: "مساوی",
NumberNotEquals: "مساوی نبودن",
NumberGreaterThan: " بزرگ تر از",
NumberLessThan: "کم تر از ",
NumberEmpty: "خالی بودن",
NumberNotEmpty: "خالی نبودن",
/* Category List Compare */
CategoryContains: "در برگرفتن",
CategoryNotContains: "در بر نگرفتن",
/* Boolean Compare */
/* Date Compare */
};
}
and passed this class to grid so :
providers: [{ provide: TableIntl, useFactory: languageIntl }];
And
export function languageIntl() {
return new PersionLanguage();
}
you can use this switch to handle all events from onTableEvent (remove those you dont need :))
export enum TableEvents {
MasterSelectionChange = "MasterSelectionChange",//depricated
RowSelectionChange = "RowSelectionChange",
RowActionMenu = "RowActionMenu",
ReloadData = "ReloadData",
RowClick = "RowClick",
CellClick = "CellClick",
DblRowClick = "DblRowClick",
DblCellClick = "DblCellClick",
BeforContextMenuOpen = "BeforContextMenuOpen",
BeforActionMenuOpen = "BeforActionMenuOpen",
ContextMenuClick = "ContextMenuClick",
SortChanged = "SortChanged",
FormFieldCellEvent = "FormFieldCellEvent",
validatonChange = "validatonChange",
settingChange = "settingChange",
ToolbarItemEvent = "ToolbarItemEvent",
PaginationEvent = "PaginationEvent",
BtnGroupCellEvent = "BtnGroupCellEvent",
SimpleFilterEvent = "SimpleFilterEvent",
FooterCellClick = "FooterCellClick",
ExportData = "ExportData",
FilterClear = "FilterClear",
CtrlKeydown = "CtrlKeydown",
}
you can also add rows with a inline form or just edit a cell with giving this config to you column definition
export interface InputFieldConfig {
// neccesseries
id: string;
fieldType: FormElementType;
//view related
icon?: string;
label?: string;
class?: string;
styles?: any;
appearance?: MatFormFieldAppearance;
floatLabel?: FloatLabelType;
hideRequiredMarker?: boolean;
hideClearBtn?: boolean;
convertor?: (id: any, row?: any, column?: any) => string;
hasSeperator?: boolean;
seperator?: string;
hasMask?: boolean;
mask?: string;
maskPatterns?: any;
enableCellEditMode?: boolean;
//validators
min?: any;
max?: any;
inputType?: InputType;
customValidator?: (row: any) => ValidatorFn;
//field states
disabled?: boolean;
required?: boolean;
readonly?: boolean;
defaultValue?: any;
//messages
hint?: string;
error?: string;
placeholder?: string;
//events
blur?: (event: any) => void;
click?: (event: any) => void;
input?: (event: any) => void;
keyup?: (event: any) => void;
change?: (event: any) => void;
onResetValue?: (row?: any) => void;
onSuffixIconClick?: (row?: any, column?: any) => void;
//for select field
options?: Observable<Partial<{ value?: any, label?: string }>[]>;
onSelectItem?: (item: any, row?: any) => void;
onDataListChanged?: (list?: any[], row?: any) => void;
hasInitSelection?: boolean;
multiple?: boolean;
valueKey?: string; //default: value
labelKey?: string; //default: label
disableKey?: string; //default: disable
// + for auto-complete field
endTyping?: (searched: any, pageIndex?: number, row?: any) => void;
NoInitEndTyping?: boolean;
// + for multi-column-autocomplete
columnsConfig?: ColumnConfig[];
footerActions?: {
icon: string,
closeAfter?: boolean,
color?: ThemePalette | string,
disabled?: boolean | ((mainRow?: any) => boolean),
}[];
onRowEvent?: (event: any, row?: any) => void;
onFooterEvent?: (event: any, searched?: string) => void;
appendNewData?: (searched?: string, pageSize?: number, row?: any) => void;
refreshData?: (row?: any) => void;
NoDataLabel?: string;
selectHeightFn?: (data: any[], row?: any, column?: any) => string;
appendedOptions?: Observable<Partial<{ value?: any, label?: string }>[]>;
// + for duplicate-mc
secondSelectConfig?: InputFieldConfig;
secondSelectControlConfig?: {
icon?: string | ((row?: any, col?: any) => string),
svgIcon?: string | ((row?: any, col?: any) => string),
switchFn?: (row?: any, column?: any) => 1 | 2,
onSwitchEvent?: (type: 1 | 2, row?: any, column?: any) => void,
};
// for checkbox
checkboxLabelPosition?: "before" | "after";
onCheckChange?: (event: any) => void;
// for input-select
defaultInputSelectMode?: "input" | "select";
// for input
inputSuffixIcon?: string | ((row?: any, col?: any) => string);
}
and for Multi Column Auto Complete :
export interface ColumnConfig {
id: string;
title: string;
width?: string;
rowActions?: {
icon: string,
color?: ThemePalette | string,
disabled?: boolean | ((option?: any) => boolean),
}[];
}
this is all the types that we support until now
export type FormElementType =
| "input"
| "select"
| "auto-complete"
| "datepicker"
| "checkbox"
| "mc-auto-complete"
| "duplicate-mc"
| "input-select";
you can have one cell with many mat-icon-button to do some actions on row, it will give you the event with row and action
export interface BtnGroupConfig {
click?: (event: any) => void;
btnConfigs?: CellBtnConfig[];
}
export interface CellBtnConfig {
id: string;
tooltip?: string;
showMode?: "edit" | "show" | "always";
color?: ThemePalette | string;
icon?: string;
svgIcon?: string;
styles?: any;
disabledFn?: boolean | ((row: any) => boolean);
hideFn?: boolean | ((row: any) => boolean);
keyboardKey?: string; //Ctrl+ ( keyboard key like KeyS = 's')
}
you can have one diffrent types of buttons with custom styles and config
export interface ToolbarItem {
id: any;
tooltip?: string; //used as title too
disabled?: boolean | ((item?: ToolbarItem) => boolean);
hidden?: boolean | ((item?: ToolbarItem) => boolean);
styles?: any | ((item?: ToolbarItem) => any);
icon?: string;
svgIcon?: string;
color?: ThemePalette | string;
menuitems?: ToolbarMenuitemConfig[];
keyboardKey?: string; //Ctrl+ ( keyboard key like KeyS = 's')
btnType?:
| "mat-button"
| "mat-raised-button"
| "mat-flat-button"
| "mat-stroked-button"
| "mat-icon-button"
| "mat-fab"
| "mat-menu"
| "mat-mini-fab"; //default
}
export interface ToolbarMenuitemConfig {
id: any;
title: string;
hide?: boolean | (() => boolean);
disable?: boolean | (() => boolean);
icon?: string;
disableIcon?: string;
styles?: any | (() => any);
}
you can customize your table on many aspects to suit your needs and desires with the Power implemented in TableSetting
export interface TableSetting {
direction?: Direction;
columnSetting?: AbstractField[];
visibaleActionMenu?: VisibleActionMenu;
stickyActionMenu?: boolean;
visibleTableMenu?: boolean;
alternativeRowStyle?: any;
normalRowStyle?: any;
rowStyle?: any;
cellStyle?: any;
footerStyle?: any;
enableContextMenu?: boolean;
headerStyles?: DmtHeaderStyles;
ActionMenuMode?: "hover" | "menu";
tableBackgroundColor?: string;
paginatorLabels?: DmtpaginatorLabels;
defaultWidth?: number;
minWidth?: number;
headerHeight?: number;
rowHeight?: number;
showNoData?: boolean;
showReload?: boolean;
printConfig?: PrintConfig;
tableName?: string;
showPagination?: boolean;
expandContainerStyle?: any;
selectOnRowClick?: boolean;
toolbarStyles?: any;
hasFooter?: boolean;
tableNoDataMessage?: string;
serverSort?: boolean;
exportMode?: "SERVER" | "CLIENT";
hasFilterOnAllColumns?: boolean;
highlightMoveActive?: boolean;
shortkeyActive?: boolean;
SelectNoDataLabel?: string;
}
and you can specifically style headers with DmtHeaderStyles
export interface DmtHeaderStyles {
headerFontSize?: string;
headerColor?: string;
headerJustify?:
| "center"
| "flex-start"
| "flex-end"
| "space-between"
| string;
headerBackgroundColor?: string;
extraStyles?: any;
}
like mat-paginator you can have pagination object like this:
export interface TablePagination {
length?: number;
pageIndex?: number;
pageSize?: number;
pageSizeOptions?: number[];
}
and you can also customize labels too:
export interface DmtpaginatorLabels {
itemsPerPageLabel: string;
nextPageLabel: string;
previousPageLabel: string;
firstPageLabel: string;
lastPageLabel: string;
toLabel: string;
fromLabel: string;
}
you have notice the filter on headers , now we add simple filter witch just have one field and give you the data on what user has entered (of course we are still developing it!)
export interface TableField<R extends TableRow> extends AbstractField {
...
footerFn?: string | ((allData?: any[]) => string);
fliterMode?: "simple" | "advance"; //'advance' is default!
simpleFilterModeConfig?: SimpleFilterModeConfig;
convertor?: (id: any, row?: any, column?: any) => string;
}
export interface SimpleFilterModeConfig {
fieldType?: "input" | "checkbox-list" | "switch"; //'input' is default!
placeholder?: string;
defaultValue?: any;
switchTitle?: string;
disabledFn?: (column: any) => boolean;
options?: Partial<{ id: number | string; value: any; label: string }>[];
}
btnType
to mat-menu
in ToolbarItem
like this: this.toolbar = [
{
...
btnType: "mat-menu",
}
and after that, you can add your options in menuitems
like this:
this.toolbar = [
{
...
btnType: "mat-menu",
menuitems: [
{
id: "1",
title: "item 1",
},
{
id: "2",
title: "item 2",
},
{
id: "3",
title: "item 3",
},
],
}
]
also this might help you in your config :
export interface ToolbarMenuitemConfig {
id: any;
title: string;
hide?: boolean | (() => boolean);
disable?: boolean | (() => boolean);
icon?: string;
disableIcon?: string;
styles?: any | (() => any);
}
::ng-deep
to style table header , simply you just need add your style object in tableSetting like this:tableSetting: TableSetting = {
...//other setting
headerStyles: {
...//other header styles
extraStyles: {
fontWeight: "900",
backgroundColor: "white",
"box-shadow": "-10px 2px 10px #ddd",
...//other styles
},
},
...
}
FAQs
tips-mat-table is an Angular component for presenting large and complex data with a lightning fast performance (at least 10x faster) and excellent level of control over the presentation.
We found that @tavanasystem/tips-mat-table demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 2 open source maintainers collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
CISA's KEV data is now on GitHub, offering easier access, API integration, commit history tracking, and automated updates for security teams and researchers.
Security News
Opengrep forks Semgrep to preserve open source SAST in response to controversial licensing changes.
Security News
Critics call the Node.js EOL CVE a misuse of the system, sparking debate over CVE standards and the growing noise in vulnerability databases.