Table表格

展示行列数据。

何时使用

  • 当有大量结构化的数据需要展现时;
  • 当需要对数据进行排序、搜索、分页、自定义操作等复杂行为时。

如何使用

Table 组件同时具备了易用性和高度可定制性

高度定制

nz-table 组件中完整的暴露了 W3C标准 <table> 的所有组成部分,你可以像使用 table 元素一样使用 nz-table ,根据依据业务需求,使用者可以自由的控制任何一个部分的样式、内容、逻辑和事件绑定。

组件增强

nz-table, thead, th, td 等多个暴露的元素上,组件提供了增强语法,经过配置之后可以很方便的实现多选、过滤、排序、固定列、固定表头、服务端分页等功能。

数据处理

传入[nzData]中的数据,经过处理之后,可以通过 模板变量 获取当前展示表格部分的数据,再使用 *ngFor 依据需求将数据渲染。

  1. <nz-table #basicTable [nzData]="dataSet">
  2. <thead>
  3. <tr>
  4. <th>Name</th>
  5. <th>Age</th>
  6. <th>Address</th>
  7. <th>Action</th>
  8. </tr>
  9. </thead>
  10. <tbody>
  11. <tr *ngFor="let data of basicTable.data">
  12. <td>{{data.name}}</td>
  13. <td>{{data.age}}</td>
  14. <td>{{data.address}}</td>
  15. <td>
  16. <a>Action 一 {{data.name}}</a>
  17. <nz-divider nzType="vertical"></nz-divider>
  18. <a>Delete</a>
  19. </td>
  20. </tr>
  21. </tbody>
  22. </nz-table>

代码演示

Table表格 - 图1

基本用法

简单的表格,最后一列是各种操作。

  1. import { Component } from '@angular/core';
  2. @Component({
  3. selector: 'nz-demo-table-basic',
  4. template: `
  5. <nz-table #basicTable [nzData]="listOfData">
  6. <thead>
  7. <tr>
  8. <th>Name</th>
  9. <th>Age</th>
  10. <th>Address</th>
  11. <th>Action</th>
  12. </tr>
  13. </thead>
  14. <tbody>
  15. <tr *ngFor="let data of basicTable.data">
  16. <td>{{ data.name }}</td>
  17. <td>{{ data.age }}</td>
  18. <td>{{ data.address }}</td>
  19. <td>
  20. <a>Action 一 {{ data.name }}</a>
  21. <nz-divider nzType="vertical"></nz-divider>
  22. <a>Delete</a>
  23. </td>
  24. </tr>
  25. </tbody>
  26. </nz-table>
  27. `
  28. })
  29. export class NzDemoTableBasicComponent {
  30. listOfData = [
  31. {
  32. key: '1',
  33. name: 'John Brown',
  34. age: 32,
  35. address: 'New York No. 1 Lake Park'
  36. },
  37. {
  38. key: '2',
  39. name: 'Jim Green',
  40. age: 42,
  41. address: 'London No. 1 Lake Park'
  42. },
  43. {
  44. key: '3',
  45. name: 'Joe Black',
  46. age: 32,
  47. address: 'Sidney No. 1 Lake Park'
  48. }
  49. ];
  50. }

Table表格 - 图2

选择和操作

第一列是联动的选择框,增加 nzShowCheckbox 后,th 获得和 nz-checkbox 一样的功能,选择后进行操作,完成后清空选择,请注意:数据逻辑需要自行控制。

  1. import { Component, OnInit } from '@angular/core';
  2. export interface Data {
  3. id: number;
  4. name: string;
  5. age: number;
  6. address: string;
  7. disabled: boolean;
  8. }
  9. @Component({
  10. selector: 'nz-demo-table-row-selection-and-operation',
  11. template: `
  12. <div class="operate">
  13. <button
  14. nz-button
  15. [disabled]="numberOfChecked === 0"
  16. [nzType]="'primary'"
  17. [nzLoading]="isOperating"
  18. (click)="operateData()"
  19. >
  20. Reload
  21. </button>
  22. <span *ngIf="numberOfChecked">Selected {{ numberOfChecked }} items</span>
  23. </div>
  24. <nz-table
  25. #rowSelectionTable
  26. nzShowPagination
  27. nzShowSizeChanger
  28. [nzData]="listOfAllData"
  29. (nzCurrentPageDataChange)="currentPageDataChange($event)"
  30. >
  31. <thead>
  32. <tr>
  33. <th
  34. nzShowCheckbox
  35. [(nzChecked)]="isAllDisplayDataChecked"
  36. [nzIndeterminate]="isIndeterminate"
  37. (nzCheckedChange)="checkAll($event)"
  38. ></th>
  39. <th>Name</th>
  40. <th>Age</th>
  41. <th>Address</th>
  42. </tr>
  43. </thead>
  44. <tbody>
  45. <tr *ngFor="let data of rowSelectionTable.data">
  46. <td
  47. nzShowCheckbox
  48. [(nzChecked)]="mapOfCheckedId[data.id]"
  49. [nzDisabled]="data.disabled"
  50. (nzCheckedChange)="refreshStatus()"
  51. ></td>
  52. <td>{{ data.name }}</td>
  53. <td>{{ data.age }}</td>
  54. <td>{{ data.address }}</td>
  55. </tr>
  56. </tbody>
  57. </nz-table>
  58. `,
  59. styles: [
  60. `
  61. .operate {
  62. margin-bottom: 16px;
  63. }
  64. .operate span {
  65. margin-left: 8px;
  66. }
  67. `
  68. ]
  69. })
  70. export class NzDemoTableRowSelectionAndOperationComponent implements OnInit {
  71. isAllDisplayDataChecked = false;
  72. isOperating = false;
  73. isIndeterminate = false;
  74. listOfDisplayData: Data[] = [];
  75. listOfAllData: Data[] = [];
  76. mapOfCheckedId: { [key: string]: boolean } = {};
  77. numberOfChecked = 0;
  78. currentPageDataChange($event: Data[]): void {
  79. this.listOfDisplayData = $event;
  80. this.refreshStatus();
  81. }
  82. refreshStatus(): void {
  83. this.isAllDisplayDataChecked = this.listOfDisplayData
  84. .filter(item => !item.disabled)
  85. .every(item => this.mapOfCheckedId[item.id]);
  86. this.isIndeterminate =
  87. this.listOfDisplayData.filter(item => !item.disabled).some(item => this.mapOfCheckedId[item.id]) &&
  88. !this.isAllDisplayDataChecked;
  89. this.numberOfChecked = this.listOfAllData.filter(item => this.mapOfCheckedId[item.id]).length;
  90. }
  91. checkAll(value: boolean): void {
  92. this.listOfDisplayData.filter(item => !item.disabled).forEach(item => (this.mapOfCheckedId[item.id] = value));
  93. this.refreshStatus();
  94. }
  95. operateData(): void {
  96. this.isOperating = true;
  97. setTimeout(() => {
  98. this.listOfAllData.forEach(item => (this.mapOfCheckedId[item.id] = false));
  99. this.refreshStatus();
  100. this.isOperating = false;
  101. }, 1000);
  102. }
  103. ngOnInit(): void {
  104. for (let i = 0; i < 100; i++) {
  105. this.listOfAllData.push({
  106. id: i,
  107. name: `Edward King ${i}`,
  108. age: 32,
  109. address: `London, Park Lane no. ${i}`,
  110. disabled: i % 2 === 0
  111. });
  112. }
  113. }
  114. }

Table表格 - 图3

自定义选择项

通过 nzShowRowSelectionnzSelections 自定义选择项.

  1. import { Component, OnInit } from '@angular/core';
  2. @Component({
  3. selector: 'nz-demo-table-row-selection-custom',
  4. template: `
  5. <nz-table
  6. #rowSelectionTable
  7. nzShowSizeChanger
  8. [nzData]="listOfAllData"
  9. (nzCurrentPageDataChange)="currentPageDataChange($event)"
  10. >
  11. <thead>
  12. <tr>
  13. <th
  14. nzShowCheckbox
  15. nzShowRowSelection
  16. [nzSelections]="listOfSelection"
  17. [(nzChecked)]="isAllDisplayDataChecked"
  18. [nzIndeterminate]="isIndeterminate"
  19. (nzCheckedChange)="checkAll($event)"
  20. ></th>
  21. <th>Name</th>
  22. <th>Age</th>
  23. <th>Address</th>
  24. </tr>
  25. </thead>
  26. <tbody>
  27. <tr *ngFor="let data of rowSelectionTable.data">
  28. <td nzShowCheckbox [(nzChecked)]="mapOfCheckedId[data.id]" (nzCheckedChange)="refreshStatus()"></td>
  29. <td>{{ data.name }}</td>
  30. <td>{{ data.age }}</td>
  31. <td>{{ data.address }}</td>
  32. </tr>
  33. </tbody>
  34. </nz-table>
  35. `
  36. })
  37. export class NzDemoTableRowSelectionCustomComponent implements OnInit {
  38. listOfSelection = [
  39. {
  40. text: 'Select All Row',
  41. onSelect: () => {
  42. this.checkAll(true);
  43. }
  44. },
  45. {
  46. text: 'Select Odd Row',
  47. onSelect: () => {
  48. this.listOfDisplayData.forEach((data, index) => (this.mapOfCheckedId[data.id] = index % 2 !== 0));
  49. this.refreshStatus();
  50. }
  51. },
  52. {
  53. text: 'Select Even Row',
  54. onSelect: () => {
  55. this.listOfDisplayData.forEach((data, index) => (this.mapOfCheckedId[data.id] = index % 2 === 0));
  56. this.refreshStatus();
  57. }
  58. }
  59. ];
  60. isAllDisplayDataChecked = false;
  61. isIndeterminate = false;
  62. listOfDisplayData: any[] = [];
  63. listOfAllData: any[] = [];
  64. mapOfCheckedId: { [key: string]: boolean } = {};
  65. currentPageDataChange($event: Array<{ id: number; name: string; age: number; address: string }>): void {
  66. this.listOfDisplayData = $event;
  67. this.refreshStatus();
  68. }
  69. refreshStatus(): void {
  70. this.isAllDisplayDataChecked = this.listOfDisplayData.every(item => this.mapOfCheckedId[item.id]);
  71. this.isIndeterminate =
  72. this.listOfDisplayData.some(item => this.mapOfCheckedId[item.id]) && !this.isAllDisplayDataChecked;
  73. }
  74. checkAll(value: boolean): void {
  75. this.listOfDisplayData.forEach(item => (this.mapOfCheckedId[item.id] = value));
  76. this.refreshStatus();
  77. }
  78. ngOnInit(): void {
  79. for (let i = 0; i < 100; i++) {
  80. this.listOfAllData.push({
  81. id: i,
  82. name: `Edward King ${i}`,
  83. age: 32,
  84. address: `London, Park Lane no. ${i}`
  85. });
  86. }
  87. }
  88. }

Table表格 - 图4

筛选和排序

对某一列数据进行筛选,通过指定 thnzShowFilter 属性来展示筛选菜单, 使用 nzFilters 属性来指定筛选选项,nzFilterChange 用于获取当前选中的选项,nzFilterMultiple 用于指定多选和单选。

