Table
IMPORT MODULE

st is not creating another table component, but use configurable rendering table on base of nz-table. this method can satisfy most scenes in admin interfaces, but it's easier to rendering table.

Data Source

data supports multiple formats of data sources: URL and static data.

URL

The value is URL.

  • Resolve request data format problems with parameters such as req.params, req.method

  • Resolve backend data format through res.reName mapping data

  • Use res.process to optimize data before rendering table

  • Use page.zeroIndexed to adjust the http request when pi parameter follows the 0 base index, default is 1 base index

  • Automatically cancel paging when the response body value is an array type

  • Use _HttpClient send request, so applies to AlainThemeConfig configuration

Static

The value is STData[] or Observable<STData[]>, both follow the following rules:

  • page.front Front paging, default is true

    • true controlled by st according to data length, including: sorting, filtering, etc.

    • false controlled by the user through the total and data parameters, and maintains (change) when the page changes to reload data

  • Whether page.show displays pager; if not specified, it will not be displayed automatically if ps>total

FAQ

Cannot read property 'text' of undefined

If the component has been rendered, this error may appear when columns is changed again. This is because st will only process the data according to columns each time. When the column definition changes, it may be because of the column definition. Unable to match with existing data, you may need to use this.st.resetColumns({ columns: [], emitReload: true }) to update the column definition and reload the data.

Show INVALID DATA

When an exception is thrown when parsing column data, INVALID DATA will be forced to display. For example, when a column is specified type:'number', an exception will be thrown when the actual value obtained is not a valid number type.

Examples

编号头像邮箱电话佣金(单位:元)注册时间
编号1头像邮箱aaa9@qq.com电话phone-37430佣金(单位:元)3,495,009注册时间2022-08-27 11:18
编号2头像邮箱aaa9@qq.com电话phone-70640佣金(单位:元)5,027,772注册时间2022-08-27 11:18
编号3头像邮箱aaa1@qq.com电话phone-69710佣金(单位:元)2,428,604注册时间2022-08-27 11:18
Basic

Quickly generate tables; use res to adapted backend data format.

expand codeexpand code
import { Component, ViewChild } from '@angular/core';
import { STColumn, STComponent } from '@delon/abc/st';

@Component({
  selector: 'components-st-basic',
  template: `
    <button nz-button nzType="primary" (click)="setRow()">setRow Method</button>
    <st #st [widthMode]="{ type: 'strict' }" [data]="url" [req]="{ params: params }" [columns]="columns"></st>
  `,
})
export class ComponentsStBasicComponent {
  url = `/users?total=2&field=list`;
  params = { a: 1, b: 2 };
  @ViewChild('st', { static: false }) private st!: STComponent;
  columns: STColumn[] = [
    { title: '编号', index: 'id', width: 80 },
    { title: '头像', type: 'img', width: 60, index: 'picture.thumbnail' },
    { title: '邮箱', index: 'email', width: 80 },
    { title: '电话', index: 'phone' },
    { title: { text: '佣金', optional: '(单位:元)', optionalHelp: '计算公式=订单金额 * 0.6%' }, index: 'price', type: 'currency' },
    { title: '注册时间', type: 'date', index: 'registered' },
  ];

  setRow(): void {
    this.st.setRow(0, { price: 100000000 });
  }
}
姓名年龄状态Date
编号姓名name 1年龄30状态WarningDate2022-08-27 11:18
编号姓名name 2年龄30状态ErrorDate2022-08-27 11:18
编号姓名name 3年龄29状态WarningDate2022-08-27 11:18
Custom Data

data property supports STData[]Observable data types.

expand codeexpand code
import { Component, OnInit } from '@angular/core';
import { of, delay } from 'rxjs';

import { STChange, STColumn, STData } from '@delon/abc/st';
import { dateTimePickerUtil } from '@delon/util/date-time';

@Component({
  selector: 'components-st-custom-data',
  template: `
    <div class="mb-md">
      <button (click)="st.clear()" nz-button>Clear Data</button>
      <button (click)="st.reload()" nz-button>Reload Data</button>
      <button (click)="st.clearStatus(); st.reload()" nz-button>Clear Status</button>
      <button (click)="st.setRow(0, { className: 'text-success' })" nz-button>Update Row ClassName</button>
    </div>
    <st #st [data]="users" [columns]="columns" (change)="change($event)"></st>
  `
})
export class ComponentsStCustomDataComponent implements OnInit {
  users: STData[] = [];
  columns: STColumn[] = [
    {
      title: '编号',
      index: 'id',
      type: 'checkbox',
      selections: [
        {
          text: '小于25岁',
          select: data => data.forEach(item => (item.checked = item.age < 25))
        },
        {
          text: '大于25岁',
          select: data => data.forEach(item => (item.checked = item.age >= 25))
        }
      ]
    },
    {
      title: '姓名',
      index: 'name',
      sort: {
        compare: (a, b) => a.name.length - b.name.length
      },
      filter: {
        type: 'keyword',
        placeholder: '输入后按回车搜索',
        fn: (filter, record) => !filter.value || record.name.indexOf(filter.value) !== -1
      }
    },
    {
      title: '年龄',
      index: 'age',
      sort: {
        compare: (a, b) => a.age - b.age
      },
      filter: {
        type: 'number',
        placeholder: '范围 10 ~ 100 之间',
        number: {
          min: 10,
          max: 100
        },
        fn: (filter, record) => (filter.value != null ? record.age >= +filter.value : true)
      }
    },
    {
      title: '状态',
      type: 'badge',
      index: 'status',
      badge: {
        1: { text: 'Success', color: 'success' },
        2: { text: 'Error', color: 'error' },
        3: { text: 'Processing', color: 'processing' },
        4: { text: 'Default', color: 'default' },
        5: { text: 'Warning', color: 'warning' }
      },
      filter: {
        menus: [
          { text: 'Success', value: 1 },
          { text: 'Error', value: 2 }
        ],
        fn: (filter, record) => record.age >= filter.value[0] && record.age <= filter.value[1],
        multiple: true
      }
    },
    {
      title: 'Date',
      index: 'created',
      type: 'date',
      filter: {
        type: 'date',
        date: {
          mode: 'date',
          showToday: false,
          disabledDate: dateTimePickerUtil.disabledAfterDate()
        },
        fn: () => true
      }
    }
  ];

  ngOnInit(): void {
    const data = Array(100)
      .fill({})
      .map((_, idx) => ({
        id: idx + 1,
        name: `name ${idx + 1}`,
        age: Math.ceil(Math.random() * 10) + 20,
        status: Math.floor(Math.random() * 5) + 1,
        created: new Date()
      }));
    of(data)
      .pipe(delay(500))
      .subscribe(res => (this.users = res));
  }

  change(e: STChange): void {
    console.log(e);
  }
}
行号姓名年龄HTMLTexttagbadgeEnumyn
行号1姓名name 1年龄22HTML1 OtherText<strong>1</strong> Othertag成功badge成功Enumyn
行号2姓名name 2年龄22HTML2 OtherText<strong>2</strong> Othertag错误badge警告Enumyn
行号3姓名name 3年龄30HTML3 OtherText<strong>3</strong> Othertag错误badge警告Enumyn
Column type

Support for ten different column types: no, checkbox, radio, badge, tag, image, number, currency, date, boolean badge, enum.

expand codeexpand code
import { Component } from '@angular/core';
import { STColumn, STColumnBadge, STColumnTag } from '@delon/abc/st';

const BADGE: STColumnBadge = {
  1: { text: '成功', color: 'success' },
  2: { text: '错误', color: 'error' },
  3: { text: '进行中', color: 'processing' },
  4: { text: '默认', color: 'default' },
  5: { text: '警告', color: 'warning' },
};
const TAG: STColumnTag = {
  1: { text: '成功', color: 'green' },
  2: { text: '错误', color: 'red' },
  3: { text: '进行中', color: 'blue' },
  4: { text: '默认', color: '' },
  5: { text: '警告', color: 'orange' },
};
const r = (min: number, max: number) => Math.floor(Math.random() * (max - min + 1) + min);

