Table表格

展示行列数据。

何时使用

  • 当有大量结构化的数据需要展现时;
  • 当需要对数据进行排序、搜索、分页、自定义操作等复杂行为时。
  1. import { NzTableModule } from 'ng-zorro-antd/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表格 - 图2

Table表格 - 图3

基本用法

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

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

Table表格 - 图4

选择和操作

第一列是联动的选择框,增加 [nzChecked] 后,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="send-request">
  13. <button nz-button nzType="primary" [disabled]="setOfCheckedId.size === 0" [nzLoading]="loading" (click)="sendRequest()">
  14. Send Request
  15. </button>
  16. <span>Selected {{ setOfCheckedId.size }} items</span>
  17. </div>
  18. <nz-table
  19. #rowSelectionTable
  20. nzShowPagination
  21. nzShowSizeChanger
  22. [nzData]="listOfData"
  23. (nzCurrentPageDataChange)="onCurrentPageDataChange($event)"
  24. >
  25. <thead>
  26. <tr>
  27. <th [nzChecked]="checked" [nzIndeterminate]="indeterminate" (nzCheckedChange)="onAllChecked($event)"></th>
  28. <th>Name</th>
  29. <th>Age</th>
  30. <th>Address</th>
  31. </tr>
  32. </thead>
  33. <tbody>
  34. <tr *ngFor="let data of rowSelectionTable.data">
  35. <td
  36. [nzChecked]="setOfCheckedId.has(data.id)"
  37. [nzDisabled]="data.disabled"
  38. (nzCheckedChange)="onItemChecked(data.id, $event)"
  39. ></td>
  40. <td>{{ data.name }}</td>
  41. <td>{{ data.age }}</td>
  42. <td>{{ data.address }}</td>
  43. </tr>
  44. </tbody>
  45. </nz-table>
  46. `,
  47. styles: [
  48. `
  49. .send-request {
  50. margin-bottom: 16px;
  51. }
  52. .send-request span {
  53. margin-left: 8px;
  54. }
  55. `
  56. ]
  57. })
  58. export class NzDemoTableRowSelectionAndOperationComponent implements OnInit {
  59. checked = false;
  60. loading = false;
  61. indeterminate = false;
  62. listOfData: Data[] = [];
  63. listOfCurrentPageData: Data[] = [];
  64. setOfCheckedId = new Set<number>();
  65. updateCheckedSet(id: number, checked: boolean): void {
  66. if (checked) {
  67. this.setOfCheckedId.add(id);
  68. } else {
  69. this.setOfCheckedId.delete(id);
  70. }
  71. }
  72. onCurrentPageDataChange(listOfCurrentPageData: Data[]): void {
  73. this.listOfCurrentPageData = listOfCurrentPageData;
  74. this.refreshCheckedStatus();
  75. }
  76. refreshCheckedStatus(): void {
  77. const listOfEnabledData = this.listOfCurrentPageData.filter(({ disabled }) => !disabled);
  78. this.checked = listOfEnabledData.every(({ id }) => this.setOfCheckedId.has(id));
  79. this.indeterminate = listOfEnabledData.some(({ id }) => this.setOfCheckedId.has(id)) && !this.checked;
  80. }
  81. onItemChecked(id: number, checked: boolean): void {
  82. this.updateCheckedSet(id, checked);
  83. this.refreshCheckedStatus();
  84. }
  85. onAllChecked(checked: boolean): void {
  86. this.listOfCurrentPageData.filter(({ disabled }) => !disabled).forEach(({ id }) => this.updateCheckedSet(id, checked));
  87. this.refreshCheckedStatus();
  88. }
  89. sendRequest(): void {
  90. this.loading = true;
  91. const requestData = this.listOfData.filter(data => this.setOfCheckedId.has(data.id));
  92. console.log(requestData);
  93. setTimeout(() => {
  94. this.setOfCheckedId.clear();
  95. this.refreshCheckedStatus();
  96. this.loading = false;
  97. }, 1000);
  98. }
  99. ngOnInit(): void {
  100. this.listOfData = new Array(100).fill(0).map((_, index) => {
  101. return {
  102. id: index,
  103. name: `Edward King ${index}`,
  104. age: 32,
  105. address: `London, Park Lane no. ${index}`,
  106. disabled: index % 2 === 0
  107. };
  108. });
  109. }
  110. }

Table表格 - 图5

自定义选择项

通过 nzSelections 自定义选择项.

  1. import { Component, OnInit } from '@angular/core';
  2. interface ItemData {
  3. id: number;
  4. name: string;
  5. age: number;
  6. address: string;
  7. }
  8. @Component({
  9. selector: 'nz-demo-table-row-selection-custom',
  10. template: `
  11. <nz-table #rowSelectionTable nzShowSizeChanger [nzData]="listOfData" (nzCurrentPageDataChange)="onCurrentPageDataChange($event)">
  12. <thead>
  13. <tr>
  14. <th
  15. [nzSelections]="listOfSelection"
  16. [(nzChecked)]="checked"
  17. [nzIndeterminate]="indeterminate"
  18. (nzCheckedChange)="onAllChecked($event)"
  19. ></th>
  20. <th>Name</th>
  21. <th>Age</th>
  22. <th>Address</th>
  23. </tr>
  24. </thead>
  25. <tbody>
  26. <tr *ngFor="let data of rowSelectionTable.data">
  27. <td [nzChecked]="setOfCheckedId.has(data.id)" (nzCheckedChange)="onItemChecked(data.id, $event)"></td>
  28. <td>{{ data.name }}</td>
  29. <td>{{ data.age }}</td>
  30. <td>{{ data.address }}</td>
  31. </tr>
  32. </tbody>
  33. </nz-table>
  34. `
  35. })
  36. export class NzDemoTableRowSelectionCustomComponent implements OnInit {
  37. listOfSelection = [
  38. {
  39. text: 'Select All Row',
  40. onSelect: () => {
  41. this.onAllChecked(true);
  42. }
  43. },
  44. {
  45. text: 'Select Odd Row',
  46. onSelect: () => {
  47. this.listOfCurrentPageData.forEach((data, index) => this.updateCheckedSet(data.id, index % 2 !== 0));
  48. this.refreshCheckedStatus();
  49. }
  50. },
  51. {
  52. text: 'Select Even Row',
  53. onSelect: () => {
  54. this.listOfCurrentPageData.forEach((data, index) => this.updateCheckedSet(data.id, index % 2 === 0));
  55. this.refreshCheckedStatus();
  56. }
  57. }
  58. ];
  59. checked = false;
  60. indeterminate = false;
  61. listOfCurrentPageData: ItemData[] = [];
  62. listOfData: ItemData[] = [];
  63. setOfCheckedId = new Set<number>();
  64. updateCheckedSet(id: number, checked: boolean): void {
  65. if (checked) {
  66. this.setOfCheckedId.add(id);
  67. } else {
  68. this.setOfCheckedId.delete(id);
  69. }
  70. }
  71. onItemChecked(id: number, checked: boolean): void {
  72. this.updateCheckedSet(id, checked);
  73. this.refreshCheckedStatus();
  74. }
  75. onAllChecked(value: boolean): void {
  76. this.listOfCurrentPageData.forEach(item => this.updateCheckedSet(item.id, value));
  77. this.refreshCheckedStatus();
  78. }
  79. onCurrentPageDataChange($event: ItemData[]): void {
  80. this.listOfCurrentPageData = $event;
  81. this.refreshCheckedStatus();
  82. }
  83. refreshCheckedStatus(): void {
  84. this.checked = this.listOfCurrentPageData.every(item => this.setOfCheckedId.has(item.id));
  85. this.indeterminate = this.listOfCurrentPageData.some(item => this.setOfCheckedId.has(item.id)) && !this.checked;
  86. }
  87. ngOnInit(): void {
  88. this.listOfData = new Array(200).fill(0).map((_, index) => {
  89. return {
  90. id: index,
  91. name: `Edward King ${index}`,
  92. age: 32,
  93. address: `London, Park Lane no. ${index}`
  94. };
  95. });
  96. }
  97. }

Table表格 - 图6

筛选和排序

筛选:对某一列数据进行筛选,通过指定 [nzFilters] 属性来指定筛选菜单,[nzFilterFn] 指定筛选函数,[nzFilterMultiple] 用于指定多选和单选,通过设置 [nzFilters] 中的 { byDefault: true } 属性来默认启用一个筛选器。

排序:对某一列数据进行排序,通过指定 [nzSortOrder] 来指定默认排序顺序,[nzSortFn] 指定排序函数 [nzSortDirections] 改变每列可用的排序方式。

  1. import { Component } from '@angular/core';
  2. import { NzTableFilterFn, NzTableFilterList, NzTableSortFn, NzTableSortOrder } from 'ng-zorro-antd/table';
  3. interface DataItem {
  4. name: string;
  5. age: number;
  6. address: string;
  7. }
  8. interface ColumnItem {
  9. name: string;
  10. sortOrder: NzTableSortOrder | null;
  11. sortFn: NzTableSortFn | null;
  12. listOfFilter: NzTableFilterList;
  13. filterFn: NzTableFilterFn | null;
  14. filterMultiple: boolean;
  15. sortDirections: NzTableSortOrder[];
  16. }
  17. @Component({
  18. selector: 'nz-demo-table-sort-filter',
  19. template: `
  20. <nz-table #filterTable [nzData]="listOfData" nzTableLayout="fixed">
  21. <thead>
  22. <tr>
  23. <th
  24. *ngFor="let column of listOfColumns"
  25. [nzSortOrder]="column.sortOrder"
  26. [nzSortFn]="column.sortFn"
  27. [nzSortDirections]="column.sortDirections"
  28. [nzFilterMultiple]="column.filterMultiple"
  29. [nzFilters]="column.listOfFilter"
  30. [nzFilterFn]="column.filterFn"
  31. >
  32. {{ column.name }}
  33. </th>
  34. </tr>
  35. </thead>
  36. <tbody>
  37. <tr *ngFor="let data of filterTable.data">
  38. <td>{{ data.name }}</td>
  39. <td>{{ data.age }}</td>
  40. <td>{{ data.address }}</td>
  41. </tr>
  42. </tbody>
  43. </nz-table>
  44. `
  45. })
  46. export class NzDemoTableSortFilterComponent {
  47. listOfColumns: ColumnItem[] = [
  48. {
  49. name: 'Name',
  50. sortOrder: null,
  51. sortFn: (a: DataItem, b: DataItem) => a.name.localeCompare(b.name),
  52. sortDirections: ['ascend', 'descend', null],
  53. filterMultiple: true,
  54. listOfFilter: [
  55. { text: 'Joe', value: 'Joe' },
  56. { text: 'Jim', value: 'Jim', byDefault: true }
  57. ],
  58. filterFn: (list: string[], item: DataItem) => list.some(name => item.name.indexOf(name) !== -1)
  59. },
  60. {
  61. name: 'Age',
  62. sortOrder: 'descend',
  63. sortFn: (a: DataItem, b: DataItem) => a.age - b.age,
  64. sortDirections: ['descend', null],
  65. listOfFilter: [],
  66. filterFn: null,
  67. filterMultiple: true
  68. },
  69. {
  70. name: 'Address',
  71. sortOrder: null,
  72. sortDirections: ['ascend', 'descend', null],
  73. sortFn: (a: DataItem, b: DataItem) => a.address.length - b.address.length,
  74. filterMultiple: false,
  75. listOfFilter: [
  76. { text: 'London', value: 'London' },
  77. { text: 'Sidney', value: 'Sidney' }
  78. ],
  79. filterFn: (address: string, item: DataItem) => item.address.indexOf(address) !== -1
  80. }
  81. ];
  82. listOfData: DataItem[] = [
  83. {
  84. name: 'John Brown',
  85. age: 32,
  86. address: 'New York No. 1 Lake Park'
  87. },
  88. {
  89. name: 'Jim Green',
  90. age: 42,
  91. address: 'London No. 1 Lake Park'
  92. },
  93. {
  94. name: 'Joe Black',
  95. age: 32,
  96. address: 'Sidney No. 1 Lake Park'
  97. },
  98. {
  99. name: 'Jim Red',
  100. age: 32,
  101. address: 'London No. 2 Lake Park'
  102. }
  103. ];
  104. }

Table表格 - 图7

多列排序

使用 [nzSortPriority] 字段以配置多列排序优先级。通过 [nzSortFn] 配置排序逻辑。

  1. import { Component } from '@angular/core';
  2. interface DataItem {
  3. name: string;
  4. chinese: number;
  5. math: number;
  6. english: number;
  7. }
  8. @Component({
  9. selector: 'nz-demo-table-multiple-sorter',
  10. template: `
  11. <nz-table #sortTable [nzData]="listOfData" nzTableLayout="fixed">
  12. <thead>
  13. <tr>
  14. <th *ngFor="let column of listOfColumn" [nzSortFn]="column.compare" [nzSortPriority]="column.priority">{{ column.title }}</th>
  15. </tr>
  16. </thead>
  17. <tbody>
  18. <tr *ngFor="let data of sortTable.data">
  19. <td>{{ data.name }}</td>
  20. <td>{{ data.chinese }}</td>
  21. <td>{{ data.math }}</td>
  22. <td>{{ data.english }}</td>
  23. </tr>
  24. </tbody>
  25. </nz-table>
  26. `
  27. })
  28. export class NzDemoTableMultipleSorterComponent {
  29. listOfColumn = [
  30. {
  31. title: 'Name',
  32. compare: null,
  33. priority: false
  34. },
  35. {
  36. title: 'Chinese Score',
  37. compare: (a: DataItem, b: DataItem) => a.chinese - b.chinese,
  38. priority: 3
  39. },
  40. {
  41. title: 'Math Score',
  42. compare: (a: DataItem, b: DataItem) => a.math - b.math,
  43. priority: 2
  44. },
  45. {
  46. title: 'English Score',
  47. compare: (a: DataItem, b: DataItem) => a.english - b.english,
  48. priority: 1
  49. }
  50. ];
  51. listOfData: DataItem[] = [
  52. {
  53. name: 'John Brown',
  54. chinese: 98,
  55. math: 60,
  56. english: 70
  57. },
  58. {
  59. name: 'Jim Green',
  60. chinese: 98,
  61. math: 66,
  62. english: 89
  63. },
  64. {
  65. name: 'Joe Black',
  66. chinese: 98,
  67. math: 90,
  68. english: 70
  69. },
  70. {
  71. name: 'Jim Red',
  72. chinese: 88,
  73. math: 99,
  74. english: 89
  75. }
  76. ];
  77. }

Table表格 - 图8

可控的筛选和排序

修改 [nzSortOrder][nzFilters] 来指定当前列的排序与筛选状态。

  1. import { Component } from '@angular/core';
  2. import { NzTableFilterFn, NzTableFilterList, NzTableSortFn, NzTableSortOrder } from 'ng-zorro-antd/table';
  3. interface DataItem {
  4. name: string;
  5. age: number;
  6. address: string;
  7. }
  8. interface ColumnItem {
  9. name: string;
  10. sortOrder: NzTableSortOrder | null;
  11. sortFn: NzTableSortFn | null;
  12. listOfFilter: NzTableFilterList;
  13. filterFn: NzTableFilterFn | null;
  14. }
  15. @Component({
  16. selector: 'nz-demo-table-reset-filter',
  17. template: `
  18. <div class="table-operations">
  19. <button nz-button (click)="sortByAge()">Sort age</button>
  20. <button nz-button (click)="resetFilters()">Clear filters</button>
  21. <button nz-button (click)="resetSortAndFilters()">Clear filters and sorters</button>
  22. </div>
  23. <nz-table #filterTable [nzData]="listOfData" nzTableLayout="fixed">
  24. <thead>
  25. <tr>
  26. <th
  27. *ngFor="let column of listOfColumns; trackBy: trackByName"
  28. [(nzSortOrder)]="column.sortOrder"
  29. [nzSortFn]="column.sortFn"
  30. [nzFilters]="column.listOfFilter"
  31. [nzFilterFn]="column.filterFn"
  32. >
  33. {{ column.name }}
  34. </th>
  35. </tr>
  36. </thead>
  37. <tbody>
  38. <tr *ngFor="let data of filterTable.data">
  39. <td>{{ data.name }}</td>
  40. <td>{{ data.age }}</td>
  41. <td>{{ data.address }}</td>
  42. </tr>
  43. </tbody>
  44. </nz-table>
  45. `,
  46. styles: [
  47. `
  48. .table-operations {
  49. margin-bottom: 16px;
  50. }
  51. .table-operations > button {
  52. margin-right: 8px;
  53. }
  54. `
  55. ]
  56. })
  57. export class NzDemoTableResetFilterComponent {
  58. listOfColumns: ColumnItem[] = [
  59. {
  60. name: 'Name',
  61. sortOrder: null,
  62. sortFn: (a: DataItem, b: DataItem) => a.name.localeCompare(b.name),
  63. listOfFilter: [
  64. { text: 'Joe', value: 'Joe' },
  65. { text: 'Jim', value: 'Jim' }
  66. ],
  67. filterFn: (list: string[], item: DataItem) => list.some(name => item.name.indexOf(name) !== -1)
  68. },
  69. {
  70. name: 'Age',
  71. sortOrder: null,
  72. sortFn: (a: DataItem, b: DataItem) => a.age - b.age,
  73. listOfFilter: [],
  74. filterFn: null
  75. },
  76. {
  77. name: 'Address',
  78. sortFn: null,
  79. sortOrder: null,
  80. listOfFilter: [
  81. { text: 'London', value: 'London' },
  82. { text: 'Sidney', value: 'Sidney' }
  83. ],
  84. filterFn: (address: string, item: DataItem) => item.address.indexOf(address) !== -1
  85. }
  86. ];
  87. listOfData: DataItem[] = [
  88. {
  89. name: 'John Brown',
  90. age: 32,
  91. address: 'New York No. 1 Lake Park'
  92. },
  93. {
  94. name: 'Jim Green',
  95. age: 42,
  96. address: 'London No. 1 Lake Park'
  97. },
  98. {
  99. name: 'Joe Black',
  100. age: 32,
  101. address: 'Sidney No. 1 Lake Park'
  102. },
  103. {
  104. name: 'Jim Red',
  105. age: 32,
  106. address: 'London No. 2 Lake Park'
  107. }
  108. ];
  109. trackByName(_: number, item: ColumnItem): string {
  110. return item.name;
  111. }
  112. sortByAge(): void {
  113. this.listOfColumns.forEach(item => {
  114. if (item.name === 'Age') {
  115. item.sortOrder = 'descend';
  116. } else {
  117. item.sortOrder = null;
  118. }
  119. });
  120. }
  121. resetFilters(): void {
  122. this.listOfColumns.forEach(item => {
  123. if (item.name === 'Name') {
  124. item.listOfFilter = [
  125. { text: 'Joe', value: 'Joe' },
  126. { text: 'Jim', value: 'Jim' }
  127. ];
  128. } else if (item.name === 'Address') {
  129. item.listOfFilter = [
  130. { text: 'London', value: 'London' },
  131. { text: 'Sidney', value: 'Sidney' }
  132. ];
  133. }
  134. });
  135. }
  136. resetSortAndFilters(): void {
  137. this.listOfColumns.forEach(item => {
  138. item.sortOrder = null;
  139. });
  140. this.resetFilters();
  141. }
  142. }

Table表格 - 图9

自定义筛选菜单

通过 <nz-filter-trigger> 组件定义自定义的列筛选功能,并实现一个搜索列的示例。

  1. import { Component } from '@angular/core';
  2. interface DataItem {
  3. name: string;
  4. age: number;
  5. address: string;
  6. }
  7. @Component({
  8. selector: 'nz-demo-table-custom-filter-panel',
  9. template: `
  10. <nz-table #nzTable [nzData]="listOfDisplayData" nzTableLayout="fixed">
  11. <thead>
  12. <tr>
  13. <th nzCustomFilter>
  14. Name
  15. <nz-filter-trigger [(nzVisible)]="visible" [nzActive]="searchValue.length > 0" [nzDropdownMenu]="menu">
  16. <i nz-icon nzType="search"></i>
  17. </nz-filter-trigger>
  18. </th>
  19. <th>Age</th>
  20. <th>Address</th>
  21. </tr>
  22. </thead>
  23. <tbody>
  24. <tr *ngFor="let data of nzTable.data">
  25. <td>{{ data.name }}</td>
  26. <td>{{ data.age }}</td>
  27. <td>{{ data.address }}</td>
  28. </tr>
  29. </tbody>
  30. </nz-table>
  31. <nz-dropdown-menu #menu="nzDropdownMenu">
  32. <div class="ant-table-filter-dropdown">
  33. <div class="search-box">
  34. <input type="text" nz-input placeholder="Search name" [(ngModel)]="searchValue" />
  35. <button nz-button nzSize="small" nzType="primary" (click)="search()" class="search-button">
  36. Search
  37. </button>
  38. <button nz-button nzSize="small" (click)="reset()">Reset</button>
  39. </div>
  40. </div>
  41. </nz-dropdown-menu>
  42. `,
  43. styles: [
  44. `
  45. .search-box {
  46. padding: 8px;
  47. }
  48. .search-box input {
  49. width: 188px;
  50. margin-bottom: 8px;
  51. display: block;
  52. }
  53. .search-box button {
  54. width: 90px;
  55. }
  56. .search-button {
  57. margin-right: 8px;
  58. }
  59. `
  60. ]
  61. })
  62. export class NzDemoTableCustomFilterPanelComponent {
  63. searchValue = '';
  64. visible = false;
  65. listOfData: DataItem[] = [
  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. search(): void {
  93. this.visible = false;
  94. this.listOfDisplayData = this.listOfData.filter((item: DataItem) => item.name.indexOf(this.searchValue) !== -1);
  95. }
  96. }

Table表格 - 图10

远程加载数据

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

  • 分页:使用 [nzFrontPagination]="false" 指定由服务端分页。
  • 排序:使用 [nzSortFn]="true" 指定由服务端排序,如果需要多列排序可使用 [nzSortPriority]="true"
  • 筛选:使用 [nzFilters] 来指定筛选项,使用 [nzFilterFn]="true" 指定由服务端筛选
  • 参数传输:通过 (nzQueryParams) 服务端需要的参数,数据结构为
  1. {
  2. pageIndex: number;
  3. pageSize: number;
  4. sort: Array<{ key: string; value: 'ascend' | 'descend' | null }>;
  5. filter: Array<{ key: string; value: any | any[] }>;
  6. }

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

  1. import { HttpClient, HttpParams } from '@angular/common/http';
  2. import { Component, Injectable, OnInit } from '@angular/core';
  3. import { NzTableQueryParams } from 'ng-zorro-antd/table';
  4. import { Observable } from 'rxjs';
  5. interface RandomUser {
  6. gender: string;
  7. email: string;
  8. name: {
  9. title: string;
  10. first: string;
  11. last: string;
  12. };
  13. }
  14. @Injectable({ providedIn: 'root' })
  15. export class RandomUserService {
  16. randomUserUrl = 'https://api.randomuser.me/';
  17. getUsers(
  18. pageIndex: number,
  19. pageSize: number,
  20. sortField: string | null,
  21. sortOrder: string | null,
  22. filters: Array<{ key: string; value: string[] }>
  23. ): Observable<{ results: RandomUser[] }> {
  24. let params = new HttpParams()
  25. .append('page', `${pageIndex}`)
  26. .append('results', `${pageSize}`)
  27. .append('sortField', `${sortField}`)
  28. .append('sortOrder', `${sortOrder}`);
  29. filters.forEach(filter => {
  30. filter.value.forEach(value => {
  31. params = params.append(filter.key, value);
  32. });
  33. });
  34. return this.http.get<{ results: RandomUser[] }>(`${this.randomUserUrl}`, { params });
  35. }
  36. constructor(private http: HttpClient) {}
  37. }
  38. @Component({
  39. selector: 'nz-demo-table-ajax',
  40. template: `
  41. <nz-table
  42. nzShowSizeChanger
  43. [nzData]="listOfRandomUser"
  44. [nzFrontPagination]="false"
  45. [nzLoading]="loading"
  46. [nzTotal]="total"
  47. [nzPageSize]="pageSize"
  48. [nzPageIndex]="pageIndex"
  49. (nzQueryParams)="onQueryParamsChange($event)"
  50. >
  51. <thead>
  52. <tr>
  53. <th nzColumnKey="name" [nzSortFn]="true">Name</th>
  54. <th nzColumnKey="gender" [nzFilters]="filterGender" [nzFilterFn]="true">Gender</th>
  55. <th nzColumnKey="email" [nzSortFn]="true">Email</th>
  56. </tr>
  57. </thead>
  58. <tbody>
  59. <tr *ngFor="let data of listOfRandomUser">
  60. <td>{{ data.name.first }} {{ data.name.last }}</td>
  61. <td>{{ data.gender }}</td>
  62. <td>{{ data.email }}</td>
  63. </tr>
  64. </tbody>
  65. </nz-table>
  66. `
  67. })
  68. export class NzDemoTableAjaxComponent implements OnInit {
  69. total = 1;
  70. listOfRandomUser: RandomUser[] = [];
  71. loading = true;
  72. pageSize = 10;
  73. pageIndex = 1;
  74. filterGender = [
  75. { text: 'male', value: 'male' },
  76. { text: 'female', value: 'female' }
  77. ];
  78. loadDataFromServer(
  79. pageIndex: number,
  80. pageSize: number,
  81. sortField: string | null,
  82. sortOrder: string | null,
  83. filter: Array<{ key: string; value: string[] }>
  84. ): void {
  85. this.loading = true;
  86. this.randomUserService.getUsers(pageIndex, pageSize, sortField, sortOrder, filter).subscribe(data => {
  87. this.loading = false;
  88. this.total = 200; // mock the total data here
  89. this.listOfRandomUser = data.results;
  90. });
  91. }
  92. onQueryParamsChange(params: NzTableQueryParams): void {
  93. console.log(params);
  94. const { pageSize, pageIndex, sort, filter } = params;
  95. const currentSort = sort.find(item => item.value !== null);
  96. const sortField = (currentSort && currentSort.key) || null;
  97. const sortOrder = (currentSort && currentSort.value) || null;
  98. this.loadDataFromServer(pageIndex, pageSize, sortField, sortOrder, filter);
  99. }
  100. constructor(private randomUserService: RandomUserService) {}
  101. ngOnInit(): void {
  102. this.loadDataFromServer(this.pageIndex, this.pageSize, null, null, []);
  103. }
  104. }

Table表格 - 图11

紧凑型

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

  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. name: 'John Brown',
  52. age: 32,
  53. address: 'New York No. 1 Lake Park'
  54. },
  55. {
  56. name: 'Jim Green',
  57. age: 42,
  58. address: 'London No. 1 Lake Park'
  59. },
  60. {
  61. name: 'Joe Black',
  62. age: 32,
  63. address: 'Sidney No. 1 Lake Park'
  64. }
  65. ];
  66. }

Table表格 - 图12

带边框

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

  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. <nz-table #outBordered nzOuterBordered nzFooter="Footer" nzTitle="Header" [nzData]="dataSet">
  22. <thead>
  23. <tr>
  24. <th>Name</th>
  25. <th>Age</th>
  26. <th>Address</th>
  27. </tr>
  28. </thead>
  29. <tbody>
  30. <tr *ngFor="let data of outBordered.data">
  31. <td>{{ data.name }}</td>
  32. <td>{{ data.age }}</td>
  33. <td>{{ data.address }}</td>
  34. </tr>
  35. </tbody>
  36. </nz-table>
  37. `
  38. })
  39. export class NzDemoTableBorderedComponent {
  40. dataSet = [
  41. {
  42. name: 'John Brown',
  43. age: 32,
  44. address: 'New York No. 1 Lake Park'
  45. },
  46. {
  47. name: 'Jim Green',
  48. age: 42,
  49. address: 'London No. 1 Lake Park'
  50. },
  51. {
  52. name: 'Joe Black',
  53. age: 32,
  54. address: 'Sidney No. 1 Lake Park'
  55. }
  56. ];
  57. }