对某一列数据进行排序,通过指定 thnzShowSort 属性来展示排序按钮,使用 nzSortKey 来指定排序的 key,在 thead 上通过 nzSortChange 来获取排序改变事件,通过 nzSingleSort 来指定是否单列排序。

  1. import { Component } from '@angular/core';
  2. @Component({
  3. selector: 'nz-demo-table-head',
  4. template: `
  5. <nz-table #filterTable [nzData]="listOfDisplayData">
  6. <thead (nzSortChange)="sort($event)" nzSingleSort>
  7. <tr>
  8. <th
  9. nzShowSort
  10. nzSortKey="name"
  11. nzShowFilter
  12. [nzFilters]="listOfName"
  13. (nzFilterChange)="filter($event, searchAddress)"
  14. >
  15. Name
  16. </th>
  17. <th nzShowSort nzSortKey="age">Age</th>
  18. <th
  19. nzShowSort
  20. nzSortKey="address"
  21. nzShowFilter
  22. [nzFilterMultiple]="false"
  23. [nzFilters]="listOfAddress"
  24. (nzFilterChange)="filter(listOfSearchName, $event)"
  25. >
  26. Address
  27. </th>
  28. </tr>
  29. </thead>
  30. <tbody>
  31. <tr *ngFor="let data of filterTable.data">
  32. <td>{{ data.name }}</td>
  33. <td>{{ data.age }}</td>
  34. <td>{{ data.address }}</td>
  35. </tr>
  36. </tbody>
  37. </nz-table>
  38. `
  39. })
  40. export class NzDemoTableHeadComponent {
  41. sortName: string | null = null;
  42. sortValue: string | null = null;
  43. searchAddress: string;
  44. listOfName = [{ text: 'Joe', value: 'Joe' }, { text: 'Jim', value: 'Jim' }];
  45. listOfAddress = [{ text: 'London', value: 'London' }, { text: 'Sidney', value: 'Sidney' }];
  46. listOfSearchName: string[] = [];
  47. listOfData: Array<{ name: string; age: number; address: string; [key: string]: string | number }> = [
  48. {
  49. name: 'John Brown',
  50. age: 32,
  51. address: 'New York No. 1 Lake Park'
  52. },
  53. {
  54. name: 'Jim Green',
  55. age: 42,
  56. address: 'London No. 1 Lake Park'
  57. },
  58. {
  59. name: 'Joe Black',
  60. age: 32,
  61. address: 'Sidney No. 1 Lake Park'
  62. },
  63. {
  64. name: 'Jim Red',
  65. age: 32,
  66. address: 'London No. 2 Lake Park'
  67. }
  68. ];
  69. listOfDisplayData: Array<{ name: string; age: number; address: string; [key: string]: string | number }> = [
  70. ...this.listOfData
  71. ];
  72. sort(sort: { key: string; value: string }): void {
  73. this.sortName = sort.key;
  74. this.sortValue = sort.value;
  75. this.search();
  76. }
  77. filter(listOfSearchName: string[], searchAddress: string): void {
  78. this.listOfSearchName = listOfSearchName;
  79. this.searchAddress = searchAddress;
  80. this.search();
  81. }
  82. search(): void {
  83. /** filter data **/
  84. const filterFunc = (item: { name: string; age: number; address: string }) =>
  85. (this.searchAddress ? item.address.indexOf(this.searchAddress) !== -1 : true) &&
  86. (this.listOfSearchName.length ? this.listOfSearchName.some(name => item.name.indexOf(name) !== -1) : true);
  87. const data = this.listOfData.filter(item => filterFunc(item));
  88. /** sort data **/
  89. if (this.sortName && this.sortValue) {
  90. this.listOfDisplayData = data.sort((a, b) =>
  91. this.sortValue === 'ascend'
  92. ? a[this.sortName!] > b[this.sortName!]
  93. ? 1
  94. : -1
  95. : b[this.sortName!] > a[this.sortName!]
  96. ? 1
  97. : -1
  98. );
  99. } else {
  100. this.listOfDisplayData = data;
  101. }
  102. }
  103. }

Table表格 - 图5

默认筛选

通过设置 filter 对象的 { byDefault: true } 属性来默认启用一个筛选器。注意,你必须同时自行设置过滤后应当展示的列表项,为了保持数据流的清晰和数据的一致性,组件库不会为你做这项工作。详情请见 demo。

  1. import { Component } from '@angular/core';
  2. @Component({
  3. selector: 'nz-demo-table-default-filter',
  4. template: `
  5. <nz-table #filterTable [nzData]="listOfDisplayData">
  6. <thead (nzSortChange)="sort($event)" nzSingleSort>
  7. <tr>
  8. <th
  9. nzShowSort
  10. nzSortKey="name"
  11. nzShowFilter
  12. [nzFilters]="listOfName"
  13. (nzFilterChange)="filter($event, searchAddress)"
  14. >
  15. Name
  16. </th>
  17. <th nzShowSort nzSortKey="age">Age</th>
  18. <th
  19. nzShowSort
  20. nzSortKey="address"
  21. nzShowFilter
  22. [nzFilterMultiple]="false"
  23. [nzFilters]="listOfAddress"
  24. (nzFilterChange)="filter(listOfSearchName, $event)"
  25. >
  26. Address
  27. </th>
  28. </tr>
  29. </thead>
  30. <tbody>
  31. <tr *ngFor="let data of filterTable.data">
  32. <td>{{ data.name }}</td>
  33. <td>{{ data.age }}</td>
  34. <td>{{ data.address }}</td>
  35. </tr>
  36. </tbody>
  37. </nz-table>
  38. `
  39. })
  40. export class NzDemoTableDefaultFilterComponent {
  41. listOfName = [{ text: 'Joe', value: 'Joe', byDefault: true }, { text: 'Jim', value: 'Jim' }];
  42. listOfAddress = [{ text: 'London', value: 'London', byDefault: true }, { text: 'Sidney', value: 'Sidney' }];
  43. listOfSearchName = ['Joe']; // You need to change it as well!
  44. sortName: string | null = null;
  45. sortValue: string | null = null;
  46. searchAddress = 'London';
  47. listOfData: Array<{ name: string; age: number; address: string; [key: string]: string | number }> = [
  48. {
  49. name: 'John Brown',
  50. age: 32,
  51. address: 'New York No. 1 Lake Park'
  52. },
  53. {
  54. name: 'Jim Green',
  55. age: 42,
  56. address: 'London No. 1 Lake Park'
  57. },
  58. {
  59. name: 'Joe Black',
  60. age: 32,
  61. address: 'Sidney No. 1 Lake Park'
  62. },
  63. {
  64. name: 'Jim Red',
  65. age: 32,
  66. address: 'London No. 2 Lake Park'
  67. }
  68. ];
  69. // You need to change it as well!
  70. listOfDisplayData: Array<{ name: string; age: number; address: string; [key: string]: string | number }> = [];
  71. sort(sort: { key: string; value: string }): void {
  72. this.sortName = sort.key;
  73. this.sortValue = sort.value;
  74. this.search();
  75. }
  76. filter(listOfSearchName: string[], searchAddress: string): void {
  77. console.log(listOfSearchName, searchAddress);
  78. this.listOfSearchName = listOfSearchName;
  79. this.searchAddress = searchAddress;
  80. this.search();
  81. }
  82. search(): void {
  83. /** filter data **/
  84. const filterFunc = (item: { name: string; age: number; address: string }) =>
  85. (this.searchAddress ? item.address.indexOf(this.searchAddress) !== -1 : true) &&
  86. (this.listOfSearchName.length ? this.listOfSearchName.some(name => item.name.indexOf(name) !== -1) : true);
  87. const data = this.listOfData.filter(item => filterFunc(item));
  88. /** sort data **/
  89. if (this.sortName && this.sortValue) {
  90. this.listOfDisplayData = data.sort((a, b) =>
  91. this.sortValue === 'ascend'
  92. ? a[this.sortName!] > b[this.sortName!]
  93. ? 1
  94. : -1
  95. : b[this.sortName!] > a[this.sortName!]
  96. ? 1
  97. : -1
  98. );
  99. } else {
  100. this.listOfDisplayData = data;
  101. }
  102. }
  103. }

Table表格 - 图6

可控的筛选和排序

使用受控属性对筛选状态进行控制。

  1. th 中定义了 nzSort 属性即视为受控模式。
  2. 通过手动指定 nzSort 来指定当前列的排序状态
  3. 通过 thnzSortChange 事件来获取当前列排序状态的改变
  4. 不可与 thead 中的 nzSortChangenzSingleSort 同时使用
  1. import { Component } from '@angular/core';
  2. interface Data {
  3. name: string;
  4. age: number;
  5. address: string;
  6. [key: string]: any;
  7. }
  8. @Component({
  9. selector: 'nz-demo-table-reset-filter',
  10. template: `
  11. <div class="table-operations">
  12. <button nz-button (click)="sort('age', 'descend')">Sort age</button>
  13. <button nz-button (click)="resetFilters()">Clear filters</button>
  14. <button nz-button (click)="resetSortAndFilters()">Clear filters and sorters</button>
  15. </div>
  16. <nz-table #filterTable [nzData]="listOfDisplayData">
  17. <thead>
  18. <tr>
  19. <th
  20. nzShowSort
  21. nzShowFilter
  22. [(nzSort)]="mapOfSort.name"
  23. (nzSortChange)="sort('name', $event)"
  24. [nzFilters]="listOfFilterName"
  25. (nzFilterChange)="search($event, listOfSearchAddress)"
  26. >
  27. Name
  28. </th>
  29. <th nzShowSort [(nzSort)]="mapOfSort.age" (nzSortChange)="sort('age', $event)">Age</th>
  30. <th
  31. nzShowSort
  32. nzShowFilter
  33. [(nzSort)]="mapOfSort.address"
  34. (nzSortChange)="sort('address', $event)"
  35. [nzFilters]="listOfFilterAddress"
  36. (nzFilterChange)="search(listOfSearchName, $event)"
  37. >
  38. Address
  39. </th>
  40. </tr>
  41. </thead>
  42. <tbody>
  43. <tr *ngFor="let data of filterTable.data">
  44. <td>{{ data.name }}</td>
  45. <td>{{ data.age }}</td>
  46. <td>{{ data.address }}</td>
  47. </tr>
  48. </tbody>
  49. </nz-table>
  50. `,
  51. styles: [
  52. `
  53. .table-operations {
  54. margin-bottom: 16px;
  55. }
  56. .table-operations > button {
  57. margin-right: 8px;
  58. }
  59. `
  60. ]
  61. })
  62. export class NzDemoTableResetFilterComponent {
  63. listOfSearchName: string[] = [];
  64. listOfSearchAddress: string[] = [];
  65. listOfFilterName = [{ text: 'Joe', value: 'Joe' }, { text: 'Jim', value: 'Jim' }];
  66. listOfFilterAddress = [{ text: 'London', value: 'London' }, { text: 'Sidney', value: 'Sidney' }];
  67. listOfData: Data[] = [
  68. {
  69. name: 'John Brown',
  70. age: 32,
  71. address: 'New York No. 1 Lake Park'
  72. },
  73. {
  74. name: 'Jim Green',
  75. age: 42,
  76. address: 'London No. 1 Lake Park'
  77. },
  78. {
  79. name: 'Joe Black',
  80. age: 32,
  81. address: 'Sidney No. 1 Lake Park'
  82. },
  83. {
  84. name: 'Jim Red',
  85. age: 32,
  86. address: 'London No. 2 Lake Park'
  87. }
  88. ];
  89. listOfDisplayData = [...this.listOfData];
  90. mapOfSort: { [key: string]: any } = {
  91. name: null,
  92. age: null,
  93. address: null
  94. };
  95. sortName: string | null = null;
  96. sortValue: string | null = null;
  97. sort(sortName: string, value: string): void {
  98. this.sortName = sortName;
  99. this.sortValue = value;
  100. for (const key in this.mapOfSort) {
  101. this.mapOfSort[key] = key === sortName ? value : null;
  102. }
  103. this.search(this.listOfSearchName, this.listOfSearchAddress);
  104. }
  105. search(listOfSearchName: string[], listOfSearchAddress: string[]): void {
  106. this.listOfSearchName = listOfSearchName;
  107. this.listOfSearchAddress = listOfSearchAddress;
  108. const filterFunc = (item: Data) =>
  109. (this.listOfSearchAddress.length
  110. ? this.listOfSearchAddress.some(address => item.address.indexOf(address) !== -1)
  111. : true) &&
  112. (this.listOfSearchName.length ? this.listOfSearchName.some(name => item.name.indexOf(name) !== -1) : true);
  113. const listOfData = this.listOfData.filter((item: Data) => filterFunc(item));
  114. if (this.sortName && this.sortValue) {
  115. this.listOfDisplayData = listOfData.sort((a, b) =>
  116. this.sortValue === 'ascend'
  117. ? a[this.sortName!] > b[this.sortName!]
  118. ? 1
  119. : -1
  120. : b[this.sortName!] > a[this.sortName!]
  121. ? 1
  122. : -1
  123. );
  124. } else {
  125. this.listOfDisplayData = listOfData;
  126. }
  127. }
  128. resetFilters(): void {
  129. this.listOfFilterName = [{ text: 'Joe', value: 'Joe' }, { text: 'Jim', value: 'Jim' }];
  130. this.listOfFilterAddress = [{ text: 'London', value: 'London' }, { text: 'Sidney', value: 'Sidney' }];
  131. this.listOfSearchName = [];
  132. this.listOfSearchAddress = [];
  133. this.search(this.listOfSearchName, this.listOfSearchAddress);
  134. }
  135. resetSortAndFilters(): void {
  136. this.sortName = null;
  137. this.sortValue = null;
  138. this.mapOfSort = {
  139. name: null,
  140. age: null,
  141. address: null
  142. };
  143. this.resetFilters();
  144. this.search(this.listOfSearchName, this.listOfSearchAddress);
  145. }
  146. }