@Component({
  selector: 'components-st-type',
  template: `
    <button nz-button (click)="reload()">Reload</button>
    <st #st [data]="users" [columns]="columns" [page]="{ position: 'both' }"></st>
  `,
})
export class ComponentsStTypeComponent {
  users: any[] = [];
  columns: STColumn[] = [
    { title: '行号', type: 'no' },
    { title: '姓名', index: 'name' },
    { title: '年龄', index: 'age', type: 'number' },
    { title: 'HTML', index: 'html', safeType: 'safeHtml' },
    { title: 'Text', index: 'html', safeType: 'text' },
    { title: 'tag', index: 'tag', type: 'tag', tag: TAG },
    { title: 'badge', index: 'badge', type: 'badge', badge: BADGE },
    { title: 'Enum', index: 'enum', type: 'enum', enum: { 1: '壹', 2: '贰', 3: '叁' } },
    { title: 'yn', index: 'yn', type: 'yn' },
  ];

  reload(): void {
    this.users = Array(10)
      .fill({})
      .map((_, idx) => ({
        id: idx + 1,
        name: `name ${idx + 1}`,
        age: r(10, 50),
        tag: r(1, 5),
        badge: r(1, 5),
        enum: r(1, 3),
        yn: [true, false][r(1, 5) % 2],
        html: `<strong>${idx + 1}</strong> Other`,
      }));
  }

  constructor() {
    this.reload();
  }
}
头像邮箱电话注册时间
编号头像邮箱aaa4@qq.com电话phone-19024注册时间2022-08-27 11:18
编号头像邮箱aaa7@qq.com电话phone-82507注册时间2022-08-27 11:18
编号头像邮箱aaa1@qq.com电话phone-90166注册时间2022-08-27 11:18
Checkbox

Use change event get selected data.

expand codeexpand code
import { Component } from '@angular/core';

import { STChange, STColumn, STData } from '@delon/abc/st';

@Component({
  selector: 'components-st-checkbox',
  template: ` <div class="mb-md">
      <button nz-button (click)="st.checkAll(true)">All</button>
      <button nz-button (click)="st.clearCheck()">Clean</button>
    </div>
    <st
      #st
      [data]="url"
      [columns]="columns"
      [req]="{ params: params }"
      [res]="{ process: dataProcess }"
      (change)="change($event)"
    ></st>`
})
export class ComponentsStCheckboxComponent {
  url = `/users?total=100`;
  params = { a: 1, b: 2 };
  columns: STColumn[] = [
    { title: '编号', index: 'id.value', type: 'checkbox' },
    { title: '头像', type: 'img', width: 60, index: 'picture.thumbnail' },
    { title: '邮箱', index: 'email' },
    { title: '电话', index: 'phone' },
    { title: '注册时间', type: 'date', index: 'registered' }
  ];
  change(e: STChange): void {
    console.log('change', e);
  }
  dataProcess(data: STData[]): STData[] {
    return data.map((i, index) => {
      i.disabled = index === 0;
      if (index === 1) i.checked = true;
      return i;
    });
  }
}
编号头像邮箱电话注册时间
编号头像邮箱aaa2@qq.com电话phone-2867注册时间2022-08-27 11:18
编号头像邮箱aaa2@qq.com电话phone-16558注册时间2022-08-27 11:18
编号头像邮箱aaa4@qq.com电话phone-49665注册时间2022-08-27 11:18
Radio

Use change event get selected data.

expand codeexpand code
import { Component } from '@angular/core';

import { STChange, STColumn, STData } from '@delon/abc/st';

@Component({
  selector: 'components-st-radio',
  template: ` <div class="mb-md">
      <button nz-button (click)="st.setRow(1, { checked: true })">Radio second</button>
      <button nz-button (click)="st.clearRadio()">Clean</button>
    </div>
    <st
      #st
      [data]="url"
      [columns]="columns"
      [req]="{ params: params }"
      [res]="{ process: dataChange }"
      (change)="change($event)"
    ></st>`
})
export class ComponentsStRadioComponent {
  url = `/users?total=300`;
  params = { a: 1, b: 2 };
  columns: STColumn[] = [
    { title: '编号', index: 'id', type: 'radio', width: 70 },
    { title: '头像', type: 'img', width: 60, index: 'picture.thumbnail' },
    { title: '邮箱', index: 'email' },
    { title: '电话', index: 'phone' },
    { title: '注册时间', type: 'date', index: 'registered' }
  ];

  change(ret: STChange): void {
    console.log('change', ret);
  }

  dataChange(data: STData[]): STData[] {
    return data.map((i, index) => {
      i.disabled = index === 0;
      i.hidden = index === 1;
      return i;
    });
  }
}
编号邮箱电话注册时间
编号1邮箱aaa8@qq.com电话phone-13572注册时间2022-08-27 11:18
编号2邮箱aaa6@qq.com电话phone-8592注册时间2022-08-27 11:18
编号3邮箱aaa9@qq.com电话phone-21081注册时间2022-08-27 11:18
Context Menu

Use contextmenu to implement the contextmenu of the table.

expand codeexpand code
import { Component } from '@angular/core';
import { STColumn, STContextmenuFn, STContextmenuItem, STContextmenuOptions } from '@delon/abc/st';
import { NzMessageService } from 'ng-zorro-antd/message';

@Component({
  selector: 'components-st-contextmenu',
  template: `
    <st
      #st
      [widthMode]="{ type: 'strict' }"
      [data]="url"
      [req]="{ params: params }"
      [columns]="columns"
      [contextmenu]="handleContextmenu"
    ></st>
  `,
})
export class ComponentsStContextmenuComponent {
  url = `/users?total=2&field=list`;
  params = { a: 1, b: 2 };
  columns: STColumn[] = [
    { title: '编号', index: 'id', width: 80 },
    { title: '邮箱', index: 'email', width: 80 },
    { title: '电话', index: 'phone' },
    { title: '注册时间', type: 'date', index: 'registered' },
  ];

  constructor(private msg: NzMessageService) {}

  private show(options: STContextmenuOptions, item: STContextmenuItem): void {
    if (options.type === 'head') {
      this.msg.info(`点击标题,下标为:${options.colIndex},当前按钮为:${item.text}`);
    } else {
      this.msg.info(`点击单元格,行下标为:${options.rowIndex},列下标为:${options.colIndex},当前按钮为:${item.text}`);
    }
  }

  handleContextmenu: STContextmenuFn = (options): STContextmenuItem[] => {
    if (options.type === 'head') {
      return [
        {
          text: 'Click me',
          fn: item => this.show(options, item),
        },
      ];
    }
    return [
      {
        text: 'Edit',
        fn: item => this.show(options, item),
      },
      {
        text: 'View',
        fn: item => this.show(options, item),
      },
      {
        text: 'Next',
        children: [
          {
            text: 'Nothing',
            fn: item => this.show(options, item),
          },
          {
            text: 'asdf',
            fn: item => this.show(options, item),
          },
        ],
      },
    ];
  };
}
编号姓名年龄启用OP
编号1姓名name 1年龄21启用YOPEdit
编号2姓名name 2年龄30启用NOPEdit
编号3姓名name 3年龄21启用YOPEdit
Editable Rows

Table with editable rows.

expand codeexpand code
import { Component, ViewChild } from '@angular/core';
import { STColumn, STComponent, STData } from '@delon/abc/st';
import { NzMessageService } from 'ng-zorro-antd/message';

