From 094dc654e2f0571e43ec7fd8c05c4b0dfc44059b Mon Sep 17 00:00:00 2001 From: ghiscoding Date: Thu, 11 Jun 2026 23:58:58 -0400 Subject: [PATCH 1/8] fix: updating columns should include internal plugin columns --- .../src/examples/slickgrid/example03.ts | 10 +- .../src/examples/slickgrid/example12.ts | 11 +- .../src/examples/slickgrid/example16.ts | 7 +- .../src/examples/slickgrid/Example02.tsx | 8 +- .../src/examples/slickgrid/Example03.tsx | 9 - .../src/examples/slickgrid/Example12.tsx | 9 - .../src/examples/slickgrid/Example16.tsx | 7 +- demos/vanilla/src/examples/example07.ts | 18 +- demos/vue/src/components/Example03.vue | 8 - demos/vue/src/components/Example12.vue | 9 - demos/vue/src/components/Example16.vue | 7 +- docs/grid-functionalities/row-selection.md | 5 +- .../docs/grid-functionalities/row-detail.md | 3 + .../grid-functionalities/row-selection.md | 3 + .../src/demos/app-routing.module.ts | 1 + .../src/demos/app.component.html | 3 + .../src/demos/examples/example.component.ts | 37 ++++ .../src/demos/examples/example03.component.ts | 11 +- .../src/demos/examples/example12.component.ts | 11 +- .../src/demos/examples/example16.component.ts | 7 +- .../angular-slickgrid.component.spec.ts | 89 ++------- .../components/angular-slickgrid.component.ts | 67 +------ .../docs/grid-functionalities/row-detail.md | 3 + .../grid-functionalities/row-selection.md | 3 + .../src/custom-elements/aurelia-slickgrid.ts | 93 +-------- .../docs/grid-functionalities/row-detail.md | 3 + .../grid-functionalities/row-selection.md | 3 + .../src/components/slickgrid-react.tsx | 91 +-------- .../docs/grid-functionalities/row-detail.md | 3 + .../grid-functionalities/row-selection.md | 3 + .../src/components/SlickgridVue.vue | 90 +-------- .../__tests__/gridState.service.spec.ts | 148 ++++++++++++-- .../common/src/services/gridState.service.ts | 183 +++++++++++++----- .../__tests__/slick-vanilla-grid.spec.ts | 150 ++------------ .../components/slick-vanilla-grid-bundle.ts | 100 ++-------- .../__tests__/vanilla-force-bundle.spec.ts | 3 + 36 files changed, 429 insertions(+), 787 deletions(-) create mode 100644 frameworks/angular-slickgrid/src/demos/examples/example.component.ts diff --git a/demos/aurelia/src/examples/slickgrid/example03.ts b/demos/aurelia/src/examples/slickgrid/example03.ts index 9e16160c28..4d4ea786ad 100644 --- a/demos/aurelia/src/examples/slickgrid/example03.ts +++ b/demos/aurelia/src/examples/slickgrid/example03.ts @@ -599,14 +599,8 @@ export class Example03 { // and then use the spread operator [...cols] OR slice to force Aurelia to review the changes this.columns.push(newCol); - // NOTE if you use an Extensions (Checkbox Selector, Row Detail, ...) that modifies the column definitions in any way - // you MUST use "getAllColumnDefinitions()" from the GridService, using this will be ALL columns including the 1st column that is created internally - // for example if you use the Checkbox Selector (row selection), you MUST use the code below - /* - const allColumns = this.aureliaGrid.gridService.getAllColumnDefinitions(); - allColumns.push(newCol); - this.columns = [...allColumns]; // (or use slice) reassign to column definitions for Aurelia to do dirty checking - */ + // use slice spread operator [...cols] to trigger dirty checking + this.columns = this.columns.slice(); } dynamicallyRemoveLastColumn() { diff --git a/demos/aurelia/src/examples/slickgrid/example12.ts b/demos/aurelia/src/examples/slickgrid/example12.ts index 3564a55c87..d65117455e 100644 --- a/demos/aurelia/src/examples/slickgrid/example12.ts +++ b/demos/aurelia/src/examples/slickgrid/example12.ts @@ -270,16 +270,9 @@ export class Example12 { params: { useFormatterOuputToFilter: true }, }; this.columns.push(newCol); - this.columns = this.columns.slice(); // or use spread operator [...cols] - // NOTE if you use an Extensions (Checkbox Selector, Row Detail, ...) that modifies the column definitions in any way - // you MUST use "getAllColumnDefinitions()" from the GridService, using this will be ALL columns including the 1st column that is created internally - // for example if you use the Checkbox Selector (row selection), you MUST use the code below - /* - const allColumns = this.aureliaGrid.gridService.getAllColumnDefinitions(); - allColumns.push(newCol); - this.columns = [...allColumns]; // (or use slice) reassign to column definitions for Aurelia to do dirty checking - */ + // use slice spread operator [...cols] to trigger dirty checking + this.columns = this.columns.slice(); } exportToExcel() { diff --git a/demos/aurelia/src/examples/slickgrid/example16.ts b/demos/aurelia/src/examples/slickgrid/example16.ts index ceec9eab31..a9b8ef1ac6 100644 --- a/demos/aurelia/src/examples/slickgrid/example16.ts +++ b/demos/aurelia/src/examples/slickgrid/example16.ts @@ -204,12 +204,9 @@ export class Example16 { }, ]; - // NOTE if you use an Extensions (Checkbox Selector, Row Detail, ...) that modifies the column definitions in any way - // you MUST use "getAllColumnDefinitions()" from the GridService, using this will be ALL columns including the 1st column that is created internally - // for example if you use the Checkbox Selector (row selection), you MUST use the code below + // use slice or spread reassign to column definitions for Angular to do dirty checking const allColumns = this.aureliaGrid.gridService.getAllColumnDefinitions(); - allColumns.unshift(newCols[0], newCols[1]); - this.columns = [...allColumns]; // (or use slice) reassign to column definitions for Aurelia to do dirty checking + this.columns = [...newCols, ...allColumns]; } } diff --git a/demos/react-fluent/src/examples/slickgrid/Example02.tsx b/demos/react-fluent/src/examples/slickgrid/Example02.tsx index 0ae2113f47..8358a79667 100644 --- a/demos/react-fluent/src/examples/slickgrid/Example02.tsx +++ b/demos/react-fluent/src/examples/slickgrid/Example02.tsx @@ -208,12 +208,8 @@ const Example02: React.FC = () => { }, ]; - // NOTE if you use an Extensions (Checkbox Selector, Row Detail, ...) that modifies the column definitions in any way - // you MUST use "getAllColumnDefinitions()" from the GridService, using this will be ALL columns including the 1st column that is created internally - // for example if you use the Checkbox Selector (row selection), you MUST use the code below - const allColumns = reactGridRef.current?.gridService.getAllColumnDefinitions() || []; - allColumns.unshift(newCols[0], newCols[1]); - setColumns([...allColumns]); // (or use slice) reassign to column definitions for React to do dirty checking + // use slice or spread reassign to column definitions for Angular to do dirty checking + setColumns([...newCols]); } } diff --git a/demos/react/src/examples/slickgrid/Example03.tsx b/demos/react/src/examples/slickgrid/Example03.tsx index a0002d2f92..6e5939c6b8 100644 --- a/demos/react/src/examples/slickgrid/Example03.tsx +++ b/demos/react/src/examples/slickgrid/Example03.tsx @@ -594,15 +594,6 @@ const Example3: React.FC = () => { // you can dynamically add your column to your column definitions // and then use the spread operator [...cols] OR slice to force React to review the changes setColumns([...columns!, newCol]); - - // NOTE if you use an Extensions (Checkbox Selector, Row Detail, ...) that modifies the column definitions in any way - // you MUST use 'getAllColumnDefinitions()' from the GridService, using this will be ALL columns including the 1st column that is created internally - // for example if you use the Checkbox Selector (row selection), you MUST use the code below - /* - const allColumns = reactGrid.gridService.getAllColumnDefinitions(); - allColumns.push(newCol); - columns = [...allColumns]; // (or use slice) reassign to column definitions for React to do dirty checking - */ } function dynamicallyRemoveLastColumn() { diff --git a/demos/react/src/examples/slickgrid/Example12.tsx b/demos/react/src/examples/slickgrid/Example12.tsx index fb3e1d0b34..1a2138586a 100644 --- a/demos/react/src/examples/slickgrid/Example12.tsx +++ b/demos/react/src/examples/slickgrid/Example12.tsx @@ -232,15 +232,6 @@ const Example12: React.FC = () => { columns.push(newCol); setColumns(columns.slice()); // or use spread operator [...cols] - - // NOTE if you use an Extensions (Checkbox Selector, Row Detail, ...) that modifies the column definitions in any way - // you MUST use "getAllColumnDefinitions()" from the GridService, using this will be ALL columns including the 1st column that is created internally - // for example if you use the Checkbox Selector (row selection), you MUST use the code below - /* - const allColumns = reactGrid.gridService.getAllColumnDefinitions(); - allColumns.push(newCol); - columns = [...allColumns]; // (or use slice) reassign to column definitions for React to do dirty checking - */ } function exportToExcel() { diff --git a/demos/react/src/examples/slickgrid/Example16.tsx b/demos/react/src/examples/slickgrid/Example16.tsx index c7bfde9dbb..0ded5b3359 100644 --- a/demos/react/src/examples/slickgrid/Example16.tsx +++ b/demos/react/src/examples/slickgrid/Example16.tsx @@ -203,12 +203,9 @@ const Example16: React.FC = () => { }, ]; - // NOTE if you use an Extensions (Checkbox Selector, Row Detail, ...) that modifies the column definitions in any way - // you MUST use "getAllColumnDefinitions()" from the GridService, using this will be ALL columns including the 1st column that is created internally - // for example if you use the Checkbox Selector (row selection), you MUST use the code below + // use slice or spread reassign to column definitions for Angular to do dirty checking const allColumns = reactGridRef.current?.gridService.getAllColumnDefinitions() || []; - allColumns.unshift(newCols[0], newCols[1]); - setColumns([...allColumns]); // (or use slice) reassign to column definitions for React to do dirty checking + setColumns([...newCols, ...allColumns]); } } diff --git a/demos/vanilla/src/examples/example07.ts b/demos/vanilla/src/examples/example07.ts index b5466caabc..e3605dbab8 100644 --- a/demos/vanilla/src/examples/example07.ts +++ b/demos/vanilla/src/examples/example07.ts @@ -613,26 +613,12 @@ export default class Example07 { // and then use the spread operator [...cols] OR slice to force the framework to review the changes this.sgb.columnDefinitions.push(newCol); - // NOTE if you use an Extensions (Checkbox Selector, Row Detail, ...) that modifies the column definitions in any way - // you MUST use "getAllColumnDefinitions()" from the GridService, using this will be ALL columns including the 1st column that is created internally - // for example if you use the Checkbox Selector (row selection), you MUST use the code below - /* - const allOriginalColumns = this.sgb.gridService.getAllColumnDefinitions(); - allOriginalColumns.push(newCol); - this.sgb.columnDefinitions = [...allOriginalColumns]; // (or use slice) reassign to column definitions for framework to do dirty checking - */ + // use slice spread operator [...cols] to trigger dirty checking + this.sgb.columnDefinitions = this.columns.slice(); } dynamicallyRemoveLastColumn() { this.sgb.columnDefinitions.pop(); - - /* - const allColumns = this.slickerGridInstance.gridService.getAllColumnDefinitions(); - // remove your column from the full set of columns - // and use slice or spread [...] to trigger a dirty change - allOriginalColumns.pop(); - this.sgb.columnDefinitions = allOriginalColumns.slice(); - */ } hideFinishColumnDynamically() { diff --git a/demos/vue/src/components/Example03.vue b/demos/vue/src/components/Example03.vue index ca7aae59e1..351ad58c82 100644 --- a/demos/vue/src/components/Example03.vue +++ b/demos/vue/src/components/Example03.vue @@ -586,14 +586,6 @@ function dynamicallyAddTitleHeader() { // you can dynamically add your column to your column definitions columns.value.push(newCol); - - // NOTE if you use an Extensions (Checkbox Selector, Row Detail, ...) that modifies the column definitions in any way - // you MUST use "getAllColumnDefinitions()" from the GridService, using this will be ALL columns including the 1st column that is created internally - // for example if you use the Checkbox Selector (row selection), you MUST use the code below - /* - const allColumns = vueGrid.gridService.getAllColumnDefinitions(); - allColumns.push(newCol); - */ } function dynamicallyRemoveLastColumn() { diff --git a/demos/vue/src/components/Example12.vue b/demos/vue/src/components/Example12.vue index 4911fcb21a..07cf0beb61 100644 --- a/demos/vue/src/components/Example12.vue +++ b/demos/vue/src/components/Example12.vue @@ -259,15 +259,6 @@ function dynamicallyAddTitleHeader() { }; columns.value.push(newCol); columns.value = columns.value.slice(); // or use spread operator [...cols] - - // NOTE if you use an Extensions (Checkbox Selector, Row Detail, ...) that modifies the column definitions in any way - // you MUST use "getAllColumnDefinitions()" from the GridService, using this will be ALL columns including the 1st column that is created internally - // for example if you use the Checkbox Selector (row selection), you MUST use the code below - /* - const allColumns = vueGrid.gridService.getAllColumnDefinitions(); - allColumns.push(newCol); - columns.value = [...allColumns]; // (or use slice) reassign to column definitions for Vue to do dirty checking - */ } function exportToExcel() { diff --git a/demos/vue/src/components/Example16.vue b/demos/vue/src/components/Example16.vue index 9bd59c87db..b54074937d 100644 --- a/demos/vue/src/components/Example16.vue +++ b/demos/vue/src/components/Example16.vue @@ -195,12 +195,9 @@ function addEditDeleteColumns() { }, ]; - // NOTE if you use an Extensions (Checkbox Selector, Row Detail, ...) that modifies the column definitions in any way - // you MUST use "getAllColumnDefinitions()" from the GridService, using this will be ALL columns including the 1st column that is created internally - // for example if you use the Checkbox Selector (row selection), you MUST use the code below + // use slice or spread reassign to column definitions for Angular to do dirty checking const allColumns = vueGrid.gridService.getAllColumnDefinitions(); - allColumns.unshift(newCols[0], newCols[1]); - columns.value = [...allColumns]; // (or use slice) reassign to column definitions for Vue to do dirty checking + columns.value = [...newCols, ...allColumns]; } } diff --git a/docs/grid-functionalities/row-selection.md b/docs/grid-functionalities/row-selection.md index 52fd49711d..afcbd11361 100644 --- a/docs/grid-functionalities/row-selection.md +++ b/docs/grid-functionalities/row-selection.md @@ -379,4 +379,7 @@ this.columns = allColumns.slice(); // or use spread operator [...cols] // you could also use SlickGrid setColumns() method // this.sgb.slickGrid.setColumns(cols); -``` \ No newline at end of file +``` + +> **Note** +> The code above is no lnger necessary with v10.8.0 and above. \ No newline at end of file diff --git a/frameworks/angular-slickgrid/docs/grid-functionalities/row-detail.md b/frameworks/angular-slickgrid/docs/grid-functionalities/row-detail.md index c6c1f60a9d..56f48584c8 100644 --- a/frameworks/angular-slickgrid/docs/grid-functionalities/row-detail.md +++ b/frameworks/angular-slickgrid/docs/grid-functionalities/row-detail.md @@ -391,6 +391,9 @@ addNewColumn() { } ``` +> **Note** +> The code above is no lnger necessary with v10.8.0 and above. + ## Row Detail with Inner Grid You can also add an inner grid inside a Row Detail, however there are a few things to know off and remember. Any time a Row Detail is falling outside the main grid viewport, it will be unmounted and until it comes back into the viewport which is then remounted. The process of unmounting and remounting means that Row Detail previous states aren't preserved, however you could use Grid State & Presets to overcome this problem. diff --git a/frameworks/angular-slickgrid/docs/grid-functionalities/row-selection.md b/frameworks/angular-slickgrid/docs/grid-functionalities/row-selection.md index a53a8c369e..415b7b295b 100644 --- a/frameworks/angular-slickgrid/docs/grid-functionalities/row-selection.md +++ b/frameworks/angular-slickgrid/docs/grid-functionalities/row-selection.md @@ -347,3 +347,6 @@ addNewColumn() { // this.angularGrid.slickGrid.setColumns(cols); } ``` + +> **Note** +> The code above is no lnger necessary with v10.8.0 and above. \ No newline at end of file diff --git a/frameworks/angular-slickgrid/src/demos/app-routing.module.ts b/frameworks/angular-slickgrid/src/demos/app-routing.module.ts index 262994dc8f..21e68c8420 100644 --- a/frameworks/angular-slickgrid/src/demos/app-routing.module.ts +++ b/frameworks/angular-slickgrid/src/demos/app-routing.module.ts @@ -55,6 +55,7 @@ export const routes: Routes = [ { path: 'example51', loadComponent: () => import('./examples/example51.component').then((m) => m.Example51Component) }, { path: 'example52', loadComponent: () => import('./examples/example52.component').then((m) => m.Example52Component) }, { path: 'example53', loadComponent: () => import('./examples/example53.component').then((m) => m.Example53Component) }, + { path: 'example', loadComponent: () => import('./examples/example.component').then((m) => m.TestGridPageComponent) }, { path: '', redirectTo: '/example34', pathMatch: 'full' }, { path: '**', redirectTo: '/example34', pathMatch: 'full' }, ]; diff --git a/frameworks/angular-slickgrid/src/demos/app.component.html b/frameworks/angular-slickgrid/src/demos/app.component.html index deb218327d..e775a1fd2a 100644 --- a/frameworks/angular-slickgrid/src/demos/app.component.html +++ b/frameworks/angular-slickgrid/src/demos/app.component.html @@ -203,6 +203,9 @@ + diff --git a/frameworks/angular-slickgrid/src/demos/examples/example.component.ts b/frameworks/angular-slickgrid/src/demos/examples/example.component.ts new file mode 100644 index 0000000000..9c378b5b91 --- /dev/null +++ b/frameworks/angular-slickgrid/src/demos/examples/example.component.ts @@ -0,0 +1,37 @@ +import { Component, signal } from '@angular/core'; +import { AngularSlickgridComponent, GridOption } from '../../library'; + +@Component({ + selector: 'app-test-grid', + imports: [AngularSlickgridComponent], + template: ` +
+ + +
+ `, +}) +export class TestGridPageComponent { + protected readonly options: GridOption = { + gridWidth: '100%', + enableCheckboxSelector: true, + }; + + protected readonly columns = signal([ + { id: 'id', name: 'id', field: 'id' }, + { id: 'name', name: 'name', field: 'name' }, + { id: 'nameShort', name: 'short', field: 'nameShort' }, + ]); + + protected readonly rows = signal([ + { id: 1, name: 'One dog', nameShort: 'one' }, + { id: 2, name: 'Two dogs', nameShort: 'two' }, + ]); + + protected updateColumns() { + this.columns.update(() => [ + { id: 'id', name: 'id', field: 'id' }, + { id: 'name', name: 'name', field: 'name' }, + ]); + } +} diff --git a/frameworks/angular-slickgrid/src/demos/examples/example03.component.ts b/frameworks/angular-slickgrid/src/demos/examples/example03.component.ts index 713bdccc36..d4012eeb82 100644 --- a/frameworks/angular-slickgrid/src/demos/examples/example03.component.ts +++ b/frameworks/angular-slickgrid/src/demos/examples/example03.component.ts @@ -653,16 +653,9 @@ export class Example3Component implements OnInit { // you can dynamically add your column to your column definitions // and then use the spread operator [...cols] OR slice to force Angular to review the changes this.columns.push(newCol); - this.columns = this.columns.slice(); // or use spread operator [...cols] - // NOTE if you use an Extensions (Checkbox Selector, Row Detail, ...) that modifies the column definitions in any way - // you MUST use "getAllColumnDefinitions()" from the GridService, using this will be ALL columns including the 1st column that is created internally - // for example if you use the Checkbox Selector (row selection), you MUST use the code below - /* - const allColumns = this.angularGrid.gridService.getAllColumnDefinitions(); - allColumns.push(newCol); - this.columns = [...allColumns]; // (or use slice) reassign to column definitions for Angular to do dirty checking - */ + // use slice spread operator [...cols] to trigger dirty checking + this.columns = this.columns.slice(); } dynamicallyRemoveLastColumn() { diff --git a/frameworks/angular-slickgrid/src/demos/examples/example12.component.ts b/frameworks/angular-slickgrid/src/demos/examples/example12.component.ts index b1a9fb9f10..64db2dbd17 100644 --- a/frameworks/angular-slickgrid/src/demos/examples/example12.component.ts +++ b/frameworks/angular-slickgrid/src/demos/examples/example12.component.ts @@ -275,16 +275,9 @@ export class Example12Component implements OnInit, OnDestroy { params: { useFormatterOuputToFilter: true }, }; this.columns.push(newCol); - this.columns = this.columns.slice(); // or use spread operator [...cols] - // NOTE if you use an Extensions (Checkbox Selector, Row Detail, ...) that modifies the column definitions in any way - // you MUST use "getAllColumnDefinitions()" from the GridService, using this will be ALL columns including the 1st column that is created internally - // for example if you use the Checkbox Selector (row selection), you MUST use the code below - /* - const allColumns = this.angularGrid.gridService.getAllColumnDefinitions(); - allColumns.push(newCol); - this.columns = [...allColumns]; // (or use slice) reassign to column definitions for Angular to do dirty checking - */ + // use slice spread operator [...cols] to trigger dirty checking + this.columns = this.columns.slice(); } exportToExcel() { diff --git a/frameworks/angular-slickgrid/src/demos/examples/example16.component.ts b/frameworks/angular-slickgrid/src/demos/examples/example16.component.ts index ef9a9092b2..1aea3f9974 100644 --- a/frameworks/angular-slickgrid/src/demos/examples/example16.component.ts +++ b/frameworks/angular-slickgrid/src/demos/examples/example16.component.ts @@ -201,12 +201,9 @@ export class Example16Component implements OnInit { }, ]; - // NOTE if you use an Extensions (Checkbox Selector, Row Detail, ...) that modifies the column definitions in any way - // you MUST use "getAllColumnDefinitions()" from the GridService, using this will be ALL columns including the 1st column that is created internally - // for example if you use the Checkbox Selector (row selection), you MUST use the code below + // use slice or spread reassign to column definitions for Angular to do dirty checking const allColumns = this.angularGrid.gridService.getAllColumnDefinitions(); - allColumns.unshift(newCols[0], newCols[1]); - this.columns = [...allColumns]; // (or use slice) reassign to column definitions for Aurelia to do dirty checking + this.columns = [...newCols, ...allColumns]; } } diff --git a/frameworks/angular-slickgrid/src/library/components/__tests__/angular-slickgrid.component.spec.ts b/frameworks/angular-slickgrid/src/library/components/__tests__/angular-slickgrid.component.spec.ts index 302776f4dd..67228905e6 100644 --- a/frameworks/angular-slickgrid/src/library/components/__tests__/angular-slickgrid.component.spec.ts +++ b/frameworks/angular-slickgrid/src/library/components/__tests__/angular-slickgrid.component.spec.ts @@ -19,7 +19,6 @@ import { type CurrentPagination, type CurrentPinning, type CurrentSorter, - type Editor, type ExtensionList, type ExtensionService, type ExtensionUtility, @@ -188,6 +187,9 @@ const gridStateServiceStub = { mockGrid.setColumns(gridColumns); } }), + addRxJsResource: vi.fn(), + loadSlickGridEditors: vi.fn(), + syncPluginColumns: vi.fn(), getAssociatedGridColumns: vi.fn(), getCurrentGridState: vi.fn(), needToPreserveRowSelection: vi.fn(), @@ -670,10 +672,7 @@ describe('Angular-Slickgrid Custom Component instantiated via Constructor', () = component.ngAfterViewInit(); expect(component).toBeTruthy(); - expect(autoAddEditorFormatterToColumnsWithEditor).toHaveBeenCalledWith( - [{ id: 'name', field: 'name', editor: undefined }], - customEditableInputFormatter - ); + expect(autoAddEditorFormatterToColumnsWithEditor).toHaveBeenCalledWith(undefined, customEditableInputFormatter); }); }); @@ -683,6 +682,7 @@ describe('Angular-Slickgrid Custom Component instantiated via Constructor', () = const autosizeSpy = vi.spyOn(mockGrid, 'autosizeColumns'); const updateSpy = vi.spyOn(component, 'updateColumnDefinitionsList'); const mockColDefs = [{ id: 'name', field: 'name', editor: undefined }]; + vi.spyOn(SharedService.prototype, 'allColumns', 'get').mockReturnValueOnce(mockColDefs); component.options = { enableTranslate: true, darkMode: true }; component.ngAfterViewInit(); @@ -701,6 +701,7 @@ describe('Angular-Slickgrid Custom Component instantiated via Constructor', () = const updateSpy = vi.spyOn(component, 'updateColumnDefinitionsList'); const renderSpy = vi.spyOn(extensionServiceStub, 'renderColumnHeaders'); const mockColDefs = [{ id: 'name', field: 'name', editor: undefined }]; + vi.spyOn(SharedService.prototype, 'allColumns', 'get').mockReturnValueOnce(mockColDefs); component.ngAfterViewInit(); component.columns = mockColDefs; @@ -710,11 +711,7 @@ describe('Angular-Slickgrid Custom Component instantiated via Constructor', () = expect(translateSpy).not.toHaveBeenCalled(); expect(autosizeSpy).toHaveBeenCalled(); expect(updateSpy).toHaveBeenCalledWith(mockColDefs); - expect(renderSpy).toHaveBeenCalledWith(mockColDefs, true); - expect(autoAddEditorFormatterToColumnsWithEditor).toHaveBeenCalledWith( - [{ id: 'name', field: 'name', editor: undefined }], - customEditableInputFormatter - ); + expect(autoAddEditorFormatterToColumnsWithEditor).toHaveBeenCalledWith(undefined, customEditableInputFormatter); }); }); @@ -783,6 +780,7 @@ describe('Angular-Slickgrid Custom Component instantiated via Constructor', () = { firstName: 'Jane', lastName: 'Smith' }, ]; const mockColDefs = [{ id: 'gender', field: 'gender', editor: { model: Editors.text, collection: ['male', 'female'] } }] as Column[]; + vi.spyOn(SharedService.prototype, 'allColumns', 'get').mockReturnValueOnce(mockColDefs); vi.spyOn(mockDataView, 'getLength').mockReturnValueOnce(0).mockReturnValueOnce(0).mockReturnValueOnce(mockData.length); component.columns = mockColDefs; @@ -880,69 +878,6 @@ describe('Angular-Slickgrid Custom Component instantiated via Constructor', () = }); }); - describe('with editors', () => { - beforeEach(() => { - component.options = gridOptions; - }); - - it('should display a console warning when any of the column definition ids include a dot notation', () => { - const consoleSpy = vi.spyOn(console, 'warn').mockReturnValue(); - const mockColDefs = [{ id: 'user.gender', field: 'user.gender', editor: { model: Editors.text, collection: ['male', 'female'] } }] as Column[]; - - component.columns = mockColDefs; - component.initialization(slickEventHandler); - - expect(consoleSpy).toHaveBeenCalledWith( - '[Angular-Slickgrid] Make sure that none of your Column Definition "id" property includes a dot in its name because that will cause some problems with the Editors. For example if your column definition "field" property is "user.firstName" then use "firstName" as the column "id".' - ); - }); - - it('should be able to load async editors with an Observable', () => - new Promise((done: any) => { - const mockCollection = ['male', 'female']; - const mockColDefs = [{ id: 'gender', field: 'gender', editor: { model: Editors.text, collectionAsync: of(mockCollection) } }] as Column[]; - - component.ngAfterViewInit(); - component.columns = mockColDefs; - - setTimeout(() => { - expect(component.columns[0].editor).toBeTruthy(); - expect(component.columns[0].editor!.collection).toEqual(mockCollection); - expect(component.columns[0].editor!.model).toEqual(Editors.text); - done(); - }); - })); - - it('should be able to load collectionAsync and expect Editor to be destroyed and re-render when receiving new collection from await', () => - new Promise((done: any) => { - const mockCollection = ['male', 'female']; - const promise = new Promise((resolve) => resolve(mockCollection)); - const mockEditor = { - disable: vi.fn(), - destroy: vi.fn(), - renderDomElement: vi.fn(), - } as unknown as Editor; - const mockColDefs = [{ id: 'gender', field: 'gender', editor: { model: Editors.text, collectionAsync: promise } }] as Column[]; - vi.spyOn(mockGrid, 'getCellEditor').mockReturnValue(mockEditor); - const disableSpy = vi.spyOn(mockEditor, 'disable'); - const destroySpy = vi.spyOn(mockEditor, 'destroy'); - const renderSpy = vi.spyOn(mockEditor, 'renderDomElement'); - - component.ngAfterViewInit(); - component.columns = mockColDefs; - - setTimeout(() => { - expect(component.columns[0].editor).toBeTruthy(); - expect(component.columns[0].editor!.collection).toEqual(mockCollection); - expect(component.columns[0].editor!.model).toEqual(Editors.text); - expect(disableSpy).toHaveBeenCalledWith(false); - expect(destroySpy).toHaveBeenCalled(); - expect(renderSpy).toHaveBeenCalledWith(mockCollection); - done(); - }); - })); - }); - describe('use grouping', () => { it('should load groupItemMetaProvider to the DataView when using "draggableGrouping" feature', () => { vi.spyOn(extensionServiceStub, 'extensionList', 'get').mockReturnValue({ @@ -1149,6 +1084,7 @@ describe('Angular-Slickgrid Custom Component instantiated via Constructor', () = const rxjsMock = new RxJsResourceStub(); const backendUtilitySpy = vi.spyOn(backendUtilityServiceStub, 'addRxJsResource'); const filterServiceSpy = vi.spyOn(filterServiceStub, 'addRxJsResource'); + const stateServiceSpy = vi.spyOn(gridStateServiceStub, 'addRxJsResource'); const sortServiceSpy = vi.spyOn(sortServiceStub, 'addRxJsResource'); const paginationServiceSpy = vi.spyOn(paginationServiceStub, 'addRxJsResource'); @@ -1158,6 +1094,7 @@ describe('Angular-Slickgrid Custom Component instantiated via Constructor', () = expect(backendUtilitySpy).toHaveBeenCalled(); expect(filterServiceSpy).toHaveBeenCalled(); + expect(stateServiceSpy).toHaveBeenCalled(); expect(sortServiceSpy).toHaveBeenCalled(); expect(paginationServiceSpy).toHaveBeenCalled(); expect(component.registeredResources.length).toBe(4); // RxJsResourceStub, GridService, GridStateService, SlickEmptyCompositeEditorComponent @@ -2262,10 +2199,8 @@ describe('Angular-Slickgrid Custom Component instantiated via Constructor', () = }; component.columns = mockColDefs; component.initialization(slickEventHandler); - // component.columnsChanged(); setTimeout(() => { - expect(component.columns).toEqual(mockColDefs); expect(component.options.showCustomFooter).toBe(true); expect(component.options.customFooterOptions).toEqual({ dateFormat: 'YYYY-MM-DD, hh:mm a', @@ -2293,6 +2228,7 @@ describe('Angular-Slickgrid Custom Component instantiated via Constructor', () = it('should NOT have a Custom Footer when "showCustomFooter" is enabled WITH Pagination in use', () => new Promise((done: any) => { const mockColDefs = [{ id: 'name', field: 'name', editor: undefined }]; + vi.spyOn(SharedService.prototype, 'allColumns', 'get').mockReturnValueOnce(mockColDefs); component.options = { enablePagination: true, showCustomFooter: true }; component.columns = mockColDefs; @@ -2300,7 +2236,6 @@ describe('Angular-Slickgrid Custom Component instantiated via Constructor', () = // component.columnsChanged(); setTimeout(() => { - expect(component.columns).toEqual(mockColDefs); expect(component.slickFooter).toBeFalsy(); done(); }); @@ -2606,7 +2541,7 @@ describe('Angular-Slickgrid Custom Component instantiated via Constructor', () = component.datasetHierarchical = mockHierarchical; expect(hierarchicalSpy).toHaveBeenCalledWith(mockHierarchical); - expect(clearFilterSpy).toHaveBeenCalled(); + // expect(clearFilterSpy).toHaveBeenCalled(); expect(processSpy).toHaveBeenCalled(); expect(setItemsSpy).toHaveBeenCalledWith([], 'id'); setTimeout(() => { diff --git a/frameworks/angular-slickgrid/src/library/components/angular-slickgrid.component.ts b/frameworks/angular-slickgrid/src/library/components/angular-slickgrid.component.ts index 0b4b0256aa..9e501f2374 100644 --- a/frameworks/angular-slickgrid/src/library/components/angular-slickgrid.component.ts +++ b/frameworks/angular-slickgrid/src/library/components/angular-slickgrid.component.ts @@ -42,7 +42,6 @@ import { SortService, TreeDataService, unsubscribeAll, - type AutocompleterEditor, type BackendService, type BackendServiceApi, type BackendServiceOption, @@ -57,7 +56,6 @@ import { type Pagination, type PaginationMetadata, type RxJsFacade, - type SelectEditor, } from '@slickgrid-universal/common'; import { SlickFooterComponent } from '@slickgrid-universal/custom-footer-component'; import { SlickEmptyWarningComponent } from '@slickgrid-universal/empty-warning-component'; @@ -710,7 +708,7 @@ export class AngularSlickgridComponent implements AfterViewInit, On this.preRegisterResources(); // prepare and load all SlickGrid editors, if an async editor is found then we'll also execute it. - this._columns = this.loadSlickGridEditors(this._columns || []); + this._columns = this.gridStateService.loadSlickGridEditors(this._columns || []); // if the user wants to automatically add a Custom Editor Formatter, we need to call the auto add function again if (this.options.autoAddCustomEditorFormatter) { @@ -1013,12 +1011,12 @@ export class AngularSlickgridComponent implements AfterViewInit, On */ updateColumnDefinitionsList(newColumns: Column[]) { // map the Editor model to editorClass and load editor collectionAsync - newColumns = this.loadSlickGridEditors(newColumns); + const updatedColumns = this.gridStateService.syncPluginColumns(newColumns, [...this.sharedService.allColumns, ...newColumns]); if (this.options.enableTranslate) { - this.extensionService.translateColumnHeaders(undefined, newColumns); + this.extensionService.translateColumnHeaders(undefined, updatedColumns); } - this.extensionService.renderColumnHeaders(newColumns, true); + this.extensionService.renderColumnHeaders(updatedColumns, true); if (this.options?.enableAutoSizeColumns) { this.slickGrid.autosizeColumns(); @@ -1392,26 +1390,6 @@ export class AngularSlickgridComponent implements AfterViewInit, On } } - /** Load the Editor Collection asynchronously and replace the "collection" property when Observable resolves */ - protected loadEditorCollectionAsync(column: Column) { - if (column?.editor) { - const collectionAsync = column.editor.collectionAsync; - column.editor.disabled = true; // disable the Editor DOM element, we'll re-enable it after receiving the collection with "updateEditorCollection()" - - if (collectionAsync instanceof Observable) { - this.subscriptions.push(collectionAsync.subscribe((resolvedCollection) => this.updateEditorCollection(column, resolvedCollection))); - } else if (collectionAsync instanceof Promise) { - // wait for the "collectionAsync", once resolved we will save it into the "collection" - // the collectionAsync can be of 3 types HttpClient, HttpFetch or a Promise - collectionAsync.then((response: any | any[]) => { - if (Array.isArray(response)) { - this.updateEditorCollection(column, response); // from Promise - } - }); - } - } - } - /** Load any possible Columns Grid Presets */ protected loadColumnPresetsWhenDatasetInitialized() { // if user entered some Columns "presets", we need to reflect them all in the grid @@ -1661,6 +1639,7 @@ export class AngularSlickgridComponent implements AfterViewInit, On this.backendUtilityService.addRxJsResource(this.rxjs); this.filterFactory.addRxJsResource(this.rxjs); this.filterService.addRxJsResource(this.rxjs); + this.gridStateService.addRxJsResource(this.rxjs); this.sortService.addRxJsResource(this.rxjs); this.paginationService.addRxJsResource(this.rxjs); this.containerService.registerInstance('RxJsResource', this.rxjs); @@ -1723,23 +1702,6 @@ export class AngularSlickgridComponent implements AfterViewInit, On return flatDatasetOutput; } - /** Prepare and load all SlickGrid editors, if an async editor is found then we'll also execute it. */ - protected loadSlickGridEditors(columns: Column[]): Column[] { - if (columns.some((col) => `${col.id}`.includes('.'))) { - console.warn( - '[Angular-Slickgrid] Make sure that none of your Column Definition "id" property includes a dot in its name because that will cause some problems with the Editors. For example if your column definition "field" property is "user.firstName" then use "firstName" as the column "id".' - ); - } - - return columns.map((column: Column | any) => { - // on every Editor that have a "collectionAsync", resolve the data and assign it to the "collection" property - if (column?.editor?.collectionAsync) { - this.loadEditorCollectionAsync(column); - } - return { ...column, editorClass: column.editor?.model }; - }); - } - protected suggestDateParsingWhenHelpful() { if ( this.dataView?.getItemCount() > WARN_NO_PREPARSE_DATE_SIZE && @@ -1753,23 +1715,4 @@ export class AngularSlickgridComponent implements AfterViewInit, On ); } } - - /** - * When the Editor(s) has a "editor.collection" property, we'll load the async collection. - * Since this is called after the async call resolves, the pointer will not be the same as the "column" argument passed. - */ - protected updateEditorCollection(column: Column, newCollection: T[]) { - if (this.slickGrid && column.editor) { - column.editor.collection = newCollection; - column.editor.disabled = false; - - // get current Editor, remove it from the DOM then re-enable it and re-render it with the new collection. - const currentEditor = this.slickGrid.getCellEditor() as AutocompleterEditor | SelectEditor; - if (currentEditor?.disable && currentEditor?.renderDomElement) { - currentEditor.destroy(); - currentEditor.disable(false); - currentEditor.renderDomElement(newCollection); - } - } - } } diff --git a/frameworks/aurelia-slickgrid/docs/grid-functionalities/row-detail.md b/frameworks/aurelia-slickgrid/docs/grid-functionalities/row-detail.md index 367d70506b..b80e86af7c 100644 --- a/frameworks/aurelia-slickgrid/docs/grid-functionalities/row-detail.md +++ b/frameworks/aurelia-slickgrid/docs/grid-functionalities/row-detail.md @@ -377,6 +377,9 @@ addNewColumn() { } ``` +> **Note** +> The code above is no lnger necessary with v10.8.0 and above. + ## Row Detail with Inner Grid You can also add an inner grid inside a Row Detail, however there are a few things to know off and remember. Any time a Row Detail is falling outside the main grid viewport, it will be unmounted and until it comes back into the viewport which is then remounted. The process of unmounting and remounting means that Row Detail previous states aren't preserved, however you could use Grid State & Presets to overcome this problem. diff --git a/frameworks/aurelia-slickgrid/docs/grid-functionalities/row-selection.md b/frameworks/aurelia-slickgrid/docs/grid-functionalities/row-selection.md index 5acc05a0c5..3a7d7e70a7 100644 --- a/frameworks/aurelia-slickgrid/docs/grid-functionalities/row-selection.md +++ b/frameworks/aurelia-slickgrid/docs/grid-functionalities/row-selection.md @@ -364,3 +364,6 @@ addNewColumn() { // this.aureliaGrid.slickGrid.setColumns(cols); } ``` + +> **Note** +> The code above is no lnger necessary with v10.8.0 and above. \ No newline at end of file diff --git a/frameworks/aurelia-slickgrid/src/custom-elements/aurelia-slickgrid.ts b/frameworks/aurelia-slickgrid/src/custom-elements/aurelia-slickgrid.ts index 093f4df289..14af68afc9 100644 --- a/frameworks/aurelia-slickgrid/src/custom-elements/aurelia-slickgrid.ts +++ b/frameworks/aurelia-slickgrid/src/custom-elements/aurelia-slickgrid.ts @@ -1,6 +1,5 @@ import type { ICollectionObserver, ICollectionSubscriber } from '@aurelia/runtime'; import type { - AutocompleterEditor, BackendService, BackendServiceApi, BackendServiceOption, @@ -15,7 +14,6 @@ import type { Metrics, Pagination, PaginationMetadata, - SelectEditor, } from '@slickgrid-universal/common'; import { autoAddEditorFormatterToColumnsWithEditor, @@ -360,7 +358,7 @@ export class AureliaSlickgridCustomElement { // and allow slickgrid to pass its arguments to the editors constructor last // when slickgrid creates the editor // https://github.com/aurelia/dependency-injection/blob/master/src/resolvers.js - this._columns = this.loadSlickGridEditors(this._columns); + this._columns = this.gridStateService.loadSlickGridEditors(this._columns); // if the user wants to automatically add a Custom Editor Formatter, we need to call the auto add function again if (this.options.autoAddCustomEditorFormatter) { @@ -1159,17 +1157,12 @@ export class AureliaSlickgridCustomElement { updateColumnDefinitionsList(newColumns: Column[]) { if (newColumns) { // map the Editor model to editorClass and load editor collectionAsync - newColumns = this.loadSlickGridEditors(newColumns); - - // if the user wants to automatically add a Custom Editor Formatter, we need to call the auto add function again - if (this.options.autoAddCustomEditorFormatter) { - autoAddEditorFormatterToColumnsWithEditor(newColumns, this.options.autoAddCustomEditorFormatter); - } + const updatedColumns = this.gridStateService.syncPluginColumns(newColumns, [...this.sharedService.allColumns, ...newColumns]); if (this.options.enableTranslate) { - this.extensionService.translateColumnHeaders(undefined, newColumns); + this.extensionService.translateColumnHeaders(undefined, updatedColumns); } - this.extensionService.renderColumnHeaders(newColumns, true); + this.extensionService.renderColumnHeaders(updatedColumns, true); if (this.options?.enableAutoSizeColumns) { this.grid.autosizeColumns(); @@ -1270,43 +1263,6 @@ export class AureliaSlickgridCustomElement { } } - /** Load the Editor Collection asynchronously and replace the "collection" property when Promise resolves */ - protected loadEditorCollectionAsync(column: Column) { - if (column?.editor) { - const collectionAsync = column.editor.collectionAsync; - column.editor.disabled = true; // disable the Editor DOM element, we'll re-enable it after receiving the collection with "updateEditorCollection()" - - if (collectionAsync instanceof Promise) { - // wait for the "collectionAsync", once resolved we will save it into the "collection" - // the collectionAsync can be of 3 types HttpClient, HttpFetch or a Promise - collectionAsync.then((response: any | any[]) => { - if (Array.isArray(response)) { - this.updateEditorCollection(column, response); // from Promise - } else if (response instanceof Response && typeof response.json === 'function') { - if (response.bodyUsed) { - console.warn( - `[Aurelia-SlickGrid] The response body passed to collectionAsync was already read. ` + - `Either pass the dataset from the Response or clone the response first using response.clone()` - ); - } else { - // from Fetch - (response as Response).json().then((data) => this.updateEditorCollection(column, data)); - } - } else if (response?.content) { - this.updateEditorCollection(column, response.content); // from http-client - } - }); - } else if (this.rxjs?.isObservable(collectionAsync)) { - // wrap this inside a microtask at the end of the task to avoid timing issue since updateEditorCollection requires to call SlickGrid getColumns() method after columns are available - queueMicrotask(() => { - this.subscriptions.push( - (collectionAsync as Observable).subscribe((resolvedCollection) => this.updateEditorCollection(column, resolvedCollection)) - ); - }); - } - } - } - /** Load any possible Columns Grid Presets */ protected loadColumnPresetsWhenDatasetInitialized() { // if user entered some Columns "presets", we need to reflect them all in the grid @@ -1570,6 +1526,7 @@ export class AureliaSlickgridCustomElement { this.backendUtilityService.addRxJsResource(this.rxjs); this.filterFactory.addRxJsResource(this.rxjs); this.filterService.addRxJsResource(this.rxjs); + this.gridStateService.addRxJsResource(this.rxjs); this.sortService.addRxJsResource(this.rxjs); this.paginationService.addRxJsResource(this.rxjs); this.containerService.registerInstance('RxJsResource', this.rxjs); @@ -1642,27 +1599,6 @@ export class AureliaSlickgridCustomElement { return flatDatasetOutput; } - /** Prepare and load all SlickGrid editors, if an async editor is found then we'll also execute it. */ - protected loadSlickGridEditors(columns: Column[]): Column[] { - if (columns.some((col) => `${col.id}`.includes('.'))) { - console.warn( - '[Aurelia-Slickgrid] Make sure that none of your Column Definition "id" property includes a dot in its name because that will cause some problems with the Editors. For example if your column definition "field" property is "user.firstName" then use "firstName" as the column "id".' - ); - } - - return columns.map((column: Column | any) => { - // on every Editor which have a "collection" or a "collectionAsync" - if (column.editor?.collectionAsync) { - this.loadEditorCollectionAsync(column); - } - - return { - ...column, - editorClass: column.editor && this.container.getFactory(column.editor.model).Type, - }; - }); - } - protected suggestDateParsingWhenHelpful() { if ( this.dataview?.getItemCount() > WARN_NO_PREPARSE_DATE_SIZE && @@ -1676,23 +1612,4 @@ export class AureliaSlickgridCustomElement { ); } } - - /** - * When the Editor(s) has a "editor.collection" property, we'll load the async collection. - * Since this is called after the async call resolves, the pointer will not be the same as the "column" argument passed. - */ - protected updateEditorCollection(column: Column, newCollection: T[]) { - if (this.grid && column.editor) { - column.editor.collection = newCollection; - column.editor.disabled = false; - - // get current Editor, remove it from the DOM then re-enable it and re-render it with the new collection. - const currentEditor = this.grid.getCellEditor() as AutocompleterEditor | SelectEditor; - if (currentEditor?.disable && currentEditor?.renderDomElement) { - currentEditor.destroy(); - currentEditor.disable(false); - currentEditor.renderDomElement(newCollection); - } - } - } } diff --git a/frameworks/slickgrid-react/docs/grid-functionalities/row-detail.md b/frameworks/slickgrid-react/docs/grid-functionalities/row-detail.md index c2592ce639..0ff41c6a13 100644 --- a/frameworks/slickgrid-react/docs/grid-functionalities/row-detail.md +++ b/frameworks/slickgrid-react/docs/grid-functionalities/row-detail.md @@ -478,6 +478,9 @@ const Example: React.FC = () => { } ``` +> **Note** +> The code above is no lnger necessary with v10.8.0 and above. + ## Row Detail with Inner Grid You can also add an inner grid inside a Row Detail, however there are a few things to know off and remember. Any time a Row Detail is falling outside the main grid viewport, it will be unmounted and until it comes back into the viewport which is then remounted. The process of unmounting and remounting means that Row Detail previous states aren't preserved, however you could use Grid State & Presets to overcome this problem. diff --git a/frameworks/slickgrid-react/docs/grid-functionalities/row-selection.md b/frameworks/slickgrid-react/docs/grid-functionalities/row-selection.md index 90767a09f0..0a8d3edd38 100644 --- a/frameworks/slickgrid-react/docs/grid-functionalities/row-selection.md +++ b/frameworks/slickgrid-react/docs/grid-functionalities/row-selection.md @@ -444,3 +444,6 @@ addNewColumn() { // reactGridRef.current?.slickGrid.setColumns(cols); } ``` + +> **Note** +> The code above is no lnger necessary with v10.8.0 and above. \ No newline at end of file diff --git a/frameworks/slickgrid-react/src/components/slickgrid-react.tsx b/frameworks/slickgrid-react/src/components/slickgrid-react.tsx index 19f43ad7b6..09d9384ba0 100644 --- a/frameworks/slickgrid-react/src/components/slickgrid-react.tsx +++ b/frameworks/slickgrid-react/src/components/slickgrid-react.tsx @@ -24,7 +24,6 @@ import { SlickGroupItemMetadataProvider, SortService, TreeDataService, - type AutocompleterEditor, type BackendService, type BackendServiceApi, type BackendServiceOption, @@ -40,7 +39,6 @@ import { type Pagination, type PaginationMetadata, type RxJsFacade, - type SelectEditor, } from '@slickgrid-universal/common'; import { SlickFooterComponent } from '@slickgrid-universal/custom-footer-component'; import { SlickEmptyWarningComponent } from '@slickgrid-universal/empty-warning-component'; @@ -501,7 +499,7 @@ export class SlickgridReact extends React.Component extends React.Component[]) { if (this.grid && this._options && Array.isArray(newColumns)) { // map the Editor model to editorClass and load editor collectionAsync - newColumns = this.loadSlickGridEditors(newColumns); - - // if the user wants to automatically add a Custom Editor Formatter, we need to call the auto add function again - if (this._options.autoAddCustomEditorFormatter) { - autoAddEditorFormatterToColumnsWithEditor(newColumns, this._options.autoAddCustomEditorFormatter); - } + const updatedColumns = this.gridStateService.syncPluginColumns(newColumns, [...this.sharedService.allColumns, ...newColumns]); if (this._options.enableTranslate) { - this.extensionService.translateColumnHeaders(undefined, newColumns); + this.extensionService.translateColumnHeaders(undefined, updatedColumns); } - this.extensionService.renderColumnHeaders(newColumns, true); + this.extensionService.renderColumnHeaders(updatedColumns, true); if (this._options?.enableAutoSizeColumns) { this.grid.autosizeColumns(); @@ -1375,43 +1368,6 @@ export class SlickgridReact extends React.Component { - if (Array.isArray(response)) { - this.updateEditorCollection(column, response); // from Promise - } else if (response instanceof Response && typeof response.json === 'function') { - if (response.bodyUsed) { - console.warn( - `[SlickGrid-React] The response body passed to collectionAsync was already read.` + - `Either pass the dataset from the Response or clone the response first using response.clone()` - ); - } else { - // from Fetch - (response as Response).json().then((data) => this.updateEditorCollection(column, data)); - } - } else if (response?.content) { - this.updateEditorCollection(column, response.content); // from http-client - } - }); - } else if (this.rxjs?.isObservable(collectionAsync)) { - // wrap this inside a microtask at the end of the task to avoid timing issue since updateEditorCollection requires to call SlickGrid getColumns() method after columns are available - queueMicrotask(() => { - this.subscriptions.push( - (collectionAsync as Observable).subscribe((resolvedCollection) => this.updateEditorCollection(column, resolvedCollection)) - ); - }); - } - } - } - /** Load any possible Columns Grid Presets */ protected loadColumnPresetsWhenDatasetInitialized() { // if user entered some Columns "presets", we need to reflect them all in the grid @@ -1624,6 +1580,7 @@ export class SlickgridReact extends React.Component extends React.Component[]): Column[] { - if (columns.some((col) => `${col?.id}`.includes('.'))) { - console.warn( - '[Slickgrid-React] Make sure that none of your Column Definition "id" property includes a dot in its name because that will cause some problems with the Editors. For example if your column definition "field" property is "user.firstName" then use "firstName" as the column "id".' - ); - } - - return columns.map((column: Column | any) => { - if (column) { - // on every Editor which have a "collection" or a "collectionAsync" - if (column.editor?.collectionAsync) { - this.loadEditorCollectionAsync(column); - } - return { ...column, editorClass: column.editor?.model }; - } - }); - } - protected suggestDateParsingWhenHelpful() { if ( this.dataView?.getItemCount() > WARN_NO_PREPARSE_DATE_SIZE && @@ -1693,25 +1631,6 @@ export class SlickgridReact extends React.Component(column: Column, newCollection: U[]) { - if (this.grid && column.editor) { - column.editor.collection = newCollection; - column.editor.disabled = false; - - // get current Editor, remove it from the DOM then re-enable it and re-render it with the new collection. - const currentEditor = this.grid.getCellEditor() as AutocompleterEditor | SelectEditor; - if (currentEditor?.disable && currentEditor?.renderDomElement) { - currentEditor.destroy(); - currentEditor.disable(false); - currentEditor.renderDomElement(newCollection); - } - } - } - render() { return (
**Note** +> The code above is no lnger necessary with v10.8.0 and above. + ## Row Detail with Inner Grid You can also add an inner grid inside a Row Detail, however there are a few things to know off and remember. Any time a Row Detail is falling outside the main grid viewport, it will be unmounted and until it comes back into the viewport which is then remounted. The process of unmounting and remounting means that Row Detail previous states aren't preserved, however you could use Grid State & Presets to overcome this problem. diff --git a/frameworks/slickgrid-vue/docs/grid-functionalities/row-selection.md b/frameworks/slickgrid-vue/docs/grid-functionalities/row-selection.md index 2c66d222db..f7cd7bdccd 100644 --- a/frameworks/slickgrid-vue/docs/grid-functionalities/row-selection.md +++ b/frameworks/slickgrid-vue/docs/grid-functionalities/row-selection.md @@ -512,3 +512,6 @@ function addNewColumn() { } ``` + +> **Note** +> The code above is no lnger necessary with v10.8.0 and above. \ No newline at end of file diff --git a/frameworks/slickgrid-vue/src/components/SlickgridVue.vue b/frameworks/slickgrid-vue/src/components/SlickgridVue.vue index 970f2674d4..877c6eb71f 100644 --- a/frameworks/slickgrid-vue/src/components/SlickgridVue.vue +++ b/frameworks/slickgrid-vue/src/components/SlickgridVue.vue @@ -25,7 +25,6 @@ import { SlickGroupItemMetadataProvider, SortService, TreeDataService, - type AutocompleterEditor, type BackendServiceApi, type BackendServiceOption, type BasePaginationComponent, @@ -42,7 +41,6 @@ import { type Pagination, type PaginationMetadata, type RxJsFacade, - type SelectEditor, } from '@slickgrid-universal/common'; import { SlickFooterComponent } from '@slickgrid-universal/custom-footer-component'; import { SlickEmptyWarningComponent } from '@slickgrid-universal/empty-warning-component'; @@ -438,7 +436,7 @@ function initialization() { // Wrap each editor class in the Factory resolver so consumers of this library. // Vue will allow slickgrid to pass its arguments to the editors constructor last // when slickgrid creates the editor - _columns.value = loadSlickGridEditors(columnsModel.value || []); + _columns.value = gridStateService.loadSlickGridEditors(columnsModel.value || []); // if the user wants to automatically add a Custom Editor Formatter, we need to call the auto add function again if (_gridOptions.value.autoAddCustomEditorFormatter) { @@ -1158,17 +1156,12 @@ function setDarkMode(dark = false) { function updateColumnsList(newColumns: Column[]) { if (newColumns) { // map the Editor model to editorClass and load editor collectionAsync - newColumns = loadSlickGridEditors(newColumns); - - // if the user wants to automatically add a Custom Editor Formatter, we need to call the auto add function again - if (_gridOptions.value.autoAddCustomEditorFormatter) { - autoAddEditorFormatterToColumnsWithEditor(newColumns, _gridOptions.value.autoAddCustomEditorFormatter); - } + const updatedColumns = gridStateService.syncPluginColumns(newColumns, [...sharedService.allColumns, ...newColumns]); if (_gridOptions.value.enableTranslate) { - extensionService.translateColumnHeaders(undefined, newColumns); + extensionService.translateColumnHeaders(undefined, updatedColumns); } - extensionService.renderColumnHeaders(newColumns, true); + extensionService.renderColumnHeaders(updatedColumns, true); if (_gridOptions.value?.enableAutoSizeColumns) { grid?.autosizeColumns(); @@ -1245,43 +1238,6 @@ function initializePaginationService(paginationOptions: Pagination) { } } -/** Load the Editor Collection asynchronously and replace the "collection" property when Promise resolves */ -function loadEditorCollectionAsync(column: Column) { - if (column?.editor) { - const collectionAsync = column.editor.collectionAsync; - column.editor.disabled = true; // disable the Editor DOM element, we'll re-enable it after receiving the collection with "updateEditorCollection()" - - if (collectionAsync instanceof Promise) { - // wait for the "collectionAsync", once resolved we will save it into the "collection" - // the collectionAsync can be of 3 types HttpClient, HttpFetch or a Promise - collectionAsync.then((response: any | any[]) => { - if (Array.isArray(response)) { - updateEditorCollection(column, response); // from Promise - } else if (response instanceof Response && typeof response.json === 'function') { - if (response.bodyUsed) { - console.warn( - `[SlickGrid-Vue] The response body passed to collectionAsync was already read. ` + - `Either pass the dataset from the Response or clone the response first using response.clone()` - ); - } else { - // from Fetch - (response as Response).json().then((data) => updateEditorCollection(column, data)); - } - } else if (response?.content) { - updateEditorCollection(column, response.content); // from http-client - } - }); - } else if (rxjs?.isObservable(collectionAsync)) { - // wrap this inside a microtask at the end of the task to avoid timing issue since updateEditorCollection requires to call SlickGrid getColumns() method after columns are available - queueMicrotask(() => { - subscriptions.push( - (collectionAsync as Observable).subscribe((resolvedCollection) => updateEditorCollection(column, resolvedCollection)) - ); - }); - } - } -} - /** Load any possible Columns Grid Presets */ function loadColumnPresetsWhenDatasetInitialized() { // if user entered some Columns "presets", we need to reflect them all in the grid @@ -1528,6 +1484,7 @@ function registerRxJsResource(resource: RxJsFacade) { backendUtilityService.addRxJsResource(rxjs); filterFactory.addRxJsResource(rxjs); filterService.addRxJsResource(rxjs); + gridStateService.addRxJsResource(rxjs); sortService.addRxJsResource(rxjs); paginationService.addRxJsResource(rxjs); containerService.registerInstance('RxJsResource', rxjs); @@ -1601,24 +1558,6 @@ function sortTreeDataset(flatDatasetInput: T[], forceGridRefresh = false): T[ return flatDatasetOutput; } -/** Prepare and load all SlickGrid editors, if an async editor is found then we'll also execute it. */ -function loadSlickGridEditors(columns: Column[]): Column[] { - if (columns.some((col) => `${col.id}`.includes('.'))) { - console.warn( - '[Slickgrid-Vue] Make sure that none of your Column Definition "id" property includes a dot in its name because that will cause some problems with the Editors. For example if your column definition "field" property is "user.firstName" then use "firstName" as the column "id".' - ); - } - - return columns.map((column: Column | any) => { - // on every Editor which have a "collection" or a "collectionAsync" - if (column.editor?.collectionAsync) { - loadEditorCollectionAsync(column); - } - - return { ...column, editorClass: column.editor?.model }; - }); -} - function suggestDateParsingWhenHelpful() { if ( dataview!.getItemCount() > WARN_NO_PREPARSE_DATE_SIZE && @@ -1632,25 +1571,6 @@ function suggestDateParsingWhenHelpful() { ); } } - -/** - * When the Editor(s) has a "editor.collection" property, we'll load the async collection. - * Since this is called after the async call resolves, the pointer will not be the same as the "column" argument passed. - */ -function updateEditorCollection(column: Column, newCollection: T[]) { - if (grid && column.editor) { - column.editor.collection = newCollection; - column.editor.disabled = false; - - // get current Editor, remove it from the DOM then re-enable it and re-render it with the new collection. - const currentEditor = grid.getCellEditor() as AutocompleterEditor | SelectEditor; - if (currentEditor?.disable && currentEditor?.renderDomElement) { - currentEditor.destroy(); - currentEditor.disable(false); - currentEditor.renderDomElement(newCollection); - } - } -}