Table表格 - 图13

可展开

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

  1. import { Component } from '@angular/core';
  2. @Component({
  3. selector: 'nz-demo-table-expand',
  4. template: `
  5. <nz-table #nzTable [nzData]="listOfData" nzTableLayout="fixed">
  6. <thead>
  7. <tr>
  8. <th nzWidth="60px"></th>
  9. <th>Name</th>
  10. <th>Age</th>
  11. <th>Address</th>
  12. </tr>
  13. </thead>
  14. <tbody>
  15. <ng-container *ngFor="let data of nzTable.data">
  16. <tr>
  17. <td [nzExpand]="expandSet.has(data.id)" (nzExpandChange)="onExpandChange(data.id, $event)"></td>
  18. <td>{{ data.name }}</td>
  19. <td>{{ data.age }}</td>
  20. <td>{{ data.address }}</td>
  21. </tr>
  22. <tr [nzExpand]="expandSet.has(data.id)">
  23. <span>{{ data.description }}</span>
  24. </tr>
  25. </ng-container>
  26. </tbody>
  27. </nz-table>
  28. `
  29. })
  30. export class NzDemoTableExpandComponent {
  31. expandSet = new Set<number>();
  32. onExpandChange(id: number, checked: boolean): void {
  33. if (checked) {
  34. this.expandSet.add(id);
  35. } else {
  36. this.expandSet.delete(id);
  37. }
  38. }
  39. listOfData = [
  40. {
  41. id: 1,
  42. name: 'John Brown',
  43. age: 32,
  44. expand: false,
  45. address: 'New York No. 1 Lake Park',
  46. description: 'My name is John Brown, I am 32 years old, living in New York No. 1 Lake Park.'
  47. },
  48. {
  49. id: 2,
  50. name: 'Jim Green',
  51. age: 42,
  52. expand: false,
  53. address: 'London No. 1 Lake Park',
  54. description: 'My name is Jim Green, I am 42 years old, living in London No. 1 Lake Park.'
  55. },
  56. {
  57. id: 3,
  58. name: 'Joe Black',
  59. age: 32,
  60. expand: false,
  61. address: 'Sidney No. 1 Lake Park',
  62. description: 'My name is Joe Black, I am 32 years old, living in Sidney No. 1 Lake Park.'
  63. }
  64. ];
  65. }