@Component({
  selector: 'components-st-edit-row',
  template: `
    <st #st [data]="users" [columns]="columns">
      <ng-template st-row="nameTpl" let-item let-index="index">
        <input *ngIf="item.edit" nz-input [ngModel]="item.name" (ngModelChange)="st.setRow(index, { name: $event })" />
        <ng-container *ngIf="!item.edit">{{ item.name }}</ng-container>
      </ng-template>
      <ng-template st-row="ageTpl" let-item let-index="index">
        <nz-input-number *ngIf="item.edit" [ngModel]="item.age" (ngModelChange)="st.setRow(index, { age: $event })"></nz-input-number>
        <ng-container *ngIf="!item.edit">{{ item.age }}</ng-container>
      </ng-template>
      <ng-template st-row="enabledTpl" let-item let-index="index">
        <nz-switch *ngIf="item.edit" [ngModel]="item.enabled" (ngModelChange)="st.setRow(index, { enabled: $event })"></nz-switch>
        <ng-container *ngIf="!item.edit">{{ item.enabled ? 'Y' : 'N' }}</ng-container>
      </ng-template>
    </st>
  `,
})
export class ComponentsStEditRowComponent {
  @ViewChild('st') private st!: STComponent;
  users: STData[] = Array(10)
    .fill({})
    .map((_, idx) => {
      return {
        id: idx + 1,
        name: `name ${idx + 1}`,
        age: Math.ceil(Math.random() * 10) + 20,
        enabled: idx % 2 === 0,
      };
    });
  columns: STColumn[] = [
    { title: '编号', index: 'id' },
    { title: '姓名', index: 'name', render: 'nameTpl' },
    { title: '年龄', index: 'age', render: 'ageTpl' },
    { title: '启用', index: 'enabled', render: 'enabledTpl' },
    {
      title: 'OP',
      buttons: [
        {
          text: `Edit`,
          iif: i => !i.edit,
          click: i => this.updateEdit(i, true),
        },
        {
          text: `Save`,
          iif: i => i.edit,
          click: i => {
            this.submit(i);
          },
        },
        {
          text: `Cancel`,
          iif: i => i.edit,
          click: i => this.updateEdit(i, false),
        },
      ],
    },
  ];

  constructor(private msg: NzMessageService) {}

  private submit(i: STData): void {
    this.msg.success(JSON.stringify(this.st.pureItem(i)));
    this.updateEdit(i, false);
  }

  private updateEdit(i: STData, edit: boolean): void {
    this.st.setRow(i, { edit }, { refreshSchema: true });
  }
}
编号头像邮箱电话注册时间
编号1头像邮箱aaa8@qq.com电话phone-83725注册时间2022-08-27 11:18
编号2头像邮箱aaa2@qq.com电话phone-49377注册时间2022-08-27 11:18
编号3头像邮箱aaa3@qq.com电话phone-34300注册时间2022-08-27 11:18
Search form

Implement search form with load() & reset().

expand codeexpand code
import { Component } from '@angular/core';
import { STColumn } from '@delon/abc/st';

@Component({
  selector: 'components-st-form',
  template: `
    <div class="mb-md">
      <input nz-input [(ngModel)]="params.name" name="name" nzPlaceHolder="请输入姓名" style="width: 100px;" class="mr-sm" />
      <button nz-button (click)="st.load(1)" [nzType]="'primary'">搜索</button>
      <button nz-button (click)="params = {}; st.reset()">重置</button>
    </div>
    <st #st [data]="url" [req]="{ params: params }" [columns]="columns"></st>
  `,
})
export class ComponentsStFormComponent {
  url = `/users?total=100`;
  params: { name?: string } = { name: 'asdf' };
  columns: STColumn[] = [
    { title: '编号', index: 'id', default: '-' },
    { title: '头像', type: 'img', width: 60, index: 'picture.thumbnail' },
    { title: '邮箱', index: 'email' },
    { title: '电话', index: 'phone' },
    { title: '注册时间', type: 'date', index: 'registered' },
  ];
}
编号邮箱电话
编号1邮箱aaa4@qq.com电话phone-5332
编号2邮箱aaa7@qq.com电话phone-79695
编号3邮箱aaa6@qq.com电话phone-41258
Row OP

Operations on rows using addRow, removeRow, setRow methods.

Open the control panel for print details.

expand codeexpand code
import { Component } from '@angular/core';

import { STChange, STClickRowClassNameType, STColumn } from '@delon/abc/st';

@Component({
  selector: 'components-st-row-op',
  template: ` <button nz-button (click)="st.addRow({ id: 1000, email: 'add@email.com', phone: '123' })"> addRow</button>
    <button nz-button (click)="st.removeRow(0)"> removeRow index: 0 </button>
    <button nz-button (click)="st.setRow(0, { className: 'text-success' })"> Via setRow method </button>
    <st
      #st
      [data]="url"
      [req]="{ params: params }"
      [columns]="columns"
      (change)="_click($event)"
      [clickRowClassName]="clickRowClassName"
    ></st>`
})
export class ComponentsStRowOpComponent {
  url = `/users?results=3`;
  params = { a: 1, b: 2 };
  clickRowClassName: STClickRowClassNameType = { exclusive: true, fn: () => 'text-error' };
  columns: STColumn[] = [
    { title: '编号', index: 'id' },
    { title: '邮箱', index: 'email' },
    { title: '电话', index: 'phone' }
  ];

  _click(e: STChange): void {
    console.log('click', e);
  }
}
编号头像姓名国家性别注册时间
编号1头像姓名1: last-4 first-15国家CH性别male注册时间2022-08-27 11:18
编号2头像姓名2: last-7 first-10国家US性别female注册时间2022-08-27 11:18
编号3头像姓名3: last-4 first-14国家DE性别male注册时间2022-08-27 11:18
Backend filtering and sorting

Using multiSort supported multi-field sorting.

expand codeexpand code
import { Component } from '@angular/core';
import { STColumn, STData } from '@delon/abc/st';

interface UserData extends STData {
  name: {
    last: string;
    first: string;
  }
}

@Component({
  selector: 'components-st-sort',
  template: `
    <button nz-button (click)="st.reset()">重置</button>
    <st #st [data]="url" [req]="{ params: params }" [columns]="columns" multiSort></st>
  `,
})
export class ComponentsStSortComponent {
  url = `/users?total=200`;
  params = { a: 1, b: 2 };
  columns: STColumn<UserData>[] = [
    { title: '编号', index: 'id' },
    { title: '头像', type: 'img', width: 60, index: 'picture.thumbnail' },
    {
      title: '姓名',
      index: 'name.last',
      format: (item, _col, index) => `${index + 1}: ${item.name.last} ${item.name.first}`,
      sort: true,
    },
    {
      title: '国家',
      index: 'nat',
      filter: {
        menus: [
          { text: '中国', value: 'CH' },
          { text: '美国', value: 'US' },
          { text: '德国', value: 'DE' },
        ],
      },
      sort: true,
    },
    {
      title: '性别',
      index: 'gender',
      filter: {
        menus: [
          { text: 'male', value: 'male' },
          { text: 'female', value: 'female' },
        ],
        multiple: false,
      },
      sort: true,
    },
    { title: '注册时间', type: 'date', index: 'registered' },
  ];
}
编号姓名年龄
编号1姓名name 1年龄22Button
编号2姓名name 2年龄22Button
编号3姓名name 3年龄22Button
Expandable Row

Use #expand template implement expandable, allowing you to receive three values: item, index, column. Additional achievable: nested subtables.

expand codeexpand code
import { Component } from '@angular/core';
import { STColumn, STData } from '@delon/abc/st';

@Component({
  selector: 'components-st-expand',
  template: `
    <st [data]="users" [columns]="columns" [expand]="expand" expandRowByClick expandAccordion>
      <ng-template #expand let-item let-index="index" let-column="column">
        {{ item.description }}
      </ng-template>
    </st>
  `,
})
export class ComponentsStExpandComponent {
  users: STData[] = Array(10)
    .fill({})
    .map((_, idx) => ({
      id: idx + 1,
      name: `name ${idx + 1}`,
      age: Math.ceil(Math.random() * 10) + 20,
      // 是否显示展开按钮
      showExpand: idx !== 0,
      description: `${idx + 1}. My name is John Brown, I am 32 years old, living in New York No. 1 Lake Park.`,
    }));
  columns: STColumn[] = [
    { title: '编号', index: 'id' },
    { title: '姓名', index: 'name' },
    { title: '年龄', index: 'age' },
    {
      buttons: [
        {
          text: 'Button',
        },
      ],
    },
  ];
}
编号姓名年龄自定义
编号1姓名name 1年龄21自定义tooltip: 21-0
编号2姓名name 2年龄21自定义tooltip: 21-1
编号3姓名name 3年龄21自定义tooltip: 21-2
Custom columns

Create a ng-template with st-row="custom-name" and specify the name in the column description render: 'custom-name'; template receive item, index, column three values.

Specifying type="title" means to customize the column for the title. Additional achievable: header grouping.

expand codeexpand code
import { Component } from '@angular/core';
import { STColumn, STData } from '@delon/abc/st';