Table表格 - 图7

自定义筛选菜单

通过 nz-dropdownnzFiltersnzFilterChange 定义自定义的列筛选功能,并实现一个搜索列的示例,实际使用中建议将搜索组件进行单独封装。

  1. import { Component } from '@angular/core';
  2. @Component({
  3. selector: 'nz-demo-table-custom-filter-panel',
  4. template: `
  5. <nz-table #nzTable [nzData]="listOfDisplayData">
  6. <thead>
  7. <tr>
  8. <th nzCustomFilter>
  9. Name
  10. <nz-dropdown nzTrigger="click" nzPlacement="bottomRight" [nzClickHide]="false" nzTableFilter #dropdown>
  11. <i
  12. nz-icon
  13. nzType="search"
  14. class="ant-table-filter-icon"
  15. [class.ant-table-filter-open]="dropdown.nzVisible"
  16. nz-dropdown
  17. ></i>
  18. <div class="search-box">
  19. <input type="text" nz-input placeholder="Search name" [(ngModel)]="searchValue" />
  20. <button nz-button nzSize="small" nzType="primary" (click)="search()" class="search-button">
  21. Search
  22. </button>
  23. <button nz-button nzSize="small" (click)="reset()">Reset</button>
  24. </div>
  25. </nz-dropdown>
  26. </th>
  27. <th>Age</th>
  28. <th nzShowFilter [nzFilters]="listOfFilterAddress" (nzFilterChange)="filterAddressChange($event)">Address</th>
  29. </tr>
  30. </thead>
  31. <tbody>
  32. <tr *ngFor="let data of nzTable.data">
  33. <td>{{ data.name }}</td>
  34. <td>{{ data.age }}</td>
  35. <td>{{ data.address }}</td>
  36. </tr>
  37. </tbody>
  38. </nz-table>
  39. `,
  40. styles: [
  41. `
  42. .search-box {
  43. padding: 8px;
  44. }
  45. .search-box input {
  46. width: 188px;
  47. margin-bottom: 8px;
  48. display: block;
  49. }
  50. .search-box button {
  51. width: 90px;
  52. }
  53. .search-button {
  54. margin-right: 8px;
  55. }
  56. `
  57. ]
  58. })
  59. export class NzDemoTableCustomFilterPanelComponent {
  60. searchValue = '';
  61. sortName: string | null = null;
  62. sortValue: string | null = null;
  63. listOfFilterAddress = [{ text: 'London', value: 'London' }, { text: 'Sidney', value: 'Sidney' }];
  64. listOfSearchAddress: string[] = [];
  65. listOfData: Array<{ name: string; age: number; address: string; [key: string]: string | number }> = [
  66. {
  67. name: 'John Brown',
  68. age: 32,
  69. address: 'New York No. 1 Lake Park'
  70. },
  71. {
  72. name: 'Jim Green',
  73. age: 42,
  74. address: 'London No. 1 Lake Park'
  75. },
  76. {
  77. name: 'Joe Black',
  78. age: 32,
  79. address: 'Sidney No. 1 Lake Park'
  80. },
  81. {
  82. name: 'Jim Red',
  83. age: 32,
  84. address: 'London No. 2 Lake Park'
  85. }
  86. ];
  87. listOfDisplayData = [...this.listOfData];
  88. reset(): void {
  89. this.searchValue = '';
  90. this.search();
  91. }
  92. sort(sortName: string, value: string): void {
  93. this.sortName = sortName;
  94. this.sortValue = value;
  95. this.search();
  96. }
  97. filterAddressChange(value: string[]): void {
  98. this.listOfSearchAddress = value;
  99. this.search();
  100. }
  101. search(): void {
  102. const filterFunc = (item: { name: string; age: number; address: string }) => {
  103. return (
  104. (this.listOfSearchAddress.length
  105. ? this.listOfSearchAddress.some(address => item.address.indexOf(address) !== -1)
  106. : true) && item.name.indexOf(this.searchValue) !== -1
  107. );
  108. };
  109. const data = this.listOfData.filter((item: { name: string; age: number; address: string }) => filterFunc(item));
  110. this.listOfDisplayData = data.sort((a, b) =>
  111. this.sortValue === 'ascend'
  112. ? a[this.sortName!] > b[this.sortName!]
  113. ? 1
  114. : -1
  115. : b[this.sortName!] > a[this.sortName!]
  116. ? 1
  117. : -1
  118. );
  119. }
  120. }

Table表格 - 图8

远程加载数据

这个例子通过简单的 ajax 读取方式,演示了如何从服务端读取并展现数据,具有筛选、排序等功能以及页面 loading 效果。开发者可以自行接入其他数据处理方式。

注意,此示例使用 模拟接口,展示数据可能不准确,请打开网络面板查看请求。

  1. import { HttpClient, HttpParams } from '@angular/common/http';
  2. import { Component, Injectable, OnInit } from '@angular/core';
  3. import { Observable } from 'rxjs';
  4. @Injectable()
  5. export class RandomUserService {
  6. randomUserUrl = 'https://api.randomuser.me/';
  7. getUsers(
  8. pageIndex: number = 1,
  9. pageSize: number = 10,
  10. sortField: string,
  11. sortOrder: string,
  12. genders: string[]
  13. ): Observable<{}> {
  14. let params = new HttpParams()
  15. .append('page', `${pageIndex}`)
  16. .append('results', `${pageSize}`)
  17. .append('sortField', sortField)
  18. .append('sortOrder', sortOrder);
  19. genders.forEach(gender => {
  20. params = params.append('gender', gender);
  21. });
  22. return this.http.get(`${this.randomUserUrl}`, {
  23. params
  24. });
  25. }
  26. constructor(private http: HttpClient) {}
  27. }
  28. @Component({
  29. selector: 'nz-demo-table-ajax',
  30. providers: [RandomUserService],
  31. template: `
  32. <nz-table
  33. #ajaxTable
  34. nzShowSizeChanger
  35. [nzFrontPagination]="false"
  36. [nzData]="listOfData"
  37. [nzLoading]="loading"
  38. [nzTotal]="total"
  39. [(nzPageIndex)]="pageIndex"
  40. [(nzPageSize)]="pageSize"
  41. (nzPageIndexChange)="searchData()"
  42. (nzPageSizeChange)="searchData(true)"
  43. >
  44. <thead (nzSortChange)="sort($event)" nzSingleSort>
  45. <tr>
  46. <th nzShowSort nzSortKey="name">Name</th>
  47. <th nzShowFilter [nzFilters]="filterGender" (nzFilterChange)="updateFilter($event)">Gender</th>
  48. <th nzShowSort nzSortKey="email"><span>Email</span></th>
  49. </tr>
  50. </thead>
  51. <tbody>
  52. <tr *ngFor="let data of ajaxTable.data">
  53. <td>{{ data.name.first }} {{ data.name.last }}</td>
  54. <td>{{ data.gender }}</td>
  55. <td>{{ data.email }}</td>
  56. </tr>
  57. </tbody>
  58. </nz-table>
  59. `
  60. })
  61. export class NzDemoTableAjaxComponent implements OnInit {
  62. pageIndex = 1;
  63. pageSize = 10;
  64. total = 1;
  65. listOfData = [];
  66. loading = true;
  67. sortValue: string | null = null;
  68. sortKey: string | null = null;
  69. filterGender = [{ text: 'male', value: 'male' }, { text: 'female', value: 'female' }];
  70. searchGenderList: string[] = [];
  71. sort(sort: { key: string; value: string }): void {
  72. this.sortKey = sort.key;
  73. this.sortValue = sort.value;
  74. this.searchData();
  75. }
  76. constructor(private randomUserService: RandomUserService) {}
  77. searchData(reset: boolean = false): void {
  78. if (reset) {
  79. this.pageIndex = 1;
  80. }
  81. this.loading = true;
  82. this.randomUserService
  83. .getUsers(this.pageIndex, this.pageSize, this.sortKey!, this.sortValue!, this.searchGenderList)
  84. .subscribe((data: any) => {
  85. this.loading = false;
  86. this.total = 200;
  87. this.listOfData = data.results;
  88. });
  89. }
  90. updateFilter(value: string[]): void {
  91. this.searchGenderList = value;
  92. this.searchData(true);
  93. }
  94. ngOnInit(): void {
  95. this.searchData();
  96. }
  97. }

Table表格 - 图9

紧凑型

