Skip to content

Commit bef12e6

Browse files
authored
feat(module:table): support nzFixed for nzSummary (#8642)
* feat(module:table): support `nzFixed` for `nzSummary` * feat(module:table): support `nzFixed` for `nzSummary`
1 parent 6fc1c78 commit bef12e6

19 files changed

+383
-210
lines changed

components/table/demo/summary.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@ title:
77

88
## zh-CN
99

10-
通过 `nzSummary` 设置总结栏。
10+
通过 `nzSummary` 设置总结栏。可以通过配置 `nzFixed` 属性使其固定。
1111

1212
## en-US
1313

14-
Set summary content by `nzSummary` prop.
14+
Set summary content by `nzSummary` prop. You can fixed it by set `nzFixed` prop.

components/table/demo/summary.ts

+50-10
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,13 @@ import { Component, OnInit } from '@angular/core';
1212
</tr>
1313
</thead>
1414
<tbody>
15-
<tr *ngFor="let data of middleTable.data">
16-
<td>{{ data.name }}</td>
17-
<td>{{ data.borrow }}</td>
18-
<td>{{ data.repayment }}</td>
19-
</tr>
20-
<tr></tr>
15+
@for (data of middleTable.data; track $index) {
16+
<tr>
17+
<td>{{ data.name }}</td>
18+
<td>{{ data.borrow }}</td>
19+
<td>{{ data.repayment }}</td>
20+
</tr>
21+
}
2122
</tbody>
2223
<tfoot nzSummary>
2324
<tr>
@@ -37,12 +38,42 @@ import { Component, OnInit } from '@angular/core';
3738
</tr>
3839
</tfoot>
3940
</nz-table>
41+
42+
<br />
43+
44+
<nz-table
45+
#fixedTable
46+
nzBordered
47+
[nzData]="fixedData"
48+
[nzShowPagination]="false"
49+
[nzScroll]="{ x: '1280px', y: '500px' }"
50+
>
51+
<thead>
52+
<tr>
53+
<th>Name</th>
54+
<th>Description</th>
55+
</tr>
56+
</thead>
57+
<tbody>
58+
@for (data of fixedTable.data; track data.key) {
59+
<tr>
60+
<td>{{ data.name }}</td>
61+
<td>{{ data.description }}</td>
62+
</tr>
63+
}
64+
</tbody>
65+
<tfoot nzSummary nzFixed>
66+
<tr>
67+
<td>Summary</td>
68+
<td>This is a summary content</td>
69+
</tr>
70+
</tfoot>
71+
</nz-table>
4072
`,
4173
styles: [
4274
`
43-
tfoot th,
44-
tfoot td {
45-
background: #fafafa;
75+
:host ::ng-deep tfoot.ant-table-summary {
76+
background-color: #fafafa !important;
4677
}
4778
`
4879
]
@@ -71,13 +102,22 @@ export class NzDemoTableSummaryComponent implements OnInit {
71102
}
72103
];
73104

74-
fixedData: Array<{ name: string; description: string }> = [];
105+
fixedData: Array<{ key: number; name: string; description: string }> = [];
75106
totalBorrow = 0;
76107
totalRepayment = 0;
108+
77109
ngOnInit(): void {
78110
this.data.forEach(({ borrow, repayment }) => {
79111
this.totalBorrow += borrow;
80112
this.totalRepayment += repayment;
81113
});
114+
115+
for (let i = 0; i < 20; i += 1) {
116+
this.fixedData.push({
117+
key: i,
118+
name: ['Light', 'Bamboo', 'Little'][i % 3],
119+
description: 'Everything that has a beginning, has an end.'
120+
});
121+
}
82122
}
83123
}

components/table/doc/index.en-US.md

+29-30
Large diffs are not rendered by default.

components/table/doc/index.zh-CN.md

+119-118
Large diffs are not rendered by default.

components/table/public-api.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ export * from './src/table/table-virtual-scroll.directive';
1616
export * from './src/table/table-fixed-row.component';
1717
export * from './src/table/tbody.component';
1818
export * from './src/table/thead.component';
19-
export * from './src/table/tfoot-summary.directive';
19+
export * from './src/table/tfoot-summary.component';
2020
export * from './src/table/tr.directive';
2121
export * from './src/table/tr-expand.directive';
2222
export * from './src/table/title-footer.component';

components/table/src/table-style.service.ts

+11-2
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,13 @@ import { map } from 'rxjs/operators';
1010
import { NzSafeAny } from 'ng-zorro-antd/core/types';
1111

1212
import { NzThMeasureDirective } from './cell/th-measure.directive';
13+
import { NzTableSummaryFixedType } from './table.types';
1314

1415
@Injectable()
1516
export class NzTableStyleService {
1617
theadTemplate$ = new ReplaySubject<TemplateRef<NzSafeAny>>(1);
18+
tfootTemplate$ = new ReplaySubject<TemplateRef<NzSafeAny>>(1);
19+
tfootFixed$ = new ReplaySubject<NzTableSummaryFixedType | null>(1);
1720
hasFixLeft$ = new ReplaySubject<boolean>(1);
1821
hasFixRight$ = new ReplaySubject<boolean>(1);
1922
hostWidth$ = new ReplaySubject<number>(1);
@@ -54,6 +57,14 @@ export class NzTableStyleService {
5457
this.theadTemplate$.next(template);
5558
}
5659

60+
setTfootTemplate(template: TemplateRef<NzSafeAny>): void {
61+
this.tfootTemplate$.next(template);
62+
}
63+
64+
setTfootFixed(fixed: NzTableSummaryFixedType | null): void {
65+
this.tfootFixed$.next(fixed);
66+
}
67+
5768
setHasFixLeft(hasFixLeft: boolean): void {
5869
this.hasFixLeft$.next(hasFixLeft);
5970
}
@@ -106,6 +117,4 @@ export class NzTableStyleService {
106117
}
107118
this.enableAutoMeasure$.next(enableAutoMeasure);
108119
}
109-
110-
constructor() {}
111120
}

components/table/src/table.module.ts

+3-3
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ import { NzTableInnerScrollComponent } from './table/table-inner-scroll.componen
2828
import { NzTableVirtualScrollDirective } from './table/table-virtual-scroll.directive';
2929
import { NzTableComponent } from './table/table.component';
3030
import { NzTbodyComponent } from './table/tbody.component';
31-
import { NzTfootSummaryDirective } from './table/tfoot-summary.directive';
31+
import { NzTfootSummaryComponent } from './table/tfoot-summary.component';
3232
import { NzTheadComponent } from './table/thead.component';
3333
import { NzTableTitleFooterComponent } from './table/title-footer.component';
3434
import { NzTrExpandDirective } from './table/tr-expand.directive';
@@ -46,7 +46,7 @@ import { NzTrDirective } from './table/tr.directive';
4646
NzTbodyComponent,
4747
NzTrDirective,
4848
NzTrExpandDirective,
49-
NzTfootSummaryDirective,
49+
NzTfootSummaryComponent,
5050
NzTableVirtualScrollDirective,
5151
NzCellFixedDirective,
5252
NzCustomColumnDirective,
@@ -81,7 +81,7 @@ import { NzTrDirective } from './table/tr.directive';
8181
NzCustomColumnDirective,
8282
NzFilterTriggerComponent,
8383
NzTrExpandDirective,
84-
NzTfootSummaryDirective,
84+
NzTfootSummaryComponent,
8585
NzCellBreakWordDirective,
8686
NzCellAlignDirective,
8787
NzCellEllipsisDirective,

components/table/src/table.types.ts

+2
Original file line numberDiff line numberDiff line change
@@ -28,3 +28,5 @@ export interface NzCustomColumn {
2828
width: number;
2929
fixWidth?: boolean;
3030
}
31+
32+
export type NzTableSummaryFixedType = 'top' | 'bottom';

components/table/src/table/table-content.component.ts

+6
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,11 @@ import { NzTableLayout } from '../table.types';
2525
}
2626
<ng-template [ngTemplateOutlet]="contentTemplate"></ng-template>
2727
<ng-content></ng-content>
28+
@if (tfootTemplate) {
29+
<tfoot class="ant-table-summary">
30+
<ng-template [ngTemplateOutlet]="tfootTemplate"></ng-template>
31+
</tfoot>
32+
}
2833
`,
2934
host: {
3035
'[style.table-layout]': 'tableLayout',
@@ -39,6 +44,7 @@ export class NzTableContentComponent {
3944
@Input() tableLayout: NzTableLayout = 'auto';
4045
@Input() theadTemplate: TemplateRef<NzSafeAny> | null = null;
4146
@Input() contentTemplate: TemplateRef<NzSafeAny> | null = null;
47+
@Input() tfootTemplate: TemplateRef<NzSafeAny> | null = null;
4248
@Input() listOfColWidth: ReadonlyArray<string | null> = [];
4349
@Input() scrollX: string | null = null;
4450
}

components/table/src/table/table-fixed-row.component.ts

+4
Original file line numberDiff line numberDiff line change
@@ -50,22 +50,26 @@ export class NzTableFixedRowComponent implements OnInit, OnDestroy, AfterViewIni
5050
hostWidth$ = new BehaviorSubject<number | null>(null);
5151
enableAutoMeasure$ = new BehaviorSubject<boolean>(false);
5252
private destroy$ = new Subject<boolean>();
53+
5354
constructor(
5455
private nzTableStyleService: NzTableStyleService,
5556
private renderer: Renderer2
5657
) {}
58+
5759
ngOnInit(): void {
5860
if (this.nzTableStyleService) {
5961
const { enableAutoMeasure$, hostWidth$ } = this.nzTableStyleService;
6062
enableAutoMeasure$.pipe(takeUntil(this.destroy$)).subscribe(this.enableAutoMeasure$);
6163
hostWidth$.pipe(takeUntil(this.destroy$)).subscribe(this.hostWidth$);
6264
}
6365
}
66+
6467
ngAfterViewInit(): void {
6568
this.nzTableStyleService.columnCount$.pipe(takeUntil(this.destroy$)).subscribe(count => {
6669
this.renderer.setAttribute(this.tdElement.nativeElement, 'colspan', `${count}`);
6770
});
6871
}
72+
6973
ngOnDestroy(): void {
7074
this.destroy$.next(true);
7175
this.destroy$.complete();

components/table/src/table/table-inner-default.component.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import { NzTableContentComponent } from './table-content.component';
2222
[tableLayout]="tableLayout"
2323
[listOfColWidth]="listOfColWidth"
2424
[theadTemplate]="theadTemplate"
25+
[tfootTemplate]="tfootTemplate"
2526
></table>
2627
</div>
2728
`,
@@ -34,6 +35,5 @@ export class NzTableInnerDefaultComponent {
3435
@Input() listOfColWidth: ReadonlyArray<string | null> = [];
3536
@Input() theadTemplate: TemplateRef<NzSafeAny> | null = null;
3637
@Input() contentTemplate: TemplateRef<NzSafeAny> | null = null;
37-
38-
constructor() {}
38+
@Input() tfootTemplate: TemplateRef<NzSafeAny> | null = null;
3939
}

components/table/src/table/table-inner-scroll.component.ts

+27-7
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ import { delay, filter, startWith, switchMap, takeUntil } from 'rxjs/operators';
2828
import { NzResizeService } from 'ng-zorro-antd/core/services';
2929
import { NzSafeAny } from 'ng-zorro-antd/core/types';
3030

31+
import { NzTableSummaryFixedType } from '../table.types';
3132
import { NzTableContentComponent } from './table-content.component';
3233
import { NzTbodyComponent } from './tbody.component';
3334

@@ -44,6 +45,7 @@ import { NzTbodyComponent } from './tbody.component';
4445
[scrollX]="scrollX"
4546
[listOfColWidth]="listOfColWidth"
4647
[theadTemplate]="theadTemplate"
48+
[tfootTemplate]="tfootFixed === 'top' ? tfootTemplate : null"
4749
></table>
4850
</div>
4951
@if (!virtualTemplate) {
@@ -76,6 +78,17 @@ import { NzTbodyComponent } from './tbody.component';
7678
</table>
7779
</cdk-virtual-scroll-viewport>
7880
}
81+
@if (tfootFixed === 'bottom') {
82+
<div #tableFootElement class="ant-table-summary" [ngStyle]="headerStyleMap">
83+
<table
84+
nz-table-content
85+
tableLayout="fixed"
86+
[scrollX]="scrollX"
87+
[listOfColWidth]="listOfColWidth"
88+
[tfootTemplate]="tfootTemplate"
89+
></table>
90+
</div>
91+
}
7992
} @else {
8093
<div class="ant-table-content" #tableBodyElement [ngStyle]="bodyStyleMap">
8194
<table
@@ -85,6 +98,7 @@ import { NzTbodyComponent } from './tbody.component';
8598
[listOfColWidth]="listOfColWidth"
8699
[theadTemplate]="theadTemplate"
87100
[contentTemplate]="contentTemplate"
101+
[tfootTemplate]="tfootTemplate"
88102
></table>
89103
</div>
90104
}
@@ -101,6 +115,8 @@ export class NzTableInnerScrollComponent<T> implements OnChanges, AfterViewInit,
101115
@Input() widthConfig: string[] = [];
102116
@Input() listOfColWidth: ReadonlyArray<string | null> = [];
103117
@Input() theadTemplate: TemplateRef<NzSafeAny> | null = null;
118+
@Input() tfootTemplate: TemplateRef<NzSafeAny> | null = null;
119+
@Input() tfootFixed: NzTableSummaryFixedType | null = null;
104120
@Input() virtualTemplate: TemplateRef<NzSafeAny> | null = null;
105121
@Input() virtualItemSize = 0;
106122
@Input() virtualMaxBufferPx = 200;
@@ -109,6 +125,7 @@ export class NzTableInnerScrollComponent<T> implements OnChanges, AfterViewInit,
109125
@Input() virtualForTrackBy: TrackByFunction<T> = index => index;
110126
@ViewChild('tableHeaderElement', { read: ElementRef }) tableHeaderElement!: ElementRef;
111127
@ViewChild('tableBodyElement', { read: ElementRef }) tableBodyElement!: ElementRef;
128+
@ViewChild('tableFootElement', { read: ElementRef }) tableFootElement?: ElementRef;
112129
@ViewChild(CdkVirtualScrollViewport, { read: CdkVirtualScrollViewport })
113130
cdkVirtualScrollViewport?: CdkVirtualScrollViewport;
114131
headerStyleMap = {};
@@ -158,15 +175,16 @@ export class NzTableInnerScrollComponent<T> implements OnChanges, AfterViewInit,
158175
overflowX: this.scrollX ? 'auto' : null,
159176
maxHeight: this.scrollY
160177
};
161-
// Caretaker note: we have to emit the value outside of the Angular zone, thus DOM timer (`delay(0)`) and `scroll`
162-
// event listener will be also added outside of the Angular zone.
178+
// Caretaker note: we have to emit the value outside the Angular zone, thus DOM timer (`delay(0)`) and `scroll`
179+
// event listener will be also added outside the Angular zone.
163180
this.ngZone.runOutsideAngular(() => this.scroll$.next());
164181
}
165182
if (data) {
166183
// See the comment above.
167184
this.ngZone.runOutsideAngular(() => this.data$.next());
168185
}
169186
}
187+
170188
ngAfterViewInit(): void {
171189
if (this.platform.isBrowser) {
172190
this.ngZone.runOutsideAngular(() => {
@@ -184,14 +202,16 @@ export class NzTableInnerScrollComponent<T> implements OnChanges, AfterViewInit,
184202
takeUntil(this.destroy$)
185203
);
186204
setClassName$.subscribe(() => this.setScrollPositionClassName());
187-
scrollEvent$
188-
.pipe(filter(() => !!this.scrollY))
189-
.subscribe(
190-
() => (this.tableHeaderElement.nativeElement.scrollLeft = this.tableBodyElement.nativeElement.scrollLeft)
191-
);
205+
scrollEvent$.pipe(filter(() => !!this.scrollY)).subscribe(() => {
206+
this.tableHeaderElement.nativeElement.scrollLeft = this.tableBodyElement.nativeElement.scrollLeft;
207+
if (this.tableFootElement) {
208+
this.tableFootElement.nativeElement.scrollLeft = this.tableBodyElement.nativeElement.scrollLeft;
209+
}
210+
});
192211
});
193212
}
194213
}
214+
195215
ngOnDestroy(): void {
196216
this.setScrollPositionClassName(true);
197217
this.destroy$.next();

0 commit comments

Comments
 (0)