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头像邮箱aaa2@qq.com电话phone-10163佣金(单位:元)7,535,188注册时间2022-06-06 06:37
编号2头像邮箱aaa4@qq.com电话phone-28362佣金(单位:元)673,377注册时间2022-06-06 06:37
编号3头像邮箱aaa1@qq.com电话phone-11203佣金(单位:元)4,023,791注册时间2022-06-06 06:37
  • 1
  • 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年龄23状态WarningDate2022-06-06 06:37
    编号姓名name 2年龄29状态DefaultDate2022-06-06 06:37
    编号姓名name 3年龄25状态DefaultDate2022-06-06 06:37
  • 1
  • 2
  • 3
  • 4
  • 5
  • •••
  • 34
  • 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);
      }
    }
  • 1 - 3 of 10
  • 1
  • 2
  • 3
  • 4
  • 行号姓名年龄HTMLTexttagbadgeEnumyn
    行号1姓名name 1年龄26HTML1 OtherText<strong>1</strong> Othertag错误badge错误Enumyn
    行号2姓名name 2年龄34HTML2 OtherText<strong>2</strong> Othertag错误badge进行中Enumyn
    行号3姓名name 3年龄33HTML3 OtherText<strong>3</strong> Othertag成功badge警告Enumyn
  • 1 - 3 of 10
  • 1
  • 2
  • 3
  • 4
  • 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();
      }
    }
    头像邮箱电话注册时间
    编号头像邮箱aaa2@qq.com电话phone-87654注册时间2022-06-06 06:37
    编号头像邮箱aaa4@qq.com电话phone-39148注册时间2022-06-06 06:37
    编号头像邮箱aaa8@qq.com电话phone-41024注册时间2022-06-06 06:37
  • 1
  • 2
  • 3
  • 4
  • 5
  • •••
  • 34
  • 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;
        });
      }
    }
    编号头像邮箱电话注册时间
    编号头像邮箱aaa1@qq.com电话phone-91920注册时间2022-06-06 06:37
    编号头像邮箱aaa3@qq.com电话phone-40488注册时间2022-06-06 06:37
    编号头像邮箱aaa2@qq.com电话phone-76439注册时间2022-06-06 06:37
  • 1
  • 2
  • 3
  • 4
  • 5
  • •••
  • 100
  • 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-77234注册时间2022-06-06 06:37
    编号2邮箱aaa2@qq.com电话phone-31521注册时间2022-06-06 06:37
    编号3邮箱aaa1@qq.com电话phone-31350注册时间2022-06-06 06:37
  • 1
  • 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年龄22启用YOPEdit
    编号2姓名name 2年龄26启用NOPEdit
    编号3姓名name 3年龄26启用YOPEdit
  • 1
  • 2
  • 3
  • 4
  • 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头像邮箱aaa9@qq.com电话phone-87363注册时间2022-06-06 06:37
    编号2头像邮箱aaa3@qq.com电话phone-79129注册时间2022-06-06 06:37
    编号3头像邮箱aaa8@qq.com电话phone-6963注册时间2022-06-06 06:37
  • 1
  • 2
  • 3
  • 4
  • 5
  • •••
  • 34
  • 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邮箱aaa9@qq.com电话phone-70340
    编号2邮箱aaa7@qq.com电话phone-3653
    编号3邮箱aaa5@qq.com电话phone-83395
  • 1
  • 2
  • 3
  • 4
  • 5
  • •••
  • 34
  • 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-10 first-18国家CH性别male注册时间2022-06-06 06:37
    编号2头像姓名2: last-8 first-13国家US性别female注册时间2022-06-06 06:37
    编号3头像姓名3: last-8 first-18国家DE性别male注册时间2022-06-06 06:37
  • 1
  • 2
  • 3
  • 4
  • 5
  • •••
  • 67
  • 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年龄21Button
    编号2姓名name 2年龄21Button
    编号3姓名name 3年龄28Button
  • 1
  • 2
  • 3
  • 4
  • 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年龄29自定义tooltip: 29-0
    编号2姓名name 2年龄25自定义tooltip: 25-1
    编号3姓名name 3年龄23自定义tooltip: 23-2
  • 1
  • 2
  • 3
  • 4
  • 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年龄25操作区EditDrawer更多
    序号2编号2姓名name 2年龄29操作区EditDrawer更多
    序号3编号3姓名name 3年龄21操作区EditDrawer更多
  • 1
  • 2
  • 3
  • 4
  • 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自定义头像邮箱aaa8@qq.com
    编号2自定义头像邮箱aaa7@qq.com
    编号3自定义头像邮箱aaa6@qq.com
  • 1
  • 2
  • 3
  • 4
  • 5
  • •••
  • 34
  • 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年龄1229
    编号13编号23编号33编号43编号53编号63编号73编号83编号83编号83编号83编号83姓名10name 3姓名11name 3年龄1226
  • 1
  • 2
  • 3
  • 4
  • 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头像邮箱aaa8@qq.comfirstfirst-10lastlast-9
    编号2头像邮箱aaa8@qq.comfirstfirst-11lastlast-7
    编号3头像邮箱aaa6@qq.comfirstfirst-17lastlast-3
  • 1
  • 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头像邮箱aaa6@qq.com电话phone-2149注册时间2022-06-06 06:37
    编号2头像邮箱aaa7@qq.com电话phone-69717注册时间2022-06-06 06:37
    编号3头像邮箱aaa10@qq.com电话phone-32320注册时间2022-06-06 06:37
    The footer
  • 1
  • 2
  • 3
  • 4
  • 5
  • •••
  • 34
  • 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性别Sum18Average18Min18Max18Custom18
    行号2编号2性别Sum92Average92Min92Max92Custom92
    行号3编号3性别Sum69Average69Min69Max69Custom69
    合计3 个217959.67189218
    性别平均值59.67
  • 1
  • 2
  • 3
  • 4
  • 5
  • •••
  • 34
  • 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数字12,393,271货币12,393,271注册时间2022-06-06 06:37
    编号2头像邮箱e2@qq.com电话phone - 2数字19,682,683货币19,682,683注册时间2022-06-06 06:37
    编号3头像邮箱e3@qq.com电话phone - 3数字16,688,978货币16,688,978注册时间2022-06-06 06:37
  • 1
  • 2
  • 3
  • 4
  • 5
  • •••
  • 3334
  • 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头像邮箱aaa8@qq.com电话phone-24485佣金4,297,378注册时间2022-06-06 06:37
    编号2头像邮箱aaa10@qq.com电话phone-2255佣金8,109,793注册时间2022-06-06 06:37
    编号3头像邮箱aaa10@qq.com电话phone-25442佣金4,412,946注册时间2022-06-06 06:37
  • 1
  • 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--
    [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{ 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