两种紧凑型的列表,小型列表只用于对话框内。

  1. import { Component } from '@angular/core';
  2. @Component({
  3. selector: 'nz-demo-table-size',
  4. template: `
  5. <h4>Middle size table</h4>
  6. <nz-table #middleTable nzSize="middle" [nzData]="data">
  7. <thead>
  8. <tr>
  9. <th>Name</th>
  10. <th>Age</th>
  11. <th>Address</th>
  12. </tr>
  13. </thead>
  14. <tbody>
  15. <tr *ngFor="let data of middleTable.data">
  16. <td>{{ data.name }}</td>
  17. <td>{{ data.age }}</td>
  18. <td>{{ data.address }}</td>
  19. </tr>
  20. </tbody>
  21. </nz-table>
  22. <h4>Small size table</h4>
  23. <nz-table #smallTable nzSize="small" [nzData]="data">
  24. <thead>
  25. <tr>
  26. <th>Name</th>
  27. <th>Age</th>
  28. <th>Address</th>
  29. </tr>
  30. </thead>
  31. <tbody>
  32. <tr *ngFor="let data of smallTable.data">
  33. <td>{{ data.name }}</td>
  34. <td>{{ data.age }}</td>
  35. <td>{{ data.address }}</td>
  36. </tr>
  37. </tbody>
  38. </nz-table>
  39. `,
  40. styles: [
  41. `
  42. h4 {
  43. margin-bottom: 16px;
  44. }
  45. `
  46. ]
  47. })
  48. export class NzDemoTableSizeComponent {
  49. data = [
  50. {
  51. key: '1',
  52. name: 'John Brown',
  53. age: 32,
  54. address: 'New York No. 1 Lake Park'
  55. },
  56. {
  57. key: '2',
  58. name: 'Jim Green',
  59. age: 42,
  60. address: 'London No. 1 Lake Park'
  61. },
  62. {
  63. key: '3',
  64. name: 'Joe Black',
  65. age: 32,
  66. address: 'Sidney No. 1 Lake Park'
  67. }
  68. ];
  69. }

Table表格 - 图10

带边框

添加表格边框线,页头和页脚。

  1. import { Component } from '@angular/core';
  2. @Component({
  3. selector: 'nz-demo-table-bordered',
  4. template: `
  5. <nz-table #borderedTable nzBordered nzFooter="Footer" nzTitle="Header" [nzData]="dataSet">
  6. <thead>
  7. <tr>
  8. <th>Name</th>
  9. <th>Age</th>
  10. <th>Address</th>
  11. </tr>
  12. </thead>
  13. <tbody>
  14. <tr *ngFor="let data of borderedTable.data">
  15. <td>{{ data.name }}</td>
  16. <td>{{ data.age }}</td>
  17. <td>{{ data.address }}</td>
  18. </tr>
  19. </tbody>
  20. </nz-table>
  21. `
  22. })
  23. export class NzDemoTableBorderedComponent {
  24. dataSet = [
  25. {
  26. key: '1',
  27. name: 'John Brown',
  28. age: 32,
  29. address: 'New York No. 1 Lake Park'
  30. },
  31. {
  32. key: '2',
  33. name: 'Jim Green',
  34. age: 42,
  35. address: 'London No. 1 Lake Park'
  36. },
  37. {
  38. key: '3',
  39. name: 'Joe Black',
  40. age: 32,
  41. address: 'Sidney No. 1 Lake Park'
  42. }
  43. ];
  44. }

Table表格 - 图11

可展开

当表格内容较多不能一次性完全展示时,可以通过 td 上的 nzExpand 属性展开。

  1. import { Component } from '@angular/core';
  2. @Component({
  3. selector: 'nz-demo-table-expand',
  4. template: `
  5. <nz-table #nzTable [nzData]="listOfData">
  6. <thead>
  7. <tr>
  8. <th nzShowExpand></th>
  9. <th>Name</th>
  10. <th>Age</th>
  11. <th>Address</th>
  12. </tr>
  13. </thead>
  14. <tbody>
  15. <ng-template ngFor let-data [ngForOf]="nzTable.data">
  16. <tr>
  17. <td nzShowExpand [(nzExpand)]="mapOfExpandData[data.id]"></td>
  18. <td>{{ data.name }}</td>
  19. <td>{{ data.age }}</td>
  20. <td>{{ data.address }}</td>
  21. </tr>
  22. <tr [nzExpand]="mapOfExpandData[data.id]">
  23. <td></td>
  24. <td colspan="3">{{ data.description }}</td>
  25. </tr>
  26. </ng-template>
  27. </tbody>
  28. </nz-table>
  29. `,
  30. styles: []
  31. })
  32. export class NzDemoTableExpandComponent {
  33. mapOfExpandData: { [key: string]: boolean } = {};
  34. listOfData = [
  35. {
  36. id: 1,
  37. name: 'John Brown',
  38. age: 32,
  39. expand: false,
  40. address: 'New York No. 1 Lake Park',
  41. description: 'My name is John Brown, I am 32 years old, living in New York No. 1 Lake Park.'
  42. },
  43. {
  44. id: 2,
  45. name: 'Jim Green',
  46. age: 42,
  47. expand: false,
  48. address: 'London No. 1 Lake Park',
  49. description: 'My name is Jim Green, I am 42 years old, living in London No. 1 Lake Park.'
  50. },
  51. {
  52. id: 3,
  53. name: 'Joe Black',
  54. age: 32,
  55. expand: false,
  56. address: 'Sidney No. 1 Lake Park',
  57. description: 'My name is Joe Black, I am 32 years old, living in Sidney No. 1 Lake Park.'
  58. }
  59. ];
  60. }

Table表格 - 图12

表格行/列合并

W3C标准 <table> 一样,使用 colspanrowspan 合并行/列。

  1. import { Component } from '@angular/core';
  2. @Component({
  3. selector: 'nz-demo-table-colspan-rowspan',
  4. template: `
  5. <nz-table #colSpanTable [nzData]="listOfData" nzBordered>
  6. <thead>
  7. <tr>
  8. <th>Name</th>
  9. <th>Age</th>
  10. <th colspan="2">Home phone</th>
  11. <th>Address</th>
  12. </tr>
  13. </thead>
  14. <tbody>
  15. <tr *ngFor="let data of colSpanTable.data; index as i">
  16. <td>{{ data.name }}</td>
  17. <td [attr.colspan]="i === 4 ? 5 : 1">{{ data.age }}</td>
  18. <td [attr.rowspan]="i === 2 ? 2 : 1" *ngIf="i !== 3 && i !== 4">{{ data.tel }}</td>
  19. <td *ngIf="i !== 4">{{ data.phone }}</td>
  20. <td *ngIf="i !== 4">{{ data.address }}</td>
  21. </tr>
  22. </tbody>
  23. </nz-table>
  24. `
  25. })
  26. export class NzDemoTableColspanRowspanComponent {
  27. listOfData = [
  28. {
  29. key: '1',
  30. name: 'John Brown',
  31. age: 32,
  32. tel: '0571-22098909',
  33. phone: 18889898989,
  34. address: 'New York No. 1 Lake Park'
  35. },
  36. {
  37. key: '2',
  38. name: 'Jim Green',
  39. tel: '0571-22098333',
  40. phone: 18889898888,
  41. age: 42,
  42. address: 'London No. 1 Lake Park'
  43. },
  44. {
  45. key: '3',
  46. name: 'Joe Black',
  47. age: 32,
  48. tel: '0575-22098909',
  49. phone: 18900010002,
  50. address: 'Sidney No. 1 Lake Park'
  51. },
  52. {
  53. key: '4',
  54. name: 'Jim Red',
  55. age: 18,
  56. tel: '0575-22098909',
  57. phone: 18900010002,
  58. address: 'London No. 2 Lake Park'
  59. },
  60. {
  61. key: '5',
  62. name: 'Jake White',
  63. age: 18,
  64. tel: '0575-22098909',
  65. phone: 18900010002,
  66. address: 'Dublin No. 2 Lake Park'
  67. }
  68. ];
  69. }

Table表格 - 图13

树形数据展示

表格支持树形数据的展示,可以通过设置 nzIndentSize 以控制每一层的缩进宽度,本例子中提供了树与数组之间的转换函数,实际业务中请根据需求修改。

  1. import { Component, OnInit } from '@angular/core';
  2. export interface TreeNodeInterface {
  3. key: number;
  4. name: string;
  5. age: number;
  6. level: number;
  7. expand: boolean;
  8. address: string;
  9. children?: TreeNodeInterface[];
  10. }
  11. @Component({
  12. selector: 'nz-demo-table-expand-children',
  13. template: `
  14. <nz-table #expandTable [nzData]="listOfMapData">
  15. <thead>
  16. <tr>
  17. <th nzWidth="40%">Name</th>
  18. <th nzWidth="30%">Age</th>
  19. <th>Address</th>
  20. </tr>
  21. </thead>
  22. <tbody>
  23. <ng-container *ngFor="let data of expandTable.data">
  24. <ng-container *ngFor="let item of mapOfExpandedData[data.key]">
  25. <tr *ngIf="(item.parent && item.parent.expand) || !item.parent">
  26. <td
  27. [nzIndentSize]="item.level * 20"
  28. [nzShowExpand]="!!item.children"
  29. [(nzExpand)]="item.expand"
  30. (nzExpandChange)="collapse(mapOfExpandedData[data.key], item, $event)"
  31. >
  32. {{ item.name }}
  33. </td>
  34. <td>{{ item.age }}</td>
  35. <td>{{ item.address }}</td>
  36. </tr>
  37. </ng-container>
  38. </ng-container>
  39. </tbody>
  40. </nz-table>
  41. `
  42. })
  43. export class NzDemoTableExpandChildrenComponent implements OnInit {
  44. listOfMapData = [
  45. {
  46. key: 1,
  47. name: 'John Brown sr.',
  48. age: 60,
  49. address: 'New York No. 1 Lake Park',
  50. children: [
  51. {
  52. key: 11,
  53. name: 'John Brown',
  54. age: 42,
  55. address: 'New York No. 2 Lake Park'
  56. },
  57. {
  58. key: 12,
  59. name: 'John Brown jr.',
  60. age: 30,
  61. address: 'New York No. 3 Lake Park',
  62. children: [
  63. {
  64. key: 121,
  65. name: 'Jimmy Brown',
  66. age: 16,
  67. address: 'New York No. 3 Lake Park'
  68. }
  69. ]
  70. },
  71. {
  72. key: 13,
  73. name: 'Jim Green sr.',
  74. age: 72,
  75. address: 'London No. 1 Lake Park',
  76. children: [
  77. {
  78. key: 131,
  79. name: 'Jim Green',
  80. age: 42,
  81. address: 'London No. 2 Lake Park',
  82. children: [
  83. {
  84. key: 1311,
  85. name: 'Jim Green jr.',
  86. age: 25,
  87. address: 'London No. 3 Lake Park'
  88. },
  89. {
  90. key: 1312,
  91. name: 'Jimmy Green sr.',
  92. age: 18,
  93. address: 'London No. 4 Lake Park'
  94. }
  95. ]
  96. }
  97. ]
  98. }
  99. ]
  100. },
  101. {
  102. key: 2,
  103. name: 'Joe Black',
  104. age: 32,
  105. address: 'Sidney No. 1 Lake Park'
  106. }
  107. ];
  108. mapOfExpandedData: { [key: string]: TreeNodeInterface[] } = {};
  109. collapse(array: TreeNodeInterface[], data: TreeNodeInterface, $event: boolean): void {
  110. if ($event === false) {
  111. if (data.children) {
  112. data.children.forEach(d => {
  113. const target = array.find(a => a.key === d.key)!;
  114. target.expand = false;
  115. this.collapse(array, target, false);
  116. });
  117. } else {
  118. return;
  119. }
  120. }
  121. }
  122. convertTreeToList(root: object): TreeNodeInterface[] {
  123. const stack: any[] = [];
  124. const array: any[] = [];
  125. const hashMap = {};
  126. stack.push({ ...root, level: 0, expand: false });
  127. while (stack.length !== 0) {
  128. const node = stack.pop();
  129. this.visitNode(node, hashMap, array);
  130. if (node.children) {
  131. for (let i = node.children.length - 1; i >= 0; i--) {
  132. stack.push({ ...node.children[i], level: node.level + 1, expand: false, parent: node });
  133. }
  134. }
  135. }
  136. return array;
  137. }
  138. visitNode(node: TreeNodeInterface, hashMap: { [key: string]: any }, array: TreeNodeInterface[]): void {
  139. if (!hashMap[node.key]) {
  140. hashMap[node.key] = true;
  141. array.push(node);
  142. }
  143. }
  144. ngOnInit(): void {
  145. this.listOfMapData.forEach(item => {
  146. this.mapOfExpandedData[item.key] = this.convertTreeToList(item);
  147. });
  148. }
  149. }

