From 90daf79730345d4fba644ac218d34a448f19b9e3 Mon Sep 17 00:00:00 2001 From: cipchk Date: Thu, 7 Mar 2024 15:44:33 +0800 Subject: [PATCH] fix(abc:st): fix sorting trigger misalignment in mulit-column - close https://github.com/ng-alain/ng-alain/issues/2482 --- packages/abc/st/st-data-source.ts | 29 +++++++++------ packages/abc/st/st.component.html | 4 +-- packages/abc/st/st.component.ts | 17 +++++---- packages/abc/st/test/st-data-source.spec.ts | 39 ++++++++++++++------- packages/abc/st/test/st-sort.spec.ts | 10 +++--- 5 files changed, 62 insertions(+), 37 deletions(-) diff --git a/packages/abc/st/st-data-source.ts b/packages/abc/st/st-data-source.ts index 439e3fea8..e3fb81ad4 100644 --- a/packages/abc/st/st-data-source.ts +++ b/packages/abc/st/st-data-source.ts @@ -35,7 +35,7 @@ import type { STStatisticalResults, STStatisticalType } from './st.interfaces'; -import { _STColumn, _STColumnButton, _STDataValue } from './st.types'; +import type { _STColumn, _STColumnButton, _STDataValue, _STHeader } from './st.types'; export interface STDataSourceOptions { pi: number; @@ -47,6 +47,7 @@ export interface STDataSourceOptions { res: STRes; page: STPage; columns: _STColumn[]; + headers: _STHeader[][]; singleSort?: STSingleSort | null; multiSort?: STMultiSort; rowClassName?: STRowClassName | null; @@ -89,7 +90,7 @@ export class STDataSource { process(options: STDataSourceOptions): Observable { let data$: Observable; let isRemote = false; - const { data, res, total, page, pi, ps, paginator, columns } = options; + const { data, res, total, page, pi, ps, paginator, columns, headers } = options; let retTotal: number; let retPs: number; let retList: STData[]; @@ -141,7 +142,7 @@ export class STDataSource { map((result: STData[]) => { rawData = result; let copyResult = deepCopy(result); - const sorterFn = this.getSorterFn(columns as _STColumn[]); + const sorterFn = this.getSorterFn(headers); if (sorterFn) { copyResult = copyResult.sort(sorterFn); } @@ -277,7 +278,7 @@ export class STDataSource { } private getByRemote(url: string, options: STDataSourceOptions): Observable { - const { req, page, paginator, pi, ps, singleSort, multiSort, columns } = options; + const { req, page, paginator, pi, ps, singleSort, multiSort, columns, headers } = options; const method = (req.method || 'GET').toUpperCase(); // eslint-disable-next-line @typescript-eslint/no-explicit-any let params: { [param: string]: any } = {}; @@ -298,7 +299,7 @@ export class STDataSource { params = { ...params, ...req.params, - ...this.getReqSortMap(singleSort, multiSort, columns), + ...this.getReqSortMap(singleSort, multiSort, headers), ...this.getReqFilterMap(columns) }; if (options.req.ignoreParamNull == true) { @@ -417,12 +418,18 @@ export class STDataSource { // #region sort - private getValidSort(columns: _STColumn[]): STSortMap[] { - return columns.filter(item => item._sort && item._sort.enabled && item._sort.default).map(item => item._sort!); + private getValidSort(headers: _STHeader[][]): STSortMap[] { + return headers.reduce((a, header) => { + const ls = header + .map(i => i.column) + .filter(item => item._sort && item._sort.enabled && item._sort.default) + .map(item => item._sort!); + return a.concat(...ls); + }, [] as STSortMap[]); } - private getSorterFn(columns: _STColumn[]): ((a: STData, b: STData) => number) | void { - const sortList = this.getValidSort(columns); + private getSorterFn(headers: _STHeader[][]): ((a: STData, b: STData) => number) | void { + const sortList = this.getValidSort(headers); if (sortList.length === 0) { return; } @@ -453,10 +460,10 @@ export class STDataSource { getReqSortMap( singleSort: STSingleSort | undefined | null, multiSort: STMultiSort | undefined, - columns: _STColumn[] + headers: _STHeader[][] ): STMultiSortResultType { let ret: STMultiSortResultType = {}; - const sortList = this.getValidSort(columns); + const sortList = this.getValidSort(headers); if (multiSort) { const ms: STMultiSort = { diff --git a/packages/abc/st/st.component.html b/packages/abc/st/st.component.html index 559b0e934..c27707612 100644 --- a/packages/abc/st/st.component.html +++ b/packages/abc/st/st.component.html @@ -60,7 +60,7 @@ @if ($first && expand) { } - @for (h of row; track index; let index = $index; let last = $last) { + @for (h of row; track h; let index = $index; let last = $last) { { - const { pi, ps, data, req, res, page, total, singleSort, multiSort, rowClassName } = this; + const { pi, ps, data, req, res, page, total, singleSort, multiSort, rowClassName, _columns, _headers } = this; return this.dataSource .process({ pi, @@ -347,7 +347,8 @@ export class STComponent implements AfterViewInit, OnChanges { req, res, page, - columns: this._columns, + columns: _columns, + headers: _headers, singleSort, multiSort, rowClassName, @@ -620,18 +621,20 @@ export class STComponent implements AfterViewInit, OnChanges { // #region sort - sort(col: _STColumn, idx: number, value: NzSafeAny): void { + sort(col: _STColumn, value: NzSafeAny): void { if (this.multiSort) { col._sort.default = value; col._sort.tick = this.dataSource.nextSortTick; } else { - this._columns.forEach((item, index) => (item._sort.default = index === idx ? value : null)); + this._headers.forEach(row => { + row.forEach(item => (item.column._sort.default = item.column === col ? value : null)); + }); } this.cdr.detectChanges(); this.loadPageData().subscribe(() => { const res = { value, - map: this.dataSource.getReqSortMap(this.singleSort, this.multiSort, this._columns), + map: this.dataSource.getReqSortMap(this.singleSort, this.multiSort, this._headers), column: col }; this.changeEmit('sort', res); @@ -639,7 +642,9 @@ export class STComponent implements AfterViewInit, OnChanges { } clearSort(): this { - this._columns.forEach(item => (item._sort.default = null)); + this._headers.forEach(row => { + row.forEach(item => (item.column._sort.default = null)); + }); return this; } diff --git a/packages/abc/st/test/st-data-source.spec.ts b/packages/abc/st/test/st-data-source.spec.ts index ec39d9d53..3eb926652 100644 --- a/packages/abc/st/test/st-data-source.spec.ts +++ b/packages/abc/st/test/st-data-source.spec.ts @@ -67,6 +67,7 @@ describe('abc: table: data-souce', () => { res: deepCopy(ST_DEFAULT_CONFIG.res), page: deepCopy(ST_DEFAULT_CONFIG.page), columns: [{ title: '', index: 'id' }] as _STColumn[], + headers: [[{ colSpan: 1, rowSpan: 1, hasSubColumns: false, column: { title: '', index: 'id' } as _STColumn }]], paginator: true }; TestBed.configureTestingModule({ @@ -167,14 +168,14 @@ describe('abc: table: data-souce', () => { describe('[sort]', () => { beforeEach(() => { options.data = genData(DEFAULT.total, true); - options.columns[0]._sort = { + options.headers[0][0].column._sort = { enabled: true, compare: (a: any, b: any) => a.id - b.id }; }); it(`should be decremented`, done => { (options.data as STData[])[1].id = 100000; - options.columns[0]._sort.default = 'descend'; + options.headers[0][0].column._sort.default = 'descend'; srv.process(options).subscribe(res => { expect(res.list[0].id).toBe(100000); done(); @@ -182,14 +183,14 @@ describe('abc: table: data-souce', () => { }); it(`should be incremented`, done => { (options.data as STData[])[1].id = -100000; - options.columns[0]._sort.default = 'ascend'; + options.headers[0][0].column._sort.default = 'ascend'; srv.process(options).subscribe(res => { expect(res.list[0].id).toBe(-100000); done(); }); }); it('should be null, muse be ingore sort processing', done => { - options.columns[0]._sort = { + options.headers[0][0].column._sort = { enabled: true, compare: null, default: 'descend' @@ -464,7 +465,7 @@ describe('abc: table: data-souce', () => { beforeEach(() => { genModule(); options.data = '/mockurl'; - options.columns[0]._sort = { + options.headers[0][0].column._sort = { enabled: true, key: 'id' }; @@ -474,30 +475,30 @@ describe('abc: table: data-souce', () => { }); }); it(`should be decremented`, done => { - options.columns[0]._sort.default = 'descend'; + options.headers[0][0].column._sort.default = 'descend'; srv.process(options).subscribe(() => { expect(resParams.get('id')!).toBe('descend'); done(); }); }); it(`should be incremented`, done => { - options.columns[0]._sort.default = 'ascend'; + options.headers[0][0].column._sort.default = 'ascend'; srv.process(options).subscribe(() => { expect(resParams.get('id')!).toBe('ascend'); done(); }); }); it(`should be re-name`, done => { - options.columns[0]._sort.default = 'ascend'; - options.columns[0]._sort.reName = { ascend: 'A', descend: 'D' }; + options.headers[0][0].column._sort.default = 'ascend'; + options.headers[0][0].column._sort.reName = { ascend: 'A', descend: 'D' }; srv.process(options).subscribe(() => { expect(resParams.get('id')!).toBe('A'); done(); }); }); it(`should be used default key when invalid re-name paraments`, done => { - options.columns[0]._sort.default = 'ascend'; - options.columns[0]._sort.reName = {}; + options.headers[0][0].column._sort.default = 'ascend'; + options.headers[0][0].column._sort.reName = {}; srv.process(options).subscribe(() => { expect(resParams.get('id')!).toBe('ascend'); done(); @@ -522,6 +523,12 @@ describe('abc: table: data-souce', () => { _sort: { enabled: true, default: 'ascend', key: 'id2' } } ]; + options.headers = [ + [ + { colSpan: 1, rowSpan: 1, hasSubColumns: false, column: options.columns[0] }, + { colSpan: 1, rowSpan: 1, hasSubColumns: false, column: options.columns[1] } + ] + ]; }); it(`should be`, done => { srv.process(options).subscribe(() => { @@ -553,6 +560,12 @@ describe('abc: table: data-souce', () => { sort: true } ] as _STColumn[]; + options.headers = [ + [ + { colSpan: 1, rowSpan: 1, hasSubColumns: false, column: options.columns[0] }, + { colSpan: 1, rowSpan: 1, hasSubColumns: false, column: options.columns[1] } + ] + ]; srv.process(options).subscribe(() => { expect(resParams.has('SORT')).toBe(false); done(); @@ -586,7 +599,7 @@ describe('abc: table: data-souce', () => { }); describe('[singleSort]', () => { it(`should working`, done => { - options.columns[0]._sort.default = 'ascend'; + options.headers[0][0].column._sort.default = 'ascend'; options.singleSort = {}; srv.process(options).subscribe(() => { expect(resParams.get('sort')).toBe('id.ascend'); @@ -594,7 +607,7 @@ describe('abc: table: data-souce', () => { }); }); it(`should specify options`, done => { - options.columns[0]._sort.default = 'ascend'; + options.headers[0][0].column._sort.default = 'ascend'; options.singleSort = { key: 'SORT', nameSeparator: '-' }; srv.process(options).subscribe(() => { expect(resParams.get('SORT')).toBe('id-ascend'); diff --git a/packages/abc/st/test/st-sort.spec.ts b/packages/abc/st/test/st-sort.spec.ts index 0ee9a564f..0975120ba 100644 --- a/packages/abc/st/test/st-sort.spec.ts +++ b/packages/abc/st/test/st-sort.spec.ts @@ -39,7 +39,7 @@ describe('abc: st-sort', () => { it('muse provide the compare function', fakeAsync(() => { spyOn(console, 'warn'); page.updateColumn([{ title: '', index: 'i', sort: { compare: 'a' } as NzSafeAny }]); - comp.sort(comp._columns[0], 0, 'descend'); + comp.sort(comp._columns[0], 'descend'); page.cd(); expect(console.warn).toHaveBeenCalled(); page.asyncEnd(); @@ -47,14 +47,14 @@ describe('abc: st-sort', () => { it('should be auto generate compose when sort is true', fakeAsync(() => { context.data = [{ i: 1 }, { i: 2 }]; page.updateColumn([{ title: '', index: 'i', sort: true }]); - comp.sort(comp._columns[0], 0, 'descend'); + comp.sort(comp._columns[0], 'descend'); page.cd(); expect(context.comp.list[0].i).toBe(2); page.asyncEnd(); })); it('should be sorting', fakeAsync(() => { page.cd(); - comp.sort(comp._columns[0], 0, 'descend'); + comp.sort(comp._columns[0], 'descend'); const sortList = comp._columns .filter(item => item._sort && item._sort.enabled && item._sort.default) .map(item => item._sort!); @@ -67,8 +67,8 @@ describe('abc: st-sort', () => { beforeEach(() => (context.multiSort = true)); it('should be sorting', fakeAsync(() => { page.cd(); - comp.sort(comp._columns[0], 0, 'descend'); - comp.sort(comp._columns[1], 0, 'ascend'); + comp.sort(comp._columns[0], 'descend'); + comp.sort(comp._columns[1], 'ascend'); const sortList = comp._columns .filter(item => item._sort && item._sort.enabled && item._sort.default) .map(item => item._sort!);