Table表格 - 图14

表格行/列合并

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. <ng-container [ngSwitch]="i">
  18. <ng-container *ngSwitchCase="2">
  19. <td>{{ data.age }}</td>
  20. <td rowspan="2">{{ data.tel }}</td>
  21. <td>{{ data.phone }}</td>
  22. <td>{{ data.address }}</td>
  23. </ng-container>
  24. <ng-container *ngSwitchCase="3">
  25. <td>{{ data.age }}</td>
  26. <td>{{ data.phone }}</td>
  27. <td>{{ data.address }}</td>
  28. </ng-container>
  29. <ng-container *ngSwitchCase="4">
  30. <td colspan="5">{{ data.age }}</td>
  31. </ng-container>
  32. <ng-container *ngSwitchDefault>
  33. <td>{{ data.age }}</td>
  34. <td>{{ data.tel }}</td>
  35. <td>{{ data.phone }}</td>
  36. <td>{{ data.address }}</td>
  37. </ng-container>
  38. </ng-container>
  39. </tr>
  40. </tbody>
  41. </nz-table>
  42. `
  43. })
  44. export class NzDemoTableColspanRowspanComponent {
  45. listOfData = [
  46. {
  47. key: '1',
  48. name: 'John Brown',
  49. age: 32,
  50. tel: '0571-22098909',
  51. phone: 18889898989,
  52. address: 'New York No. 1 Lake Park'
  53. },
  54. {
  55. key: '2',
  56. name: 'Jim Green',
  57. tel: '0571-22098333',
  58. phone: 18889898888,
  59. age: 42,
  60. address: 'London No. 1 Lake Park'
  61. },
  62. {
  63. key: '3',
  64. name: 'Joe Black',
  65. age: 32,
  66. tel: '0575-22098909',
  67. phone: 18900010002,
  68. address: 'Sidney No. 1 Lake Park'
  69. },
  70. {
  71. key: '4',
  72. name: 'Jim Red',
  73. age: 18,
  74. tel: '0575-22098909',
  75. phone: 18900010002,
  76. address: 'London No. 2 Lake Park'
  77. },
  78. {
  79. key: '5',
  80. name: 'Jake White',
  81. age: 18,
  82. tel: '0575-22098909',
  83. phone: 18900010002,
  84. address: 'Dublin No. 2 Lake Park'
  85. }
  86. ];
  87. }

Table表格 - 图15

树形数据展示

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

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

Table表格 - 图16

固定表头

指定 [nzScroll]y 数值 方便一页内展示大量数据,每一列的宽度可以由 [nzWidth] 指定。

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

Table表格 - 图17

固定列

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

列头与内容不对齐或出现列重复,请指定固定列的宽度 [nzWidth]。如果指定 width 不生效或出现白色垂直空隙,请尝试建议留一列不设宽度以适应弹性布局,或者检查是否有超长连续字段破坏布局。 建议指定 nzScroll.x 为大于表格宽度的固定值或百分比。注意,且非固定列宽度之和不要超过 nzScroll.x。 注意:固定列通过 sticky 实现,IE 11 会降级成横向滚动。

  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 nzLeft>Full Name</th>
  9. <th nzLeft>Age</th>
  10. <th>Column 1</th>
  11. <th>Column 2</th>
  12. <th>Column 3</th>
  13. <th>Column 4</th>
  14. <th>Column 5</th>
  15. <th>Column 6</th>
  16. <th>Column 7</th>
  17. <th nzRight>Column 8</th>
  18. <th nzRight>Action</th>
  19. </tr>
  20. </thead>
  21. <tbody>
  22. <tr *ngFor="let data of columnTable.data">
  23. <td nzLeft>{{ data.name }}</td>
  24. <td nzLeft>{{ 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>{{ data.address }}</td>
  33. <td nzRight>
  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表格 - 图18

固定头和列

同时固定头和列,适合同时展示有大量数据和数据列。

列头与内容不对齐或出现列重复,请指定固定列的宽度 [nzWidth]。如果指定 width 不生效或出现白色垂直空隙,请尝试建议留一列不设宽度以适应弹性布局,或者检查是否有超长连续字段破坏布局。 建议指定 nzScroll.x 为大于表格宽度的固定值或百分比。注意,且非固定列宽度之和不要超过 nzScroll.x。 注意:固定列通过 sticky 实现,IE 11 会降级成横向滚动。

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

Table表格 - 图19

表头分组

固定列与分组表头联合使用。

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

Table表格 - 图20

可编辑单元格

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

为了获得更好的性能,NG-ZORRO 所有组件都运行在 OnPush 模式下,这意味着对 @Input() 数据的 mutate 将不会生效,请使用 immutable 方式操作数组或者对象。

开发者可以参照该例子根据自己需求自由定制表格的编辑功能。

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

Table表格 - 图21

可编辑行

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

为了获得更好的性能,NG-ZORRO 所有组件都运行在 OnPush 模式下,这意味着对 @Input() 数据的 mutate 将不会生效,请使用 immutable 方式操作数组或者对象。

开发者可以参照该例子根据自己需求自由定制表格的编辑功能。

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

Table表格 - 图22

嵌套子表格

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

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

Table表格 - 图23

虚拟滚动

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

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

Table表格 - 图24

拖拽排序

使用自定义元素,用户可以导入 @angular/cdk/drag-drop 来实现拖拽排序。

注意:需要手动导入 import {DragDropModule} from '@angular/cdk/drag-drop';

  1. import { CdkDragDrop, moveItemInArray } 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表格 - 图25

模板用法

模板模式,显示内容仅由模板内容控制,不再需要向 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表格 - 图26

折行显示

当有连续超长字符串时,可以使用 nzBreakWord 来折行显示

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

Table表格 - 图27

单元格自动省略

设置 nzTableLayout="fixed"nzEllipsis 可以让单元格内容根据宽度自动省略。

列头缩略暂不支持和排序筛选一起使用。

  1. import { Component, OnInit } from '@angular/core';
  2. @Component({
  3. selector: 'nz-demo-table-ellipsis',
  4. template: `
  5. <nz-table #fixedTable [nzData]="listOfData" nzTableLayout="fixed">
  6. <thead>
  7. <tr>
  8. <th>Full Name</th>
  9. <th>Age</th>
  10. <th>Column 1</th>
  11. <th>Column 2</th>
  12. <th nzEllipsis>Column ColumnColumn 3</th>
  13. <th>Column 4</th>
  14. </tr>
  15. </thead>
  16. <tbody>
  17. <tr *ngFor="let data of fixedTable.data">
  18. <td>{{ data.name }}</td>
  19. <td>{{ data.age }}</td>
  20. <td nzEllipsis>{{ data.address }}</td>
  21. <td nzEllipsis>{{ data.address }}</td>
  22. <td nzEllipsis>{{ data.address }}</td>
  23. <td nzEllipsis>{{ data.address }}</td>
  24. </tr>
  25. </tbody>
  26. </nz-table>
  27. `
  28. })
  29. export class NzDemoTableEllipsisComponent implements OnInit {
  30. listOfData: Array<{ name: string; age: number; address: string }> = [];
  31. ngOnInit(): void {
  32. for (let i = 0; i < 3; i++) {
  33. this.listOfData.push({
  34. name: `Edward King`,
  35. age: 32,
  36. address: `LondonLondonLondonLondonLondon`
  37. });
  38. }
  39. }
  40. }

Table表格 - 图28

动态控制表格属性

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

  1. import { Component, OnInit } from '@angular/core';
  2. import { FormBuilder, FormGroup } from '@angular/forms';
  3. import { NzTableLayout, NzTablePaginationPosition, NzTableSize } from 'ng-zorro-antd/table';
  4. interface ItemData {
  5. name: string;
  6. age: number | string;
  7. address: string;
  8. checked: boolean;
  9. expand: boolean;
  10. description: string;
  11. disabled?: boolean;
  12. }
  13. interface Setting {
  14. bordered: boolean;
  15. loading: boolean;
  16. pagination: boolean;
  17. sizeChanger: boolean;
  18. title: boolean;
  19. header: boolean;
  20. footer: boolean;
  21. expandable: boolean;
  22. checkbox: boolean;
  23. fixHeader: boolean;
  24. noResult: boolean;
  25. ellipsis: boolean;
  26. simple: boolean;
  27. size: NzTableSize;
  28. tableScroll: string;
  29. tableLayout: NzTableLayout;
  30. position: NzTablePaginationPosition;
  31. }
  32. @Component({
  33. selector: 'nz-demo-table-dynamic-settings',
  34. template: `
  35. <div class="components-table-demo-control-bar">
  36. <form nz-form nzLayout="inline" [formGroup]="settingForm!">
  37. <nz-form-item *ngFor="let switch of listOfSwitch">
  38. <nz-form-label> {{ switch.name }} </nz-form-label>
  39. <nz-form-control><nz-switch [formControlName]="switch.formControlName"></nz-switch></nz-form-control>
  40. </nz-form-item>
  41. <nz-form-item *ngFor="let radio of listOfRadio">
  42. <nz-form-label> {{ radio.name }} </nz-form-label>
  43. <nz-form-control>
  44. <nz-radio-group [formControlName]="radio.formControlName">
  45. <label *ngFor="let o of radio.listOfOption" nz-radio-button [nzValue]="o.value">{{ o.label }}</label>
  46. </nz-radio-group>
  47. </nz-form-control>
  48. </nz-form-item>
  49. </form>
  50. </div>
  51. <nz-table
  52. #dynamicTable
  53. [nzScroll]="{ x: scrollX, y: scrollY }"
  54. [nzData]="listOfData"
  55. [nzTableLayout]="settingValue.tableLayout"
  56. [nzBordered]="settingValue.bordered"
  57. [nzSimple]="settingValue.simple"
  58. [nzLoading]="settingValue.loading"
  59. [nzPaginationPosition]="settingValue.position"
  60. [nzShowSizeChanger]="settingValue.sizeChanger"
  61. [nzFrontPagination]="settingValue.pagination"
  62. [nzShowPagination]="settingValue.pagination"
  63. [nzFooter]="settingValue.footer ? 'Here is Footer' : null"
  64. [nzTitle]="settingValue.title ? 'Here is Title' : null"
  65. [nzSize]="settingValue.size"
  66. (nzCurrentPageDataChange)="currentPageDataChange($event)"
  67. >
  68. <thead>
  69. <tr *ngIf="settingValue.header">
  70. <th nzWidth="40px" *ngIf="settingValue.expandable" [nzLeft]="fixedColumn"></th>
  71. <th
  72. *ngIf="settingValue.checkbox"
  73. nzWidth="60px"
  74. [(nzChecked)]="allChecked"
  75. [nzLeft]="fixedColumn"
  76. [nzIndeterminate]="indeterminate"
  77. (nzCheckedChange)="checkAll($event)"
  78. ></th>
  79. <th [nzLeft]="fixedColumn">Name</th>
  80. <th>Age</th>
  81. <th>Address</th>
  82. <th [nzRight]="fixedColumn">Action</th>
  83. </tr>
  84. </thead>
  85. <tbody>
  86. <ng-container *ngFor="let data of dynamicTable.data">
  87. <tr>
  88. <td [nzLeft]="fixedColumn" *ngIf="settingValue.expandable" [(nzExpand)]="data.expand"></td>
  89. <td [nzLeft]="fixedColumn" *ngIf="settingValue.checkbox" [(nzChecked)]="data.checked" (nzCheckedChange)="refreshStatus()"></td>
  90. <td [nzLeft]="fixedColumn">{{ data.name }}</td>
  91. <td>{{ data.age }}</td>
  92. <td [nzEllipsis]="settingValue.ellipsis">{{ data.address }}</td>
  93. <td [nzRight]="fixedColumn" [nzEllipsis]="settingValue.ellipsis">
  94. <a href="#">Delete</a>
  95. <nz-divider nzType="vertical"></nz-divider>
  96. <a href="#">More action</a>
  97. </td>
  98. </tr>
  99. <tr *ngIf="settingValue.expandable" [nzExpand]="data.expand">
  100. <span> {{ data.description }}</span>
  101. </tr>
  102. </ng-container>
  103. </tbody>
  104. </nz-table>
  105. `,
  106. styles: [
  107. `
  108. form nz-form-item {
  109. margin-right: 16px;
  110. margin-bottom: 8px;
  111. }
  112. `
  113. ]
  114. })
  115. export class NzDemoTableDynamicSettingsComponent implements OnInit {
  116. settingForm?: FormGroup;
  117. listOfData: ItemData[] = [];
  118. displayData: ItemData[] = [];
  119. allChecked = false;
  120. indeterminate = false;
  121. fixedColumn = false;
  122. scrollX: string | null = null;
  123. scrollY: string | null = null;
  124. settingValue!: Setting;
  125. listOfSwitch = [
  126. { name: 'Bordered', formControlName: 'bordered' },
  127. { name: 'Loading', formControlName: 'loading' },
  128. { name: 'Pagination', formControlName: 'pagination' },
  129. { name: 'PageSizeChanger', formControlName: 'sizeChanger' },
  130. { name: 'Title', formControlName: 'title' },
  131. { name: 'Column Header', formControlName: 'header' },
  132. { name: 'Footer', formControlName: 'footer' },
  133. { name: 'Expandable', formControlName: 'expandable' },
  134. { name: 'Checkbox', formControlName: 'checkbox' },
  135. { name: 'Fixed Header', formControlName: 'fixHeader' },
  136. { name: 'No Result', formControlName: 'noResult' },
  137. { name: 'Ellipsis', formControlName: 'ellipsis' },
  138. { name: 'Simple Pagination', formControlName: 'simple' }
  139. ];
  140. listOfRadio = [
  141. {
  142. name: 'Size',
  143. formControlName: 'size',
  144. listOfOption: [
  145. { value: 'default', label: 'Default' },
  146. { value: 'middle', label: 'Middle' },
  147. { value: 'small', label: 'Small' }
  148. ]
  149. },
  150. {
  151. name: 'Table Scroll',
  152. formControlName: 'tableScroll',
  153. listOfOption: [
  154. { value: 'unset', label: 'Unset' },
  155. { value: 'scroll', label: 'Scroll' },
  156. { value: 'fixed', label: 'Fixed' }
  157. ]
  158. },
  159. {
  160. name: 'Table Layout',
  161. formControlName: 'tableLayout',
  162. listOfOption: [
  163. { value: 'auto', label: 'Auto' },
  164. { value: 'fixed', label: 'Fixed' }
  165. ]
  166. },
  167. {
  168. name: 'Pagination Position',
  169. formControlName: 'position',
  170. listOfOption: [
  171. { value: 'top', label: 'Top' },
  172. { value: 'bottom', label: 'Bottom' },
  173. { value: 'both', label: 'Both' }
  174. ]
  175. }
  176. ];
  177. currentPageDataChange($event: ItemData[]): void {
  178. this.displayData = $event;
  179. this.refreshStatus();
  180. }
  181. refreshStatus(): void {
  182. const validData = this.displayData.filter(value => !value.disabled);
  183. const allChecked = validData.length > 0 && validData.every(value => value.checked === true);
  184. const allUnChecked = validData.every(value => !value.checked);
  185. this.allChecked = allChecked;
  186. this.indeterminate = !allChecked && !allUnChecked;
  187. }
  188. checkAll(value: boolean): void {
  189. this.displayData.forEach(data => {
  190. if (!data.disabled) {
  191. data.checked = value;
  192. }
  193. });
  194. this.refreshStatus();
  195. }
  196. generateData(): ItemData[] {
  197. const data = [];
  198. for (let i = 1; i <= 100; i++) {
  199. data.push({
  200. name: 'John Brown',
  201. age: `${i}2`,
  202. address: `New York No. ${i} Lake Park`,
  203. description: `My name is John Brown, I am ${i}2 years old, living in New York No. ${i} Lake Park.`,
  204. checked: false,
  205. expand: false
  206. });
  207. }
  208. return data;
  209. }
  210. constructor(private formBuilder: FormBuilder) {}
  211. ngOnInit(): void {
  212. this.settingForm = this.formBuilder.group({
  213. bordered: false,
  214. loading: false,
  215. pagination: true,
  216. sizeChanger: false,
  217. title: true,
  218. header: true,
  219. footer: true,
  220. expandable: true,
  221. checkbox: true,
  222. fixHeader: false,
  223. noResult: false,
  224. ellipsis: false,
  225. simple: false,
  226. size: 'small',
  227. tableScroll: 'unset',
  228. tableLayout: 'auto',
  229. position: 'bottom'
  230. });
  231. this.settingValue = this.settingForm.value;
  232. this.settingForm.valueChanges.subscribe(value => (this.settingValue = value));
  233. this.settingForm.get('tableScroll')!.valueChanges.subscribe(scroll => {
  234. this.fixedColumn = scroll === 'fixed';
  235. this.scrollX = scroll === 'scroll' || scroll === 'fixed' ? '100vw' : null;
  236. });
  237. this.settingForm.get('fixHeader')!.valueChanges.subscribe(fixed => {
  238. this.scrollY = fixed ? '240px' : null;
  239. });
  240. this.settingForm.get('noResult')!.valueChanges.subscribe(empty => {
  241. if (empty) {
  242. this.listOfData = [];
  243. } else {
  244. this.listOfData = this.generateData();
  245. }
  246. });
  247. this.listOfData = this.generateData();
  248. }
  249. }

API

nz-tablecomponent

参数说明类型默认值全局配置
[nzData]数据数组any[]-
[nzFrontPagination]是否在前端对数据进行分页,如果在服务器分页数据或者需要在前端显示全部数据时传入 falsebooleantrue
[nzTotal]当前总数据,在服务器渲染时需要传入number-
[nzPageIndex]当前页码,可双向绑定number-
[nzPageSize]每页展示多少数据,可双向绑定number-
[nzShowPagination]是否显示分页器booleantrue
[nzPaginationPosition]指定分页显示的位置‘top’ | ‘bottom’ | ‘both’bottom
[nzBordered]是否展示外边框和列边框booleanfalse
[nzOutBordered]是否显示外边框booleanfalse-
[nzWidthConfig]表头分组时指定每列宽度,与 th[nzWidth] 不可混用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-
[nzVirtualItemSize]虚拟滚动时每一列的高度,与 cdk itemSize 相同number0
[nzVirtualMaxBufferPx]缓冲区最大像素高度,与 cdk maxBufferPx 相同number200
[nzVirtualMinBufferPx]缓冲区最小像素高度,低于该值时将加载新结构,与 cdk minBufferPx 相同number100
[nzVirtualForTrackBy]虚拟滚动数据 TrackByFunction 函数TrackByFunction<T>-
(nzPageIndexChange)当前页码改变时的回调函数EventEmitter<number>-
(nzPageSizeChange)页数改变时的回调函数EventEmitter<number>-
(nzCurrentPageDataChange)当前页面展示数据改变的回调函数EventEmitter<any[]>-
(nzQueryParams)当服务端分页、筛选、排序时,用于获得参数,具体见示例EventEmitter<NzTableQueryParams>-

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-
[nzSortFn]排序函数,前端排序使用一个函数(参考 Array.sort 的 compareFunction),服务端排序时传入 true((a: any, b: any, sortOrder?: string) =&gt; number)</td><td>boolean-
[nzSortDirections]支持的排序方式,取值为 ‘ascend’, ‘descend’, nullArray<’ascend’ | ‘descend’ | null>[‘ascend’, ‘descend’, null]
[nzSortOrder]当前排序状态,可双向绑定‘descend’ | ‘ascend’ | nullnull
(nzSortOrderChange)排序状态改变回调EventEmitter<’descend’ | ‘ascend’ | null>-

过滤属性

参数说明类型默认值
[nzShowFilter]是否显示过滤boolean-
[nzFilterFn]前端排序时,确定筛选的运行函数,服务端排序时,传入 true((value: any, data: any) =&gt; boolean;)</td><td>boolean-
[nzFilters]过滤器内容, 显示数据 text,回调函数传出 value,设置 byDefault 以默认应用过滤规则Array<{ text: string; value: any; byDefault?: boolean }>-
[nzFilterMultiple]是否为多选过滤器booleantrue
(nzFilterChange)过滤器内容选择的 value 数据回调EventEmitter<any[] | any>-

样式属性

参数说明类型默认值
[nzWidth]指定该列宽度,表头未分组时可用string-
[nzLeft]左侧距离,用于固定左侧列,当为 true 时自动计算,为 false 时停止固定string | booleanfalse
[nzRight]右侧距离,用于固定右侧列,当为 true 时自动计算,为 false 时停止固定string | booleanfalse
[nzAlign]设置列内容的对齐方式‘left’ | ‘right’ | ‘center’-
[nzBreakWord]是否折行显示booleanfalse
[nzEllipsis]超过宽度将自动省略,暂不支持和排序筛选一起使用。仅当表格布局将为 nzTableLayout=”fixed”时可用booleanfalse
[colSpan]每单元格中扩展列的数量numbernull
[rowSpan]每单元格中扩展行的数量numbernull

其他

参数说明类型默认值
[nzColumnKey]当前列的key,用于服务端筛选和排序使用string-

td

勾选属性

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

展开属性

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

样式属性

参数说明类型默认值
[nzLeft]左侧距离,用于固定左侧列,当为 true 时自动计算,为 false 时停止固定string | booleanfalse
[nzRight]右侧距离,用于固定右侧列,当为 true 时自动计算,为 false 时停止固定string | booleanfalse
[nzAlign]设置列内容的对齐方式‘left’ | ‘right’ | ‘center’-
[nzBreakWord]是否折行显示booleanfalse
[nzEllipsis]超过宽度将自动省略,暂不支持和排序筛选一起使用。仅当表格布局将为 nzTableLayout=”fixed”时可用booleanfalse

其他

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

tr

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

nz-filter-triggercomponent

用于自定义筛选功能

参数说明类型默认值
[nzDropdownMenu]Dropdown 下拉菜单组件NzDropdownMenuComponent-
[nzVisible]菜单是否显示,可双向绑定boolean-
[nzActive]是否激活选中图标效果booleanfalse
(nzVisibleChange)菜单显示状态改变时调用,参数为 nzVisibleEventEmitter<boolean>-

[nz-virtual-scroll]directive

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

注意

为了获得更好的性能,NG-ZORRO 所有组件都运行在 OnPush 模式下,这意味着对 @Input() 数据的 mutate 将不会生效,请使用 immutable 方式操作数组或者对象。

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

开发者也可以使用 immer 获得更好的操作体验