Table表格 - 图14

固定表头

方便一页内展示大量数据。

需要指定 thnzWidth 属性,否则列头和内容可能不对齐。

  1. import { Component, OnInit } from '@angular/core';
  2. @Component({
  3. selector: 'nz-demo-table-fixed-header',
  4. template: `
  5. <nz-table #headerTable [nzData]="listOfData" [nzPageSize]="50" [nzScroll]="{ y: '240px' }">
  6. <thead>
  7. <tr>
  8. <th nzWidth="150px">Name</th>
  9. <th nzWidth="150px">Age</th>
  10. <th>Address</th>
  11. </tr>
  12. </thead>
  13. <tbody>
  14. <tr *ngFor="let data of headerTable.data">
  15. <td>{{ data.name }}</td>
  16. <td>{{ data.age }}</td>
  17. <td>{{ data.address }}</td>
  18. </tr>
  19. </tbody>
  20. </nz-table>
  21. `
  22. })
  23. export class NzDemoTableFixedHeaderComponent implements OnInit {
  24. listOfData: any[] = [];
  25. ngOnInit(): void {
  26. for (let i = 0; i < 100; i++) {
  27. this.listOfData.push({
  28. name: `Edward King ${i}`,
  29. age: 32,
  30. address: `London, Park Lane no. ${i}`
  31. });
  32. }
  33. }
  34. }

Table表格 - 图15

固定列

对于列数很多的数据,可以使用 nzLeftnzRight 固定前后的列,横向滚动查看其它数据,需要和 nzScroll.x 配合使用。

固定列使用了 sticky 属性,浏览器支持情况可以参考这里

若列头与内容不对齐或出现列重复,请指定每一列的 th 的宽度 nzWidth

建议指定 nzScroll.x 为大于表格宽度的固定值或百分比。注意,且非固定列宽度之和不要超过 nzScroll.x

  1. import { Component } from '@angular/core';
  2. @Component({
  3. selector: 'nz-demo-table-fixed-columns',
  4. template: `
  5. <nz-table #columnTable [nzData]="listOfData" [nzScroll]="{ x: '1100px' }">
  6. <thead>
  7. <tr>
  8. <th nzWidth="100px" nzLeft="0px">Full Name</th>
  9. <th nzWidth="100px" nzLeft="100px">Age</th>
  10. <th nzWidth="100px">Column 1</th>
  11. <th nzWidth="100px">Column 2</th>
  12. <th nzWidth="100px">Column 3</th>
  13. <th nzWidth="100px">Column 4</th>
  14. <th nzWidth="100px">Column 5</th>
  15. <th nzWidth="100px">Column 6</th>
  16. <th nzWidth="100px">Column 7</th>
  17. <th nzRight="100px" nzWidth="100px">Column 8</th>
  18. <th nzWidth="100px" nzRight="0px">Action</th>
  19. </tr>
  20. </thead>
  21. <tbody>
  22. <tr *ngFor="let data of columnTable.data">
  23. <td nzLeft="0px">{{ data.name }}</td>
  24. <td nzLeft="100px">{{ data.age }}</td>
  25. <td>{{ data.address }}</td>
  26. <td>{{ data.address }}</td>
  27. <td>{{ data.address }}</td>
  28. <td>{{ data.address }}</td>
  29. <td>{{ data.address }}</td>
  30. <td>{{ data.address }}</td>
  31. <td>{{ data.address }}</td>
  32. <td nzRight="100px">{{ data.address }}</td>
  33. <td nzRight="0px">
  34. <a>action</a>
  35. </td>
  36. </tr>
  37. </tbody>
  38. </nz-table>
  39. `
  40. })
  41. export class NzDemoTableFixedColumnsComponent {
  42. listOfData = [
  43. {
  44. key: '1',
  45. name: 'John Brown',
  46. age: 32,
  47. address: 'New York'
  48. },
  49. {
  50. key: '2',
  51. name: 'Jim Green',
  52. age: 40,
  53. address: 'London'
  54. }
  55. ];
  56. }

Table表格 - 图16

固定头和列

适合同时展示有大量数据和数据列。

固定列使用了 sticky 属性,浏览器支持情况可以参考这里

若列头与内容不对齐或出现列重复,请指定列的宽度 nzWidth

建议指定 nzScroll.x 为大于表格宽度的固定值或百分比。注意,且非固定列宽度之和不要超过 nzScroll.x

  1. import { Component, OnInit } from '@angular/core';
  2. @Component({
  3. selector: 'nz-demo-table-fixed-columns-header',
  4. template: `
  5. <nz-table #fixedTable [nzData]="listOfData" [nzScroll]="{ x: '1150px', y: '240px' }">
  6. <thead>
  7. <tr>
  8. <th nzWidth="150px" nzLeft="0px">Full Name</th>
  9. <th nzWidth="100px" nzLeft="150px">Age</th>
  10. <th nzWidth="100px">Column 1</th>
  11. <th nzWidth="100px">Column 2</th>
  12. <th nzWidth="100px">Column 3</th>
  13. <th nzWidth="100px">Column 4</th>
  14. <th nzWidth="100px">Column 5</th>
  15. <th nzWidth="100px">Column 6</th>
  16. <th nzWidth="100px">Column 7</th>
  17. <th nzWidth="100px">Column 8</th>
  18. <th nzWidth="100px" nzRight="0px">Action</th>
  19. </tr>
  20. </thead>
  21. <tbody>
  22. <tr *ngFor="let data of fixedTable.data">
  23. <td nzLeft="0px">{{ data.name }}</td>
  24. <td nzLeft="150px">{{ data.age }}</td>
  25. <td>{{ data.address }}</td>
  26. <td>{{ data.address }}</td>
  27. <td>{{ data.address }}</td>
  28. <td>{{ data.address }}</td>
  29. <td>{{ data.address }}</td>
  30. <td>{{ data.address }}</td>
  31. <td>{{ data.address }}</td>
  32. <td>{{ data.address }}</td>
  33. <td nzRight="0px">
  34. <a>action</a>
  35. </td>
  36. </tr>
  37. </tbody>
  38. </nz-table>
  39. `
  40. })
  41. export class NzDemoTableFixedColumnsHeaderComponent implements OnInit {
  42. listOfData: any[] = [];
  43. ngOnInit(): void {
  44. for (let i = 0; i < 100; i++) {
  45. this.listOfData.push({
  46. name: `Edward King ${i}`,
  47. age: 32,
  48. address: `London`
  49. });
  50. }
  51. }
  52. }

Table表格 - 图17

表头分组

当使用分组表头时,thnzWidth 方式不再适用,使用 nzWidthConfig 来设定每个分组的宽度

  1. import { Component, OnInit } from '@angular/core';
  2. @Component({
  3. selector: 'nz-demo-table-grouping-columns',
  4. template: `
  5. <nz-table
  6. #groupingTable
  7. [nzData]="listOfDisplayData"
  8. nzBordered
  9. nzSize="middle"
  10. [nzWidthConfig]="widthConfig"
  11. [nzScroll]="scrollConfig"
  12. >
  13. <thead>
  14. <tr>
  15. <th rowspan="4" nzLeft="0px" nzShowFilter [nzFilters]="filterName" (nzFilterChange)="search($event)">Name</th>
  16. <th colspan="4">Other</th>
  17. <th colspan="2">Company</th>
  18. <th rowspan="4" nzRight="0px">Gender</th>
  19. </tr>
  20. <tr>
  21. <th rowspan="3" nzShowSort [(nzSort)]="sortValue" (nzSortChange)="search(searchName)">Age</th>
  22. <th colspan="3">Address</th>
  23. <th rowspan="3">Company Address</th>
  24. <th rowspan="3">Company Name</th>
  25. </tr>
  26. <tr>
  27. <th rowspan="2">Street</th>
  28. <th colspan="2">Block</th>
  29. </tr>
  30. <tr>
  31. <th>Building</th>
  32. <th>Door No.</th>
  33. </tr>
  34. </thead>
  35. <tbody>
  36. <tr *ngFor="let data of groupingTable.data">
  37. <td nzLeft="0px">{{ data.name }}</td>
  38. <td>{{ data.age }}</td>
  39. <td>{{ data.street }}</td>
  40. <td>{{ data.building }}</td>
  41. <td>{{ data.number }}</td>
  42. <td>{{ data.companyAddress }}</td>
  43. <td>{{ data.companyName }}</td>
  44. <td nzRight="0px">{{ data.gender }}</td>
  45. </tr>
  46. </tbody>
  47. </nz-table>
  48. `
  49. })
  50. export class NzDemoTableGroupingColumnsComponent implements OnInit {
  51. widthConfig = ['100px', '200px', '200px', '100px', '100px', '200px', '200px', '100px'];
  52. scrollConfig = { x: '1200px', y: '240px' };
  53. listOfDisplayData: any[] = [];
  54. listOfData: any[] = [];
  55. sortValue: string | null = null;
  56. filterName = [{ text: 'Joe', value: 'Joe' }, { text: 'John', value: 'John' }];
  57. searchName: string[] = [];
  58. search(searchName: string[]): void {
  59. this.searchName = searchName;
  60. const filterFunc = (item: any) => {
  61. return this.searchName.length ? this.searchName.some(name => item.name.indexOf(name) !== -1) : true;
  62. };
  63. const listOfData = this.listOfData.filter(item => filterFunc(item));
  64. this.listOfDisplayData = listOfData.sort((a, b) =>
  65. this.sortValue === 'ascend' ? (a.age > b.age ? 1 : -1) : b.age > a.age ? 1 : -1
  66. );
  67. }
  68. ngOnInit(): void {
  69. for (let i = 0; i < 100; i++) {
  70. this.listOfData.push({
  71. name: 'John Brown',
  72. age: i + 1,
  73. street: 'Lake Park',
  74. building: 'C',
  75. number: 2035,
  76. companyAddress: 'Lake Street 42',
  77. companyName: 'SoftLake Co',
  78. gender: 'M'
  79. });
  80. }
  81. this.listOfDisplayData = [...this.listOfData];
  82. }
  83. }

Table表格 - 图18

可编辑单元格