@Component({
  selector: 'components-st-render',
  template: `
    <div class="mb-md">
      <nz-checkbox-group
        [(ngModel)]="customColumns"
        name="customColumns"
        (ngModelChange)="st.resetColumns({ emitReload: true })"
      ></nz-checkbox-group>
    </div>
    <st #st [data]="users" [columns]="columns">
      <ng-template st-row="customTitle" type="title" let-c>
        {{ c.title.text }}
        <span nz-dropdown [nzDropdownMenu]="menuTpl" nzTrigger="click" [nzClickHide]="false" nzPlacement="bottomRight">
          <i nz-icon nzType="down"></i>
        </span>
        <nz-dropdown-menu #menuTpl="nzDropdownMenu">
          <div class="ant-table-filter-dropdown p-sm">
            <input type="text" nz-input placeholder="Search name" [(ngModel)]="searchValue" name="searchValue" class="width-sm mr-sm" />
            <button nz-button [nzType]="'primary'" (click)="st.load(2)">Search</button>
          </div>
        </nz-dropdown-menu>
      </ng-template>
      <ng-template st-row="custom" let-item let-index="index">
        <span nz-tooltip [nzTooltipTitle]="'年龄:' + item.age">tooltip: {{ item.age }}-{{ index }}</span>
      </ng-template>
    </st>
  `,
})
export class ComponentsStRenderComponent {
  searchValue?: string;
  users: STData[] = Array(10)
    .fill({})
    .map((_, idx) => {
      return {
        id: idx + 1,
        name: `name ${idx + 1}`,
        age: Math.ceil(Math.random() * 10) + 20,
      };
    });
  columns: STColumn[] = [
    { title: '编号', index: 'id' },
    { title: '姓名', index: 'name', iif: () => this.isChoose('name') },
    { title: '年龄', index: 'age', iif: () => this.isChoose('age') },
    {
      title: '自定义',
      renderTitle: 'customTitle',
      render: 'custom',
      iif: () => this.isChoose('custom'),
    },
  ];
  customColumns = [
    { label: '姓名', value: 'name', checked: true },
    { label: '年龄', value: 'age', checked: true },
    { label: '自定义', value: 'custom', checked: true },
  ];

  isChoose(key: string): boolean {
    return !!this.customColumns.find(w => w.value === key && w.checked);
  }
}
序号编号姓名年龄操作区
序号1编号1姓名name 1年龄22操作区EditDrawer更多
序号2编号2姓名name 2年龄28操作区EditDrawer更多
序号3编号3姓名name 3年龄27操作区EditDrawer更多
Custom Buttons

Build a button group with the buttons property.

Generate a set of button group with a simple configuration (example code: DemoModalComponent, DemoDrawerComponent).

The modal is handled by ModalHelper and the drawer is handled by DrawerHelper.

expand codeexpand code
import { Component } from '@angular/core';

import { DemoDrawerComponent, DemoModalComponent } from '@shared';

import { STChange, STColumn, STData } from '@delon/abc/st';
import { NzMessageService } from 'ng-zorro-antd/message';

@Component({
  selector: 'components-st-buttons',
  template: ` <st [data]="users" [columns]="columns" (change)="change($event)"></st> `
})
export class ComponentsStButtonsComponent {
  constructor(private message: NzMessageService) {}

  users: STData[] = Array(10)
    .fill({})
    .map((_, idx) => ({
      id: idx + 1,
      name: `name ${idx + 1}`,
      age: Math.ceil(Math.random() * 10) + 20
    }));
  columns: STColumn[] = [
    { title: '序号', type: 'no' },
    { title: '编号', index: 'id' },
    { title: '姓名', index: 'name' },
    { title: '年龄', index: 'age' },
    {
      title: '操作区',
      buttons: [
        {
          text: 'Edit',
          icon: 'edit',
          type: 'modal',
          modal: {
            component: DemoModalComponent
          },
          click: (_record, modal) => this.message.success(`重新加载页面,回传值:${JSON.stringify(modal)}`)
        },
        {
          text: 'Drawer',
          type: 'drawer',
          drawer: {
            title: '编辑',
            component: DemoDrawerComponent
          },
          click: (_record, modal) => this.message.success(`重新加载页面,回传值:${JSON.stringify(modal)}`)
        },
        {
          icon: 'check-circle',
          click: record => this.message.info(`check-${record.name}`),
          iif: record => record.id % 2 === 0,
          iifBehavior: 'disabled',
          tooltip: `Is disabled button`
        },
        {
          icon: 'delete',
          type: 'del',
          pop: {
            title: 'Yar you sure?',
            okType: 'danger',
            icon: 'star'
          },
          click: (record, _modal, comp) => {
            this.message.success(`成功删除【${record.name}】`);
            comp!.removeRow(record);
          },
          iif: record => record.id % 2 === 0
        },
        {
          text: '更多',
          children: [
            {
              text: record => (record.id === 1 ? `过期` : `正常`),
              click: record => this.message.error(`${record.id === 1 ? `过期` : `正常`}【${record.name}】`)
            },
            {
              text: `审核`,
              click: record => this.message.info(`check-${record.name}`),
              iif: record => record.id % 2 === 0,
              iifBehavior: 'disabled',
              tooltip: 'This is tooltip'
            },
            {
              type: 'divider'
            },
            {
              text: `重新开始`,
              icon: 'edit',
              click: record => this.message.success(`重新开始【${record.name}】`)
            }
          ]
        }
      ]
    }
  ];

  change(e: STChange): void {
    console.log(e);
  }
}
编号自定义头像邮箱
编号1自定义头像邮箱aaa6@qq.com
编号2自定义头像邮箱aaa9@qq.com
编号3自定义头像邮箱aaa4@qq.com
Custom Widgets

The type is widget custom widget, eg: Click on Avatar effect.

expand codeexpand code
import { Component, ViewChild } from '@angular/core';
import { STColumn, STComponent } from '@delon/abc/st';

@Component({
  selector: 'components-st-widget',
  template: `
    <div class="mb-md">
      <button (click)="st.clear()" nz-button>Clear Data</button>
      <button (click)="st.reload()" nz-button>Reload Data</button>
      <button (click)="st.clearStatus(); st.reload()" nz-button>Clear Status</button>
      <button (click)="changeImg()" nz-button>Change Img Data</button>
    </div>
    <st #st [data]="url" [columns]="columns"></st>
  `,
})
export class ComponentsStWidgetComponent {
  url = `/users?total=100`;
  @ViewChild('st', { static: false }) private st!: STComponent;
  columns: STColumn[] = [
    { title: '编号', index: 'id', width: 80 },
    {
      title: '自定义头像',
      type: 'widget',
      widget: { type: 'img', params: ({ record }) => ({ img: record.picture.thumbnail }) },
      width: 150,
    },
    { title: '邮箱', index: 'email' },
  ];

  changeImg(): void {
    this.st.setRow(
      0,
      { picture: { thumbnail: 'https://ng-alain.com/assets/img/logo-color.svg' } },
      { refreshSchema: true, emitReload: false },
    );
  }
}
编号1编号2编号3编号4编号5编号6编号7编号8编号8编号8编号8编号8姓名10姓名11年龄12
编号11编号21编号31编号41编号51编号61编号71编号81编号81编号81编号81编号81姓名10name 1姓名11name 1年龄1226
编号12编号22编号32编号42编号52编号62编号72编号82编号82编号82编号82编号82姓名10name 2姓名11name 2年龄1223
编号13编号23编号33编号43编号53编号63编号73编号83编号83编号83编号83编号83姓名10name 3姓名11name 3年龄1222
Fixed columns

To fix some columns and scroll inside other columns, and you must set scroll.x, left and right meanwhile.

We use sticky property to fixed column,browsers support.

  • Specify the width of th if header and cell do not align properly.

  • A fixed value which is greater than table width for scroll.x is recommended. The sum of unfixed columns should not greater than scroll.x.

expand codeexpand code
import { Component } from '@angular/core';
import { STColumn, STData } from '@delon/abc/st';

