npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@tavanasystem/tips-mat-table

v1.1.5

Published

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.

Downloads

7

Readme

Tips Mat Table

Dynamic Table built with Angular Material.

Online Demo

Version(1.1.4): Checkout this Repo!

Checkout this Demo! in stackblitz.com

Table of Contents

| No. | Questions | | --- | ----------------------------------------------------------------------------- | | 1 | Getting Started | | 2 | Inputs | | 3 | Outputs | | 4 | How to add international | | 5 | Table Events | | 6 | Form Field Cell | | 7 | Button Group Cell | | 8 | Toolbar Buttons | | 9 | additional Setting with TableSetting | | 10 | Pagination | | 11 | Advance and Simple Filter | | 12 | Releases |


  1. Getting Started

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>

⬆ Back to Top


  1. Inputs:

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

⬆ Back to Top


  1. Outputs:

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.

⬆ Back to Top


  1. How to add international

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();
}

⬆ Back to Top


  1. Table Events

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",
}

⬆ Back to Top


  1. Form Field Cell

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";

⬆ Back to Top


  1. Button Group Cell

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')
}

⬆ Back to Top


  1. Toolbar Buttons

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);
}

⬆ Back to Top


  1. additional Setting with TableSetting

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;
}

⬆ Back to Top


  1. Pagination

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;
}

⬆ Back to Top


  1. Advance and Simple Filter

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 }>[];
}

⬆ Back to Top


  1. Releases

(from v1.1.3)


v1.1.4 :

Menu type in toolbar

  • if you wnat menu in footer toolbar you can set 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);
}
  • now you dont need to do some hard styling or using ::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
      },
    },
    ...
  }

v1.1.5 :

  • fix toolbar menu open position (2022/1/23)
  • fix color type to take custom ThemePalette
  • set pageIndex default value to 1 in endTyping