定制带单元格编辑功能的表格,自由操作单元格内容。

  1. import { Component, ElementRef, HostListener, OnInit, ViewChild } from '@angular/core';
  2. import { NzInputDirective } from 'ng-zorro-antd';
  3. @Component({
  4. selector: 'nz-demo-table-edit-cell',
  5. template: `
  6. <button nz-button (click)="addRow()" nzType="primary">Add</button>
  7. <nz-table #editRowTable nzBordered [nzData]="listOfData">
  8. <thead>
  9. <tr>
  10. <th nzWidth="30%">Name</th>
  11. <th>Age</th>
  12. <th>Address</th>
  13. <th>Action</th>
  14. </tr>
  15. </thead>
  16. <tbody>
  17. <tr *ngFor="let data of editRowTable.data" class="editable-row">
  18. <td>
  19. <div class="editable-cell" *ngIf="editId !== data.id; else editTpl">
  20. <div class="editable-cell-value-wrap" (click)="startEdit(data.id, $event)">
  21. {{ data.name }}
  22. </div>
  23. </div>
  24. <ng-template #editTpl>
  25. <input type="text" nz-input [(ngModel)]="data.name" />
  26. </ng-template>
  27. </td>
  28. <td>{{ data.age }}</td>
  29. <td>{{ data.address }}</td>
  30. <td>
  31. <a nz-popconfirm nzTitle="Sure to delete?" (nzOnConfirm)="deleteRow(data.id)">Delete</a>
  32. </td>
  33. </tr>
  34. </tbody>
  35. </nz-table>
  36. `,
  37. styles: [
  38. `
  39. button {
  40. margin-bottom: 16px;
  41. }
  42. .editable-cell {
  43. position: relative;
  44. }
  45. .editable-cell-value-wrap {
  46. padding: 5px 12px;
  47. cursor: pointer;
  48. }
  49. .editable-row:hover .editable-cell-value-wrap {
  50. border: 1px solid #d9d9d9;
  51. border-radius: 4px;
  52. padding: 4px 11px;
  53. }
  54. `
  55. ]
  56. })
  57. export class NzDemoTableEditCellComponent implements OnInit {
  58. i = 0;
  59. editId: string | null;
  60. listOfData: any[] = [];
  61. @ViewChild(NzInputDirective, { read: ElementRef }) inputElement: ElementRef;
  62. @HostListener('window:click', ['$event'])
  63. handleClick(e: MouseEvent): void {
  64. if (this.editId && this.inputElement && this.inputElement.nativeElement !== e.target) {
  65. this.editId = null;
  66. }
  67. }
  68. addRow(): void {
  69. this.listOfData = [
  70. ...this.listOfData,
  71. {
  72. id: `${this.i}`,
  73. name: `Edward King ${this.i}`,
  74. age: '32',
  75. address: `London, Park Lane no. ${this.i}`
  76. }
  77. ];
  78. this.i++;
  79. }
  80. deleteRow(id: string): void {
  81. this.listOfData = this.listOfData.filter(d => d.id !== id);
  82. }
  83. startEdit(id: string, event: MouseEvent): void {
  84. event.preventDefault();
  85. event.stopPropagation();
  86. this.editId = id;
  87. }
  88. ngOnInit(): void {
  89. this.addRow();
  90. this.addRow();
  91. }
  92. }

Table表格 - 图19

可编辑行

定制带行编辑功能的表格,自由操作行内容。

  1. import { Component, OnInit } from '@angular/core';
  2. @Component({
  3. selector: 'nz-demo-table-edit-row',
  4. template: `
  5. <nz-table #editRowTable nzBordered [nzData]="listOfData">
  6. <thead>
  7. <tr>
  8. <th nzWidth="25%">Name</th>
  9. <th nzWidth="15%">Age</th>
  10. <th nzWidth="40%">Address</th>
  11. <th>Action</th>
  12. </tr>
  13. </thead>
  14. <tbody>
  15. <tr *ngFor="let data of editRowTable.data">
  16. <td>
  17. <ng-container *ngIf="!editCache[data.id].edit; else nameInputTpl">
  18. {{ data.name }}
  19. </ng-container>
  20. <ng-template #nameInputTpl>
  21. <input type="text" nz-input [(ngModel)]="editCache[data.id].data.name" />
  22. </ng-template>
  23. </td>
  24. <td>
  25. <ng-container *ngIf="!editCache[data.id].edit; else ageInputTpl">
  26. {{ data.age }}
  27. </ng-container>
  28. <ng-template #ageInputTpl>
  29. <input type="text" nz-input [(ngModel)]="editCache[data.id].data.age" />
  30. </ng-template>
  31. </td>
  32. <td>
  33. <ng-container *ngIf="!editCache[data.id].edit; else addressInputTpl">
  34. {{ data.address }}
  35. </ng-container>
  36. <ng-template #addressInputTpl>
  37. <input type="text" nz-input [(ngModel)]="editCache[data.id].data.address" />
  38. </ng-template>
  39. </td>
  40. <td>
  41. <div class="editable-row-operations">
  42. <ng-container *ngIf="!editCache[data.id].edit; else saveTpl">
  43. <a (click)="startEdit(data.id)">Edit</a>
  44. </ng-container>
  45. <ng-template #saveTpl>
  46. <a (click)="saveEdit(data.id)">Save</a>
  47. <a nz-popconfirm nzTitle="Sure to cancel?" (nzOnConfirm)="cancelEdit(data.id)">Cancel</a>
  48. </ng-template>
  49. </div>
  50. </td>
  51. </tr>
  52. </tbody>
  53. </nz-table>
  54. `,
  55. styles: [
  56. `
  57. .editable-row-operations a {
  58. margin-right: 8px;
  59. }
  60. `
  61. ]
  62. })
  63. export class NzDemoTableEditRowComponent implements OnInit {
  64. editCache: { [key: string]: any } = {};
  65. listOfData: any[] = [];
  66. startEdit(id: string): void {
  67. this.editCache[id].edit = true;
  68. }
  69. cancelEdit(id: string): void {
  70. const index = this.listOfData.findIndex(item => item.id === id);
  71. this.editCache[id] = {
  72. data: { ...this.listOfData[index] },
  73. edit: false
  74. };
  75. }
  76. saveEdit(id: string): void {
  77. const index = this.listOfData.findIndex(item => item.id === id);
  78. Object.assign(this.listOfData[index], this.editCache[id].data);
  79. this.editCache[id].edit = false;
  80. }
  81. updateEditCache(): void {
  82. this.listOfData.forEach(item => {
  83. this.editCache[item.id] = {
  84. edit: false,
  85. data: { ...item }
  86. };
  87. });
  88. }
  89. ngOnInit(): void {
  90. for (let i = 0; i < 100; i++) {
  91. this.listOfData.push({
  92. id: `${i}`,
  93. name: `Edrward ${i}`,
  94. age: 32,
  95. address: `London Park no. ${i}`
  96. });
  97. }
  98. this.updateEditCache();
  99. }
  100. }

Table表格 - 图20

嵌套子表格

展示每行数据更详细的信息。

  1. import { Component, OnInit } from '@angular/core';
  2. @Component({
  3. selector: 'nz-demo-table-nested-table',
  4. template: `
  5. <nz-table #nestedTable [nzData]="listOfParentData" [nzPageSize]="10">
  6. <thead>
  7. <tr>
  8. <th nzShowExpand></th>
  9. <th>Name</th>
  10. <th>Platform</th>
  11. <th>Version</th>
  12. <th>Upgraded</th>
  13. <th>Creator</th>
  14. <th>Date</th>
  15. <th>Action</th>
  16. </tr>
  17. </thead>
  18. <tbody>
  19. <ng-template ngFor let-data [ngForOf]="nestedTable.data">
  20. <tr>
  21. <td nzShowExpand [(nzExpand)]="data.expand"></td>
  22. <td>{{ data.name }}</td>
  23. <td>{{ data.platform }}</td>
  24. <td>{{ data.version }}</td>
  25. <td>{{ data.upgradeNum }}</td>
  26. <td>{{ data.creator }}</td>
  27. <td>{{ data.createdAt }}</td>
  28. <td>
  29. <a>Publish</a>
  30. </td>
  31. </tr>
  32. <tr [nzExpand]="data.expand">
  33. <td></td>
  34. <td colspan="7">
  35. <nz-table #innerTable [nzData]="listOfChildrenData" nzSize="middle" [nzShowPagination]="false">
  36. <thead>
  37. <tr>
  38. <th>Date</th>
  39. <th>Name</th>
  40. <th>Status</th>
  41. <th>Upgrade Status</th>
  42. <th>Action</th>
  43. </tr>
  44. </thead>
  45. <tbody>
  46. <tr *ngFor="let data of innerTable.data">
  47. <td>{{ data.date }}</td>
  48. <td>{{ data.name }}</td>
  49. <td>
  50. <nz-badge [nzStatus]="'success'" [nzText]="'Finished'"></nz-badge>
  51. </td>
  52. <td>{{ data.upgradeNum }}</td>
  53. <td>
  54. <span class="table-operation">
  55. <nz-dropdown>
  56. <a nz-dropdown class="operation"> Pause <i nz-icon type="down"></i> </a>
  57. <ul nz-menu>
  58. <li nz-menu-item>
  59. <a>Action 1</a>
  60. </li>
  61. <li nz-menu-item>
  62. <a>Action 2</a>
  63. </li>
  64. </ul>
  65. </nz-dropdown>
  66. <nz-divider nzType="vertical"></nz-divider>
  67. <a class="operation">Stop</a>
  68. <nz-divider nzType="vertical"></nz-divider>
  69. <a>More</a>
  70. </span>
  71. </td>
  72. </tr>
  73. </tbody>
  74. </nz-table>
  75. </td>
  76. </tr>
  77. </ng-template>
  78. </tbody>
  79. </nz-table>
  80. `
  81. })
  82. export class NzDemoTableNestedTableComponent implements OnInit {
  83. listOfParentData: any[] = [];
  84. listOfChildrenData: any[] = [];
  85. ngOnInit(): void {
  86. for (let i = 0; i < 3; ++i) {
  87. this.listOfParentData.push({
  88. key: i,
  89. name: 'Screem',
  90. platform: 'iOS',
  91. version: '10.3.4.5654',
  92. upgradeNum: 500,
  93. creator: 'Jack',
  94. createdAt: '2014-12-24 23:12:00',
  95. expand: false
  96. });
  97. }
  98. for (let i = 0; i < 3; ++i) {
  99. this.listOfChildrenData.push({
  100. key: i,
  101. date: '2014-12-24 23:12:00',
  102. name: 'This is production name',
  103. upgradeNum: 'Upgraded: 56'
  104. });
  105. }
  106. }
  107. }

Table表格 - 图21

虚拟滚动