@Component({
  selector: 'components-st-fixed',
  template: ` <st [data]="users" [columns]="columns" [scroll]="{ x: '1300px' }"></st> `,
})
export class ComponentsStFixedComponent {
  users: STData[] = Array(10)
    .fill({})
    .map((_, idx) => {
      return {
        id: idx + 1,
        name: `name ${idx + 1}`,
        age: Math.ceil(Math.random() * 10) + 20,
      };
    });
  columns: STColumn[] = [
    { title: '编号1', index: 'id', fixed: 'left', width: 100 },
    { title: '编号2', index: 'id', fixed: 'left', width: 100 },
    { title: '编号3', index: 'id', fixed: 'left', width: 100 },
    { title: '编号4', index: 'id' },
    { title: '编号5', index: 'id' },
    { title: '编号6', index: 'id' },
    { title: '编号7', index: 'id' },
    { title: '编号8', index: 'id' },
    { title: '编号8', index: 'id' },
    { title: '编号8', index: 'id' },
    { title: '编号8', index: 'id' },
    { title: '编号8', index: 'id' },
    { title: '姓名10', index: 'name', fixed: 'right', width: 100 },
    { title: '姓名11', index: 'name', fixed: 'right', width: 100 },
    { title: '年龄12', index: 'age', fixed: 'right', width: 100 },
  ];
}
编号Other
头像邮箱姓名
firstlast
编号1头像邮箱aaa2@qq.comfirstfirst-16lastlast-8
编号2头像邮箱aaa9@qq.comfirstfirst-13lastlast-5
编号3头像邮箱aaa2@qq.comfirstfirst-10lastlast-3
Grouping table head

Group table head with columns[n].children.

expand codeexpand code
import { Component } from '@angular/core';
import { STColumn } from '@delon/abc/st';

@Component({
  selector: 'components-st-grouping-columns',
  template: ` <st #st [data]="url" [req]="{ params: params }" [columns]="columns" bordered size="middle"> </st>`,
})
export class ComponentsStGroupingColumnsComponent {
  url = `/users?total=2&field=list`;
  params = { a: 1, b: 2 };
  columns: STColumn[] = [
    { title: '编号', index: 'id', sort: true, width: 100 },
    {
      title: 'Other',
      children: [
        { title: '头像', type: 'img', index: 'picture.thumbnail', width: 60 },
        { title: '邮箱', index: 'email' },
        {
          title: '姓名',
          sort: true,
          children: [
            { title: 'first', index: 'name.first', sort: true },
            { title: 'last', index: 'name.last' },
          ],
        },
      ],
    },
  ];
}
The header
编号头像邮箱电话注册时间
编号1头像邮箱aaa8@qq.com电话phone-71645注册时间2022-08-27 11:18
编号2头像邮箱aaa5@qq.com电话phone-82341注册时间2022-08-27 11:18
编号3头像邮箱aaa2@qq.com电话phone-4578注册时间2022-08-27 11:18
The footer
Responsive

Table columns are displayed as stacked in responsive mode if the screen size becomes smaller.

expand codeexpand code
import { Component } from '@angular/core';
import { STColumn } from '@delon/abc/st';

@Component({
  selector: 'components-st-responsive',
  template: ` <st
    [data]="url"
    [req]="{ params: params }"
    [columns]="columns"
    header="The header"
    footer="The footer"
    responsiveHideHeaderFooter
  >
  </st>`,
})
export class ComponentsStResponsiveComponent {
  url = `/users?total=100`;
  params = { a: 1, b: 2 };
  columns: STColumn[] = [
    { title: '编号', index: 'id' },
    { title: '头像', type: 'img', width: 60, index: 'picture.thumbnail' },
    { title: '邮箱', index: 'email' },
    { title: '电话', index: 'phone' },
    { title: '注册时间', type: 'date', index: 'registered' },
  ];
}
行号编号性别SumAverageMinMaxCustom
行号1编号1性别Sum0Average0Min0Max0Custom0
行号2编号2性别Sum41Average41Min41Max41Custom41
行号3编号3性别Sum54Average54Min54Max54Custom54
合计3 个29531.670540
性别平均值31.67
Statistical

Support count, distinctCount, sum, average, max, min or custom function statistics methods.

expand codeexpand code
import { Component } from '@angular/core';
import { STColumn, STData } from '@delon/abc/st';

@Component({
  selector: 'components-st-statistical',
  template: `
    <button nz-button (click)="data = []">Clean Data</button>
    <st #st [data]="data" [columns]="columns" [body]="bodyTpl">
      <ng-template #bodyTpl let-s>
        <ng-container *ngIf="st.count > 0">
          <tr>
            <td>合计</td>
            <td>{{ s.len.text }} 个</td>
            <td>{{ s.dc.text }}</td>
            <td class="text-right">{{ s.sum.text }}</td>
            <td class="text-right">{{ s.avg.text }}</td>
            <td class="text-right">{{ s.min.text }}</td>
            <td class="text-right">{{ s.max.text }}</td>
            <td class="text-right">{{ s.custom.text }}</td>
          </tr>
          <tr class="bg-grey-lighter">
            <td colspan="3">性别平均值</td>
            <td class="text-right">{{ s.sum.value / s.len.value | price }}</td>
            <td colspan="4"></td>
          </tr>
        </ng-container>
      </ng-template>
    </st>
  `,
})
export class ComponentsStStatisticalComponent {
  data: STData[] = Array(100)
    .fill({})
    .map((_, idx) => ({
      id: idx + 1,
      price: ~~(Math.random() * 100),
      age: ~~(Math.random() * 100) > 50 ? '女' : '男',
    }));
  columns: STColumn[] = [
    { title: '行号', type: 'no' },
    { title: '编号', index: 'id', statistical: 'count', key: 'len' },
    { title: '性别', index: 'age', statistical: 'distinctCount', key: 'dc' },
    { title: 'Sum', index: 'price', type: 'currency', statistical: 'sum', key: 'sum' },
    { title: 'Average', index: 'price', type: 'currency', statistical: 'average', key: 'avg' },
    { title: 'Min', index: 'price', type: 'currency', statistical: 'min', key: 'min' },
    { title: 'Max', index: 'price', type: 'currency', statistical: 'max', key: 'max' },
    {
      title: 'Custom',
      index: 'price',
      type: 'currency',
      statistical: { type: values => ({ value: values[0], text: `**${values[0]}` }), currency: false },
      key: 'custom',
    },
  ];
}
编号价格1价格2价格3价格4价格5价格6价格7价格8价格9价格10
Virtual Scroll

Virtual scrolling combine with cdk scrolling used to display large data, you can get cdkVirtualScrollViewport in STComponent and find more API here.

expand codeexpand code
import { AfterViewInit, Component, OnDestroy, ViewChild } from '@angular/core';
import { STColumn, STComponent, STPage } from '@delon/abc/st';
import { Subject, takeUntil } from 'rxjs';

@Component({
  selector: 'components-st-virtual',
  template: `
    <button nz-button (click)="scrollToIndex(200)">Scroll To Index 200</button>
    <st #st [data]="data" [columns]="columns" [page]="page" virtualScroll [scroll]="{ x: '1300px', y: '240px' }"></st>
  `,
})
export class ComponentsStVirtualComponent implements AfterViewInit, OnDestroy {
  private destroy$ = new Subject<void>();
  @ViewChild('st', { static: false }) st!: STComponent;

  page: STPage = {
    front: false,
    show: false,
  };
  data: Array<{ id: number; price: number }> = Array(2000)
    .fill({})
    .map((_, idx) => ({
      id: idx + 1,
      price: ~~(Math.random() * 100),
    }));
  columns: STColumn[] = [
    { title: '编号', index: 'id', width: 100 },
    { title: '价格1', index: 'price', width: 100 },
    { title: '价格2', index: 'price', width: 100 },
    { title: '价格3', index: 'price', width: 100 },
    { title: '价格4', index: 'price', width: 100 },
    { title: '价格5', index: 'price', width: 100 },
    { title: '价格6', index: 'price', width: 100 },
    { title: '价格7', index: 'price', width: 100 },
    { title: '价格8', index: 'price', width: 100 },
    { title: '价格9', index: 'price', width: 100 },
    { title: '价格10', index: 'price', width: 100 },
  ];

  scrollToIndex(index: number): void {
    this.st.cdkVirtualScrollViewport.scrollToIndex(index);
  }