虚拟滚动,结合 cdk scrolling 的虚拟滚动,用于巨量数据加载。可以通过获得 cdkVirtualScrollViewport 进行进一步操作,见本示例及 API

  1. import { AfterViewInit, Component, OnDestroy, OnInit, ViewChild } from '@angular/core';
  2. import { NzTableComponent } from 'ng-zorro-antd';
  3. import { Subject } from 'rxjs';
  4. import { takeUntil } from 'rxjs/operators';
  5. @Component({
  6. selector: 'nz-demo-table-virtual',
  7. template: `
  8. <button nz-button (click)="scrollToIndex(200)">Scroll To Index 200</button>
  9. <br />
  10. <br />
  11. <nz-table
  12. #virtualTable
  13. nzVirtualScroll
  14. [nzVirtualItemSize]="54"
  15. [nzData]="listOfData"
  16. [nzFrontPagination]="false"
  17. [nzShowPagination]="false"
  18. [nzScroll]="{ x: '1300px', y: '240px' }"
  19. >
  20. <thead>
  21. <tr>
  22. <th nzWidth="200px" nzLeft="0px">Full Name</th>
  23. <th nzWidth="100px" nzLeft="200px">Age</th>
  24. <th nzWidth="100px">Index</th>
  25. <th nzWidth="100px">Column 1</th>
  26. <th nzWidth="100px">Column 2</th>
  27. <th nzWidth="100px">Column 3</th>
  28. <th nzWidth="100px">Column 4</th>
  29. <th nzWidth="100px">Column 5</th>
  30. <th nzWidth="100px">Column 6</th>
  31. <th nzWidth="100px">Column 7</th>
  32. <th nzWidth="100px">Column 8</th>
  33. <th nzWidth="100px" nzRight="0px">Action</th>
  34. </tr>
  35. </thead>
  36. <tbody>
  37. <ng-template nz-virtual-scroll let-data let-index="index">
  38. <tr>
  39. <td nzLeft="0px">{{ data.name }} {{ index }}</td>
  40. <td nzLeft="200px">{{ data.age }}</td>
  41. <td>{{ data.index }}</td>
  42. <td>{{ data.address }}</td>
  43. <td>{{ data.address }}</td>
  44. <td>{{ data.address }}</td>
  45. <td>{{ data.address }}</td>
  46. <td>{{ data.address }}</td>
  47. <td>{{ data.address }}</td>
  48. <td>{{ data.address }}</td>
  49. <td>{{ data.address }}</td>
  50. <td nzRight="0px">
  51. <a>action</a>
  52. </td>
  53. </tr>
  54. </ng-template>
  55. </tbody>
  56. </nz-table>
  57. `
  58. })
  59. export class NzDemoTableVirtualComponent implements OnInit, AfterViewInit, OnDestroy {
  60. @ViewChild('virtualTable') nzTableComponent: NzTableComponent;
  61. private destroy$ = new Subject();
  62. listOfData: any[] = [];
  63. scrollToIndex(index: number): void {
  64. this.nzTableComponent.cdkVirtualScrollViewport.scrollToIndex(index);
  65. }
  66. ngOnInit(): void {
  67. for (let i = 0; i < 20000; i++) {
  68. this.listOfData.push({
  69. index: i,
  70. name: `Edward King`,
  71. age: 32,
  72. address: `London`
  73. });
  74. }
  75. }
  76. ngAfterViewInit(): void {
  77. this.nzTableComponent.cdkVirtualScrollViewport.scrolledIndexChange
  78. .pipe(takeUntil(this.destroy$))
  79. .subscribe(data => {
  80. console.log('scroll index to', data);
  81. });
  82. }
  83. ngOnDestroy(): void {
  84. this.destroy$.next();
  85. this.destroy$.complete();
  86. }
  87. }

Table表格 - 图22

拖拽排序

使用自定义元素,我们可以集成 cdk drag-drop 来实现拖拽排序。

  1. import { moveItemInArray, CdkDragDrop } from '@angular/cdk/drag-drop';
  2. import { Component } from '@angular/core';
  3. @Component({
  4. selector: 'nz-demo-table-drag-sorting',
  5. template: `
  6. <nz-table [nzData]="listOfData" [nzFrontPagination]="false" [nzShowPagination]="false">
  7. <thead>
  8. <tr>
  9. <th>Name</th>
  10. <th>Age</th>
  11. <th>Address</th>
  12. </tr>
  13. </thead>
  14. <tbody cdkDropList (cdkDropListDropped)="drop($event)">
  15. <tr *ngFor="let data of listOfData" cdkDrag>
  16. <td>{{ data.name }}</td>
  17. <td>{{ data.age }}</td>
  18. <td>{{ data.address }}</td>
  19. </tr>
  20. </tbody>
  21. </nz-table>
  22. `,
  23. styles: [
  24. `
  25. ::ng-deep .cdk-drag-preview {
  26. display: table;
  27. }
  28. ::ng-deep .cdk-drag-placeholder {
  29. opacity: 0;
  30. }
  31. `
  32. ]
  33. })
  34. export class NzDemoTableDragSortingComponent {
  35. listOfData = [
  36. {
  37. key: '1',
  38. name: 'John Brown',
  39. age: 32,
  40. address: 'New York No. 1 Lake Park'
  41. },
  42. {
  43. key: '2',
  44. name: 'Jim Green',
  45. age: 42,
  46. address: 'London No. 1 Lake Park'
  47. },
  48. {
  49. key: '3',
  50. name: 'Joe Black',
  51. age: 32,
  52. address: 'Sidney No. 1 Lake Park'
  53. }
  54. ];
  55. drop(event: CdkDragDrop<string[]>): void {
  56. moveItemInArray(this.listOfData, event.previousIndex, event.currentIndex);
  57. }
  58. }

Table表格 - 图23

模板用法

模板模式,显示内容仅由模板内容控制,不再需要向 nzData 传入数据,完全像普通 table 一样使用,使用 ant-design 的样式。

  1. import { Component } from '@angular/core';
  2. @Component({
  3. selector: 'nz-demo-table-template',
  4. template: `
  5. <nz-table nzTemplateMode>
  6. <thead>
  7. <tr>
  8. <th>Company</th>
  9. <th>Contact</th>
  10. <th>Country</th>
  11. </tr>
  12. </thead>
  13. <tbody>
  14. <tr>
  15. <td>Alfreds Futterkiste</td>
  16. <td>Maria Anders</td>
  17. <td>Germany</td>
  18. </tr>
  19. <tr>
  20. <td>Centro comercial Moctezuma</td>
  21. <td>Francisco Chang</td>
  22. <td>Mexico</td>
  23. </tr>
  24. <tr>
  25. <td>Ernst Handel</td>
  26. <td>Roland Mendel</td>
  27. <td>Austria</td>
  28. </tr>
  29. <tr>
  30. <td>Island Trading</td>
  31. <td>Helen Bennett</td>
  32. <td>UK</td>
  33. </tr>
  34. <tr>
  35. <td>Laughing Bacchus Winecellars</td>
  36. <td>Yoshi Tannamuri</td>
  37. <td>Canada</td>
  38. </tr>
  39. <tr>
  40. <td>Magazzini Alimentari Riuniti</td>
  41. <td>Giovanni Rovelli</td>
  42. <td>Italy</td>
  43. </tr>
  44. </tbody>
  45. </nz-table>
  46. `
  47. })
  48. export class NzDemoTableTemplateComponent {}

Table表格 - 图24

动态控制表格属性

选择不同配置组合查看效果。

  1. import { Component, OnInit } from '@angular/core';
  2. @Component({
  3. selector: 'nz-demo-table-dynamic-settings',
  4. template: `
  5. <div class="components-table-demo-control-bar">
  6. <form nz-form nzLayout="inline">
  7. <nz-form-item>
  8. <nz-form-label><label>Bordered</label></nz-form-label>
  9. <nz-form-control><nz-switch [(ngModel)]="bordered" name="bordered"></nz-switch></nz-form-control>
  10. </nz-form-item>
  11. <nz-form-item>
  12. <nz-form-label><label>Loading</label></nz-form-label>
  13. <nz-form-control><nz-switch [(ngModel)]="loading" name="loading"></nz-switch></nz-form-control>
  14. </nz-form-item>
  15. <nz-form-item>
  16. <nz-form-label><label>Pagination</label></nz-form-label>
  17. <nz-form-control><nz-switch [(ngModel)]="pagination" name="pagination"></nz-switch></nz-form-control>
  18. </nz-form-item>
  19. <nz-form-item>
  20. <nz-form-label><label>PageSizeChanger</label></nz-form-label>
  21. <nz-form-control><nz-switch [(ngModel)]="sizeChanger" name="sizeChanger"></nz-switch></nz-form-control>
  22. </nz-form-item>
  23. <nz-form-item>
  24. <nz-form-label><label>Title</label></nz-form-label>
  25. <nz-form-control><nz-switch [(ngModel)]="title" name="title"></nz-switch></nz-form-control>
  26. </nz-form-item>
  27. <nz-form-item>
  28. <nz-form-label><label>Column Header</label></nz-form-label>
  29. <nz-form-control><nz-switch [(ngModel)]="header" name="header"></nz-switch></nz-form-control>
  30. </nz-form-item>
  31. <nz-form-item>
  32. <nz-form-label><label>Footer</label></nz-form-label>
  33. <nz-form-control><nz-switch [(ngModel)]="footer" name="footer"></nz-switch></nz-form-control>
  34. </nz-form-item>
  35. <nz-form-item>
  36. <nz-form-label><label>Expandable</label></nz-form-label>
  37. <nz-form-control><nz-switch [(ngModel)]="expandable" name="expandable"></nz-switch></nz-form-control>
  38. </nz-form-item>
  39. <nz-form-item>
  40. <nz-form-label><label>Checkbox</label></nz-form-label>
  41. <nz-form-control><nz-switch [(ngModel)]="checkbox" name="checkbox"></nz-switch></nz-form-control>
  42. </nz-form-item>
  43. <nz-form-item>
  44. <nz-form-label><label>Fixed Header</label></nz-form-label>
  45. <nz-form-control><nz-switch [(ngModel)]="fixHeader" name="fixHeader"></nz-switch></nz-form-control>
  46. </nz-form-item>
  47. <nz-form-item>
  48. <nz-form-label><label>No Result</label></nz-form-label>
  49. <nz-form-control
  50. ><nz-switch [(ngModel)]="noResult" (ngModelChange)="noResultChange($event)" name="noResult"></nz-switch
  51. ></nz-form-control>
  52. </nz-form-item>
  53. <nz-form-item>
  54. <nz-form-label><label>Simple Pagination</label></nz-form-label>
  55. <nz-form-control><nz-switch [(ngModel)]="simple" name="simple"></nz-switch></nz-form-control>
  56. </nz-form-item>
  57. <nz-form-item>
  58. <nz-form-label><label>Size</label></nz-form-label>
  59. <nz-form-control>
  60. <nz-radio-group [(ngModel)]="size" name="size">
  61. <label nz-radio-button nzValue="default">Default</label>
  62. <label nz-radio-button nzValue="middle">Middle</label>
  63. <label nz-radio-button nzValue="small">Small</label>
  64. </nz-radio-group>
  65. </nz-form-control>
  66. </nz-form-item>
  67. <nz-form-item>
  68. <nz-form-label><label>Pagination Position</label></nz-form-label>
  69. <nz-form-control>
  70. <nz-radio-group [(ngModel)]="position" name="position">
  71. <label nz-radio-button nzValue="top">Top</label>
  72. <label nz-radio-button nzValue="bottom">Bottom</label>
  73. <label nz-radio-button nzValue="both">Both</label>
  74. </nz-radio-group>
  75. </nz-form-control>
  76. </nz-form-item>
  77. </form>
  78. </div>
  79. <nz-table
  80. #dynamicTable
  81. [nzScroll]="fixHeader ? { y: '240px' } : null"
  82. [nzData]="listOfData"
  83. [nzBordered]="bordered"
  84. [nzSimple]="simple"
  85. [nzLoading]="loading"
  86. [nzPaginationPosition]="position"
  87. [nzShowSizeChanger]="sizeChanger"
  88. [nzFrontPagination]="pagination"
  89. [nzShowPagination]="pagination"
  90. [nzFooter]="footer ? 'Here is Footer' : null"
  91. [nzTitle]="title ? 'Here is Title' : null"
  92. [nzSize]="size"
  93. (nzCurrentPageDataChange)="currentPageDataChange($event)"
  94. >
  95. <thead>
  96. <tr *ngIf="header">
  97. <th nzWidth="50px" nzShowExpand *ngIf="expandable"></th>
  98. <th
  99. nzWidth="62px"
  100. nzShowCheckbox
  101. *ngIf="checkbox"
  102. [(nzChecked)]="allChecked"
  103. [nzIndeterminate]="indeterminate"
  104. (nzCheckedChange)="checkAll($event)"
  105. ></th>
  106. <th nzWidth="150px">Name</th>
  107. <th nzWidth="70px">Age</th>
  108. <th>Address</th>
  109. <th nzWidth="260px">Action</th>
  110. </tr>
  111. </thead>
  112. <tbody>
  113. <ng-template ngFor let-data [ngForOf]="dynamicTable.data">
  114. <tr>
  115. <td nzShowExpand *ngIf="expandable" [(nzExpand)]="data.expand"></td>
  116. <td nzShowCheckbox *ngIf="checkbox" [(nzChecked)]="data.checked" (nzCheckedChange)="refreshStatus()"></td>
  117. <td>{{ data.name }}</td>
  118. <td>{{ data.age }}</td>
  119. <td>{{ data.address }}</td>
  120. <td>
  121. <a href="#">Action 一 {{ data.name }}</a>
  122. <nz-divider nzType="vertical"></nz-divider>
  123. <a href="#">Delete</a>
  124. </td>
  125. </tr>
  126. <tr [nzExpand]="data.expand && expandable">
  127. <td></td>
  128. <td [attr.colspan]="checkbox ? 5 : 4">{{ data.description }}</td>
  129. </tr>
  130. </ng-template>
  131. </tbody>
  132. </nz-table>
  133. `,
  134. styles: [
  135. `
  136. .components-table-demo-control-bar {
  137. margin-bottom: 12px;
  138. }
  139. .nz-form-item {
  140. margin-right: 16px;
  141. margin-bottom: 8px;
  142. }
  143. `
  144. ]
  145. })
  146. export class NzDemoTableDynamicSettingsComponent implements OnInit {
  147. listOfData: any[] = [];
  148. bordered = false;
  149. loading = false;
  150. sizeChanger = false;
  151. pagination = true;
  152. header = true;
  153. title = true;
  154. footer = true;
  155. fixHeader = false;
  156. size = 'small';
  157. expandable = true;
  158. checkbox = true;
  159. allChecked = false;
  160. indeterminate = false;
  161. displayData: any[] = [];
  162. simple = false;
  163. noResult = false;
  164. position = 'bottom';
  165. currentPageDataChange(
  166. $event: Array<{
  167. name: string;
  168. age: number;
  169. address: string;
  170. checked: boolean;
  171. expand: boolean;
  172. description: string;
  173. }>
  174. ): void {
  175. this.displayData = $event;
  176. this.refreshStatus();
  177. }
  178. refreshStatus(): void {
  179. const validData = this.displayData.filter(value => !value.disabled);
  180. const allChecked = validData.length > 0 && validData.every(value => value.checked === true);
  181. const allUnChecked = validData.every(value => !value.checked);
  182. this.allChecked = allChecked;
  183. this.indeterminate = !allChecked && !allUnChecked;
  184. }
  185. checkAll(value: boolean): void {
  186. this.displayData.forEach(data => {
  187. if (!data.disabled) {
  188. data.checked = value;
  189. }
  190. });
  191. this.refreshStatus();
  192. }
  193. ngOnInit(): void {
  194. for (let i = 1; i <= 100; i++) {
  195. this.listOfData.push({
  196. name: 'John Brown',
  197. age: `${i}2`,
  198. address: `New York No. ${i} Lake Park`,
  199. description: `My name is John Brown, I am ${i}2 years old, living in New York No. ${i} Lake Park.`,
  200. checked: false,
  201. expand: false
  202. });
  203. }
  204. }
  205. noResultChange(status: boolean): void {
  206. this.listOfData = [];
  207. if (!status) {
  208. this.ngOnInit();
  209. }
  210. }
  211. }