  ngAfterViewInit(): void {
    this.st.cdkVirtualScrollViewport.scrolledIndexChange.pipe(takeUntil(this.destroy$)).subscribe(data => {
      console.log('scroll index to', data);
    });
  }

  ngOnDestroy(): void {
    this.destroy$.next();
    this.destroy$.complete();
  }
}
编号头像邮箱电话数字货币注册时间
编号1头像邮箱e1@qq.com电话phone - 1数字15,345,671货币15,345,671注册时间2022-08-27 11:18
编号2头像邮箱e2@qq.com电话phone - 2数字13,833,475货币13,833,475注册时间2022-08-27 11:18
编号3头像邮箱e3@qq.com电话phone - 3数字10,053,749货币10,053,749注册时间2022-08-27 11:18
Export Excel

Save the table data as Excel.

expand codeexpand code
import { Component, ViewChild } from '@angular/core';
import { STColumn, STComponent, STData } from '@delon/abc/st';

@Component({
  selector: 'components-st-export',
  template: `
    <button nz-button (click)="st.export()">Export</button>
    <button nz-button (click)="st.export(true)">Export Filtered Data</button>
    <button nz-button (click)="st.export(data, { filename: 'via-data.xlsx', sheetname: 'user' })">Export via data</button>
    <st #st [data]="data" [columns]="columns" class="mt-sm"></st>
  `,
})
export class ComponentsStExportComponent {
  @ViewChild('st', { static: false }) st!: STComponent;
  data: STData[] = Array(10000)
    .fill({})
    .map((_, index) => ({
      id: index + 1,
      picture: {
        thumbnail: `https://dummyimage.com/100x100&text=${Math.min(index + 1, 30)}`,
      },
      email: `e${index + 1}@qq.com`,
      phone: `phone - ${index + 1}`,
      price: Math.ceil(Math.random() * 10000000) + 10000000,
      registered: new Date(),
    }));
  columns: STColumn[] = [
    { title: '编号', index: 'id' },
    {
      title: '头像',
      type: 'img',
      width: 60,
      index: 'picture.thumbnail',
      exported: false,
    },
    { title: '邮箱', index: 'email' },
    { title: '电话', index: 'phone' },
    {
      title: '数字',
      index: 'price',
      type: 'number',
      sort: {
        compare: (a, b) => a.price - b.price,
      },
    },
    { title: '货币', index: 'price', type: 'currency' },
    { title: '注册时间', type: 'date', index: 'registered' },
  ];
}
编号头像邮箱电话佣金注册时间
编号1头像邮箱aaa5@qq.com电话phone-93533佣金9,303,778注册时间2022-08-27 11:18
编号2头像邮箱aaa6@qq.com电话phone-99212佣金2,383,346注册时间2022-08-27 11:18
编号3头像邮箱aaa8@qq.com电话phone-15046佣金5,686,125注册时间2022-08-27 11:18
Resizable

Resize the table header base on nz-resizable.

  • Note: Don't forget to import the nz-resizable Less style (@import 'ng-zorro-antd/resizable/style/entry.less';) file in src/styles.

  • Multiple headers not supported

expand codeexpand code
import { Component } from '@angular/core';
import { STChange, STColumn } from '@delon/abc/st';

@Component({
  selector: 'components-st-resizable',
  template: `
    <st
      [data]="url"
      [columns]="columns"
      [widthMode]="{ type: 'strict' }"
      resizable
      (change)="onChange($event)"
    ></st>
  `,
})
export class ComponentsStResizableComponent {
  url = `/users?total=2&field=list`;
  columns: STColumn[] = [
    { title: '编号', index: 'id', width: 80, resizable: false },
    { title: '头像', type: 'img', width: 60, index: 'picture.thumbnail' },
    { title: '邮箱', index: 'email', width: 150, resizable: { minWidth: 150 } },
    { title: '电话', index: 'phone' },
    { title: '佣金', index: 'price', type: 'currency' },
    { title: '注册时间', type: 'date', index: 'registered' },
  ];

  onChange({ type, resize }: STChange): void {
    if (type === 'resize') {
      console.log(resize?.width);
    }
  }
}

API

st

PropertyDescriptionTypeDefaultGlobal Config
[columns]Columns descriptionSTColumn[]--
[data]Data sourcestring, STData[], Observable<STData[]>--
[req]Http request configurationSTReq-
[res]Http response configurationSTRes-
[pi]Page indexnumber1
[ps]Page size, default is 10number10
[total]Total data count, should set when nzServerRender is true, default is 0number0-
[page]Pager configurationSTPage-
[noResult]Custom no result contentstring,TemplateRef<void>-
[bordered]Whether to show all table bordersbooleanfalse
[size]Size of table'small','middle','default''default'
[widthMode]Set the table width modeSTWidthMode-
[rowClassName]Row class name of table(record: STData, index: number) => string-
[clickRowClassName]Row class name of click the rowstring, STClickRowClassNameType-
[loading]Loading status of table, when specifying null is controlled by stboolean | nullnull-
[loadingIndicator]The spinning indicatorTemplateRef<void>-
[loadingDelay]Specifies a delay in milliseconds for loading state (prevent flush)number0
[scroll]Whether table can be scrolled in x/y direction, x or y can be a string that indicates the width and height of table body{ y?: string; x?: string }--
[virtualScroll]Enable virtual scroll mode,work with [nzScroll]booleanfalse
[virtualItemSize]The size of the items in the list, same as cdk itemSizenumber54
[virtualMaxBufferPx]The number of pixels worth of buffer to render for when rendering new items, same as cdk maxBufferPxnumber200
[virtualMinBufferPx]The minimum amount of buffer rendered beyond the viewport (in pixels),same as cdk minBufferPxnumber100
[virtualForTrackBy]The TrackByFunction to use for tracking changes.TrackByFunction<T>-
[singleSort]Single sort config
If not specified, return: columnName=ascend|descend
If specified, return: sort=columnName.(ascend|descend)
STSingleSortnull
[multiSort]Whether to mulit-sort, recommended use in URL data sourceboolean, STMultiSortfalse
[header]Table header rendererstring,TemplateRef<void>--
[showHeader]Whether show the head of the columns of the tablebooleantrue-
[footer]Table footer rendererstring,TemplateRef<void>--
[bodyHeader]Table extra body renderer in header, generally used to add total rowsTemplateRef<STStatisticalResults>--
[body]Table extra body renderer, generally used to add total rowsTemplateRef<STStatisticalResults>--
[widthConfig]Set col width can not used with width of STColumnstring[]--
[expandRowByClick]Whether to expand row by clicking anywhere in the whole rowbooleanfalse
[expandAccordion]Accordion modebooleanfalse
[expand]Whether current column include expand iconTemplateRef<void>--
[responsive]Whether to turn on responsivebooleantrue
[responsiveHideHeaderFooter]Whether to display the header and footer under the small screenbooleanfalse
[resizable]Resize header of the current table, Multiple headers not supportedSTResizable, boolean--
(change)EventsEventEmitter<STChange>--
(error)Error eventEventEmitter<STError>--

Properties & Methods

NameDescription
[filteredData]Get all data after filtering & sorting
- Local data: including sorting, filtering
- Remote data: Don't pass pi, ps parameters in http request
[count]Get the number of the current page
[list]Get the data of the current page
resetColumns(options?: STResetColumnsOption)Reset columns
load(pi = 1, extraParams?: any, options?: STLoadOptions)Load specified page
reload(extraParams?: any, options?: STLoadOptions)Refresh current page
reset(extraParams?: any, options?: STLoadOptions)Reset data and pi to 1, including single multi-select, sort, filter status (Covered default state)
addRow(data: STData | STData[], options?: { index?: number })Add a rows in the table
removeRow(data: STData | STData[] | number)Remove a row in the table
setRow(index: number | STData, item: STData, options?: { refreshSchema?: boolean; emitReload?: boolean })Sets the row value for the index in the table
pureItem(itemOrIndex: STData | number)Return pure data, st internally maintains a set of data for caching, this part of data may affect the backend
clear(cleanStatus = true)Clear all data
clearStatus()Clean all status (like this: single multi-select, sort, filter status)
clearCheck()Clear all checkbox
clearRadio()Clear all radio
export(newData?: STData[] | true, opt?: STExportOptions)Export Excel and make sure you have imported XlsxModule

Some details:

  • extraParams Keep original values when is null

  • STLoadOptions.merge merge mode, if true merges with new values instead of replacing

  • STLoadOptions.toTop Whether to jump to the top, if not specified, it's determined by page.toTop

Usage

@Component({
  template: `
    <st #st></st>
    <button (click)="st.load()">Load</button>
    <button (click)="st.reset()">Reset</button>
  `
})
class TestComponent {
  @ViewChild('st', { static: false }) comp: STComponent;
  // this.comp.load();
}

STReq

PropertyDescriptionTypeDefaultGlobal Config
[type]Pagination type, page used pi, ps; skip used skip, limitpage,skippage
[params]Request parameters, default to auto append pi, ps to URLany--
[ignoreParamNull]Whether to ignore null or unfind values in parametersBooleanfalse
[method]Request method'POST','GET','HEAD','PUT','PATCH','DELETE''GET'
[body]Request body (only method is POST)any--
[headers]Request headerany-
[reName]Map name pipsSTReqReNameType, ((result: any, options: { pi: number; ps: number; total: number }) => { total: number; list: T[] }){ pi: 'pi', ps: 'ps', skip: 'skip', limit: 'limit' }
[allInBody]Whether to request all parameter data into body (except url itself parameter)booleanfalse
[lazyLoad]Whether to delay loading data in first render st componentbooleanfalse
[process]Pre-request data processing(requestOptions: STRequestOptions) => STRequestOptions-

STRes

PropertyDescriptionTypeDefaultGlobal Config
[reName]Map name totallist, could be set like a.b.c{total:string;list:string}-
[process]Data preprocessing(data: STData[], rawData?: any) => STData[]-

STPage

PropertyDescriptionTypeDefaultGlobal Config
[front]Front paging when data is any[] or Observable<any[]>booleantrue
[zeroIndexed]Whether the backend paging uses the 0 base index (only data is url)booleanfalse
[position]Specify the position of Paginationtop,bottom,bothbottom
[placement]Specify the direction of Paginationleft,center,rightright
[show]Whether to show pagerbooleantrue
[showSize]Determine whether ps can be changedbooleanfalse
[pageSizes]Specify the sizeChanger optionsnumber[][10, 20, 30, 40, 50]
[showQuickJumper]Determine whether you can jump to pages directlybooleanfalse
[total]To display the total number and range, support custom string template (Three variable names: total for total data, range[0] and range[1] for current data range; Variable name must be double curly braces wrapper)boolean, stringfalse
[toTop]To top when pager changedbooleantrue
[toTopOffset]To top offset valuenumber100
[itemRender]To customize Pagination item, same as PaginationTemplateRef<{ $implicit: 'page' \| 'prev' \| 'next', page: number }>-
[simple]Whether to use simple modeboolean-

STError

PropertyDescriptionTypeDefault
[type]Error typereq-
[error]Error messageany-

STChange

PropertyDescriptionTypeDefault
[type]Change typeSTChangeType-
[pi]Page indexnumber-
[ps]Page sizenumber-
[total]Total datanumber-
[loaded]Parameters of type loadedSTData[]-
[checkbox]Parameters of type checkboxSTData[]-
[radio]Parameters of type radioSTData-
[sort]Parameters of type sortSTChangeSort-
[filter]Parameters of type filterSTColumn-
[click]Parameters of type clickSTChangeRowClick-
[dblClick]Parameters of type dblClickSTChangeRowClick-
[expand]Parameters of type expandSTData-

STChangeSort

PropertyDescriptionTypeDefault
[value]Current column sort statusascend,descend-
[map]All column sorting states{ [key: string]: string }-
[column]Column descriptionSTColumn-

STChangeRowClick

PropertyDescriptionTypeDefault
[e]Current rows eventEvent-
[item]Current rows dataSTData-
[index]Current rows indexnumber-

STExportOptions

PropertyDescriptionTypeDefault
[sheetname]Sheet namestringSheet1
[filename]Save file namestringexport.xslx
[callback]Callback before saving(wb: WorkBook) => void-

STSingleSort

PropertyDescriptionTypeDefaultGlobal Config
[key]Request parameter namestringsort
[nameSeparator]Column name and state separatorstring.

STMultiSort

PropertyDescriptionTypeDefaultGlobal Config
[key]Request parameter namestringsort
[separator]Separator between attributesstring-
[nameSeparator]Column name and state separatorstring.
[arrayParam]Whether to pass parameters as an array
true Indicates the use of url?sort=name.asc&sort=age.desc
false Indicates the use of url?sort=name.asc-age.desc
booleanfalse
[keepEmptyKey]Whether to keep send empty key
true send the key name anyway
false don't send key when not sorting
booleantrue
[global]Only global config, Whether global multi sort mode
true all st defaults multi-sort
false all st non-multiple sorting, just only configurable for rule
booleantrue

STData

PropertyDescriptionTypeDefault
[checked]Select or radio button checked status valueboolean-
[disabled]Select or radio button disabled status valueboolean-
[expand]Whether to expand the status valueboolean-
[showExpand]Whether show expand iconboolean-
[className]Class name of the rowstring-

STColumn

PropertyDescriptionTypeDefault
[title]Name of this columnstring, STColumnTitle-
[i18n]I18n key of this columnstring-
[type]no Rows number
checkbox selection
radio selection
link Link that triggers click
img Align to the center
number Align to the right
currency Align to the right
date Align to the center
badge Nz-Badge
tag Nz-Tag
yn Make boolean as badge
widget Custom widgets to render columns
string-
[index]Display field of the data record, could be set like a.b.cstring, string[]-
[render]Custom render template IDstring, TemplateRef, TemplateRef<{ $implicit: STData; index: number }>-
[renderTitle]Title custom render template IDstring, TemplateRef<void>, TemplateRef<{ $implicit: STColumn; index: number }>-
[default]Replace with default value when no data exists (value typeof is undefined)string-
[buttons]Buttons of this columnSTColumnButton[]-
[maxMultipleButton]Max button option can be showed, and the extra part are auto generated under moreSTColumnMaxMultipleButton, number-
[width]Width of this column (NOTICE: If the fixed column must be a number), e.g: 100, 10%, 100pxstring,number-
[fixed]Set column to be fixed, must specify widthleft,right-
[format]Format value of this column(item: STData, col: STColumn, index: number) => string-
[className]Class name of this column, e.g: text-center, text-right, text-error, pls refer to Style Toolsstring-
[colSpan]Span of this column's titlenumber-
[sort]Sort config of this column, Remote Data ConfigurationPriority Rule:
true allow sorting, should be auto generate compose compare: (a, b) => a[index] - b[index] method when data is local
string corresponding key value
true,string,STColumnSort-
[filter]Filter config of this columnSTColumnFilter-
[selections]Config of type is checkboxSTColumnSelection[]-
[numberDigits]Config of type is numberstring-
[dateFormat]Config of type is dateyyyy-MM-dd HH:mm-
[currency]Currency format option, type=currency is validSTColumnCurrency-
[yn]Config of type is ynSTColumnYn-
[exported]Whether to allow exportbooleantrue
[acl]ACL permission (Use can() verify)ACLCanType-
[click]Callback of type is link(record: STData, instance?: STComponent) => void-
[badge]Config of type is badgeSTColumnBadge-
[tag]Config of type is tagSTColumnTag-
[enum]Config of type is enum{ [key: string]: string; [key: number]: string }-
[widget]Config of type is widgetSTWidgetColumn-
[noIndex]Line number index start valuenumber,(item: STData, col: STColumn, idx: number) => number1
[iif]Custom conditional expression
1. Execute only once when columns is assigned
2. Call resetColumns() to trigger again
(item: STColumn) => boolean-
[statistical]StatisticsSTStatisticalType,STStatistical-
[resizable]Resize header, Multiple headers not supportedSTResizable, boolean--
[children]Group columnsSTColumn[]-
[safeType]Safe rendering type, Support global configtext,html,safeHtmlsafeHtml
[customRequest]Override the default request behavior, you can customize your own request implementation, for example: Graphql, Support global config(options: STCustomRequestOptions) => Observable<any>-

STColumnTitle