API

单独引入此组件

想要了解更多关于单独引入组件的内容,可以在快速上手页面进行查看。

  1. import { NzTableModule } from 'ng-zorro-antd';

nz-tablecomponent

参数说明类型默认值
[nzData]数据数组any[]-
[nzFrontPagination]是否在前端对数据进行分页,如果在服务器分页数据或者需要在前端显示全部数据时传入 falsebooleantrue
[nzTotal]当前总数据,在服务器渲染时需要传入number-
[nzPageIndex]当前页码,可双向绑定number-
[nzPageSize]每页展示多少数据,可双向绑定number-
[nzShowPagination]是否显示分页器booleantrue
[nzPaginationPosition]指定分页显示的位置'top'|'bottom'|'both'bottom
[nzBordered]是否展示外边框和列边框booleanfalse
[nzWidthConfig]表头分组时指定每列宽度,与 thnzWidth 不可混用string[]-
[nzSize]正常或迷你类型'middle'|'small'|'default''default'
[nzLoading]页面是否加载中booleanfalse
[nzLoadingIndicator]加载指示符TemplateRef<void>-
[nzLoadingDelay]延迟显示加载效果的时间(防止闪烁)number0
[nzScroll]横向或纵向支持滚动,也可用于指定滚动区域的宽高度:{ x: "300px", y: "300px" }object-
[nzTitle]表格标题string|TemplateRef<void>-
[nzFooter]表格尾部string|TemplateRef<void>-
[nzNoResult]无数据时显示内容string|TemplateRef<void>-
[nzPageSizeOptions]页数选择器可选值number[][ 10, 20, 30, 40, 50 ]
[nzShowQuickJumper]是否可以快速跳转至某页booleanfalse
[nzShowSizeChanger]是否可以改变 nzPageSizebooleanfalse
[nzShowTotal]用于显示数据总量和当前数据范围,用法参照 Pagination 组件TemplateRef<{ $implicit: number, range: [ number, number ] }>-
[nzItemRender]用于自定义页码的结构,用法参照 Pagination 组件TemplateRef<{ $implicit: 'page'|'prev'|'next', page: number }>-
[nzHideOnSinglePage]只有一页时是否隐藏分页器booleanfalse
[nzSimple]当添加该属性时,显示为简单分页boolean-
[nzVirtualScroll]是否启用虚拟滚动模式,与 [nzScroll] 配合使用booleanfalse
[nzVirtualItemSize]虚拟滚动时每一列的高度,与 cdk itemSize 相同number0
[nzVirtualMaxBufferPx]缓冲区最大像素高度,与 cdk maxBufferPx 相同number200
[nzVirtualMinBufferPx]缓冲区最小像素高度,低于该值时将加载新结构,与 cdk minBufferPx 相同number100
(nzPageIndexChange)当前页码改变时的回调函数EventEmitter<number>-
(nzPageSizeChange)页数改变时的回调函数EventEmitter<number>-
(nzCurrentPageDataChange)当前页面展示数据改变的回调函数EventEmitter<any[]>-

th

勾选属性

参数说明类型默认值
[nzShowCheckbox]是否添加checkboxboolean-
[nzDisabled]checkbox 是否禁用boolean-
[nzIndeterminate]checkbox indeterminate 状态boolean-
[nzChecked]checkbox 是否被选中,可双向绑定boolean-
(nzCheckedChange)选中的回调EventEmitter<boolean>-

下拉选择属性

参数说明类型默认值
[nzShowRowSelection]是否显示下拉选择boolean-
[nzSelections]下拉选择的内容 text 及回调函数 onSelectArray<{ text: string, onSelect: any }>-

排序属性

参数说明类型默认值
[nzShowSort]是否显示排序boolean-
[nzSortKey]排序key,非受控模式使用,与 theadnzSortChange 配合使用string-
[nzSort]当前排序状态,受控模式使用,可双向绑定'descend'|'ascend'|nullnull
(nzSortChange)排序状态改变回调,受控模式使用EventEmitter<'descend'|'ascend'|null>-

过滤属性

参数说明类型默认值
[nzShowFilter]是否显示过滤boolean-
[nzFilters]过滤器内容, 显示数据 text,回调函数传出 value,设置 byDefault 以默认应用过滤规则Array<{ text: string; value: any; byDefault?: boolean }>-
[nzFilterMultiple]是否为多选过滤器booleantrue
(nzFilterChange)过滤器内容选择的 value 数据回调EventEmitter<any[]|any>-

样式属性

参数说明类型默认值
[nzWidth]指定该列宽度,表头未分组时可用string-
[nzLeft]左侧距离,用于固定左侧列string-
[nzRight]右侧距离,用于固定右侧列string-
[nzAlign]设置列内容的对齐方式'left'|'right'|'center'-

其他

参数说明类型默认值
[nzExpand]当前列是否包含展开按钮boolean-

td

勾选属性

参数说明类型默认值
[nzShowCheckbox]是否添加checkboxboolean-
[nzDisabled]checkbox 是否禁用boolean-
[nzIndeterminate]checkbox indeterminate 状态boolean-
[nzChecked]checkbox 是否被选中,可双向绑定boolean-
(nzCheckedChange)选中的回调EventEmitter<boolean>-

展开属性

参数说明类型默认值
[nzShowExpand]是否显示展开按钮boolean-
[nzExpand]当前展开按钮状态,可双向绑定boolean-
(nzExpandChange)当前展开按钮状态改变回调函数EventEmitter<boolean>-

样式属性

参数说明类型默认值
[nzLeft]左侧距离,用于固定左侧列string-
[nzRight]右侧距离,用于固定右侧列string-
[nzAlign]设置列内容的对齐方式'left'|'right'|'center'-

其他

参数说明类型默认值
[nzIndentSize]展示树形数据时,每层缩进的宽度,以 px 为单位number-

thead

参数说明类型默认值
[nzSingleSort]是否单列排序模式,非受控排序下使用booleanfalse
(nzSortChange)排序改变时的回调函数,需要与 th 上的 nzSortKey 同时使用,非受控排序下使用EventEmitter<{ nzSortKey: string, value: 'descend'|'ascend'|null }>-

tr

参数说明类型默认值
[nzExpand]当前列是否展开,与 td 上的 nzExpand 属性配合使用boolean-

[nz-virtual-scroll]directive

虚拟滚动时配合 ng-template 使用, 格式为: TemplateRef<{ $implicit: any, index: number }>.

注意

按照 Angular 的设计,当需要对 nzData 中的数据进行增删时需要使用以下操作,使用 push 或者 splice 修改 nzData 的数据不会生效

  1. // 增加数据
  2. this.dataSet = [ ...this.dataSet, {
  3. key : `${this.i}`,
  4. name : `Edward King ${this.i}`,
  5. age : '32',
  6. address: `London, Park Lane no. ${this.i}`
  7. }];
  8. // 删除数据
  9. this.dataSet = this.dataSet.filter(d => d.key !== i);