PropertyDescriptionTypeDefault
[text]Text of header, can be choose one of text or i18nstring-
[i18n]I18n key of header, can be choose one of text or i18nstring-
[optional]Optional information of headerstring-
[optionalHelp]Optional help of headerstring-

STColumnSort

PropertyDescriptionTypeDefault
[default]Default order of sorted valuesascend,descend-
[compare]Sort function for local sort, see Array.sort's compareFunction, null ingore local sort but keeping sort function.(a: STData, b: STData) => number, null-
[key]Unique key of this column, default is index property value
multiSort: false => key: 'name' => ?name=1&pi=1
multiSort: true allow multiple sort keys, or use STMultiSort to specify multi-column sort key merge rule
string-
[reName]Map name
{ ascend: '0', descend: '1' } => ?name=1&pi=1
{ ascend: 'asc', descend: 'desc' } => ?name=desc&pi=1
{ ascend?: string, descend?: string }-

STColumnFilter

PropertyDescriptionTypeDefault
[type]Type of the filter, keyword render by inputdefault,keyword,number,date,customdefault
[menus]Filter menu configSTColumnFilterMenu[]-
[fn]Filter function for local data(filter: STColumnFilterMenu, record: STData) => boolean-
[default]Whether the data is filteredboolean-
[icon]Customized filter icon
When type='default' default filter
when type='keyword' default search
string | STIconfilter
[multiple]Whether multiple filters can be selectedbooleantrue
[confirmText]Text of the confirm buttonstring-
[clearText]Text of the clear buttonstring-
[key]Unique key of this column, default is index property valuestring-
[reName]Map name(list: STColumnFilterMenu[], col: STColumn) => Object-
[custom]Custom templateTemplateRef<{ $implicit: STColumnFilter; col: STColumn }>-
[showOPArea]Whether to display the operation areabooleantrue
[placeholder]placeholderbooleantrue
[number]Option for the type is numberObject-
[date]Option for the type is dateObject-

STColumnFilterMenu

PropertyDescriptionTypeDefault
[text]Filter text
When type: 'keyword' is placeholder value
string-
[value]Filter valueany-
[checked]Whether checkedboolean-
[acl]ACL permission (Use can() verify)ACLCanType-

STIcon

PropertyDescriptionTypeDefaultGlobal Config
[type]Type of the ant design iconstring--
[theme]Type of the ant design iconoutline | twotone | filloutline
[spin]Rotate icon with animationbooleanfalse
[twoToneColor]Only support the two-tone icon. Specific the primary color.string-v
[iconfont]Type of the icon from iconfontstring-

STColumnButton

PropertyDescriptionTypeDefault
[text]Text of button, coexist with iconstring | (record: STData, btn: STColumnButton) => string-
[icon]Icon of button, coexist with textstring | STIcon-
[i18n]I18n key of buttonstring-
[type]Type of buttonnone,del,modal,static,drawer,link-
[click]Click callback;
function when type=modal will only fire when confirmed
reload Refresh current page
load load 1 page
(record: STData, modal?: any, instance?: STComponent) => void | reload-
[pop]Whether to pop confirmboolean, string, STColumnButtonPopfalse
[modal]Config of type is modal or staticSTColumnButtonModal-
[drawer]Config of type is drawerSTColumnButtonDrawer-
[children]Drop-down menu, only supports level 1STColumnButton[]-
[acl]ACL permission (Use can() verify)ACLCanType-
[iif]Custom conditional expression(item: STData, btn: STColumnButton, column: STColumn) => boolean() => true
[iifBehavior]Render button mode when the conditional expression false valuehide,disabledhide
[tooltip]Button popup tipstring-
[className]Class name of this button, e.g: text-error, pls refer to Style Toolsstring-

STColumnButtonModal

PropertyDescriptionTypeDefaultGlobal Config
[component]Modal component classany--
[params]Dialog parameter(record: STData) => Object--
[paramsName]Receive parameter name of the target component, If target component receive value is null, pls check global-config.module.ts Global settingsstringrecord
[size]Size of modal, support number type'sm','md','lg','xl''lg'
[exact]Exact match return value, default is true, If the return value is not null (null or undefined) is considered successful, otherwise it is considered error.booleantrue
[includeTabs]Whether to wrap the nz-tabset, fix content spacing problemboolean--
[modalOptions]nz-modal raw parameters ModalOptionsany-

STColumnButtonDrawer

PropertyDescriptionTypeDefaultGlobal Config
[title]Title of drawerstring--
[component]Drawer component classany--
[params]Dialog parameter(record: STData) => Object--
[paramsName]Receive parameter name of the target component, If target component receive value is null, pls check global-config.module.ts Global settingsstringrecord
[size]Size of drawer, support number type'sm','md','lg','xl''md'
[drawerOptions]nz-drawer raw parameters NzDrawerOptionsany-
[footer]Whether to include the bottom toolbarbooleantrue
[footerHeight]Height of bottom toolbarnumber55

STColumnSelection

PropertyDescriptionTypeDefault
[text]Selection textstring-
[select]Select callback event(data: STData[]) => void-
[acl]ACL permission (Use can() verify)ACLCanType-

STColumnYn

PropertyDescriptionTypeDefault
[truth]Truth condition valueanytrue
[yes]Badge true textstring
[no]Badge false textstring
[mode]Display mode for ynfull,icon,texticon

STcolumnCurrency

PropertyDescriptionTypeDefault
[type]Currency rendering typecommas, megacommas
[format]See CurrencyService.formatCurrencyFormatOptions-

STColumnBadge

PropertyDescriptionTypeDefault
[text]Badge textstring-
[color]Badge color valuesuccess,processing,default,error,warning-

STColumnTag

PropertyDescriptionTypeDefault
[text]Tag textstring-
[color]Tag color valuestring-

STWidgetColumn

PropertyDescriptionTypeDefault
[type]Specify the type name, which can be customized by STWidgetRegistry, for examplestring-
[params]Parameters of the target component(options: { record: STData; column: STColumn }) => {}-

STWidthMode

PropertyDescriptionTypeDefaultGlobal Config
[type]Type of width modestrict,defaultdefault
[strictBehavior]Behavior type of strictwrap,truncatetruncate

STStatistical

PropertyDescriptionTypeDefault
[type]Statistic type of current columnSTStatisticalType | STStatisticalFn-
[digits]The number of digits to appear after the decimal pointnumber2
[currency]Whether formatting currency, default to true when type is STStatisticalFn,sum,average,max,minboolean-

STStatisticalFn

(
  values: number[],
  col: STColumn,
  list: STData[],
  rawData?: any,
) => STStatisticalResult

STResizable

PropertyDescriptionTypeDefault
[disabled]Disable resizebooleantrue
[bounds]Specifies resize boundarieswindow, parent, ElementRef<HTMLElement>window
[maxWidth]Maximum width of resizable elemennumber360
[minWidth]Minimum width of resizable elementnumber60
[preview]Enable preview when resizingbooleantrue

Theme

PropertyDescriptionDefault
@nz-table-img-radiusRadius size for the image in td4px
@nz-table-img-margin-rightMargin right for the image in td4px
@nz-table-img-max-heightMax height for the image in td32px
@nz-table-img-max-widthMax width for the image in td32px
@nz-table-even-backgroundEven background for the rownone
@nz-table-rep-max-widthTrigger when the viewable area is less than
@nz-table-rep-min-widthTrigger when the visible area is greater than
@nz-table-rep-header-backgroundHeader background in responsive@border-color-split
@nz-table-rep-even-backgroundEvent background in responsive#f9f9f9
@nz-table-rep-column-name-colorName color in responsivergba(0, 0, 0, 0.5)
@nz-table-rep-column-name-text-alignName text align in responsiveright
@nz-table-rep-column-name-widthName column width in responsive100px
@nz-table-rep-column-name-padding-rightRight padding of title and content in responsive8px
@table-row-hover-bgHover background color of the row#fafafa
@st-btn-disabled-colorText color of the buttonrgba(0, 0, 0, 0.25)
@st-title-optional-colorOptional color of titlergba(0, 0, 0, 0.35)
@st-resizable-handle-widthWidth of the rasizable handle1px
@st-resizable-handle-heightHeight of the rasizable handle60%
@st-resizable-handle-colorColor of the rasizable handle@border-color-base