Skip to content

Commit

Permalink
feat(dataView): add option to apply row selection to all pages
Browse files Browse the repository at this point in the history
  • Loading branch information
ghiscoding committed Feb 4, 2023
1 parent c5f0dc4 commit e6335be
Show file tree
Hide file tree
Showing 15 changed files with 398 additions and 152 deletions.
26 changes: 13 additions & 13 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -50,13 +50,13 @@
},
"dependencies": {
"@ngx-translate/core": ">=14.0.0",
"@slickgrid-universal/common": "~2.3.0",
"@slickgrid-universal/custom-footer-component": "~2.3.0",
"@slickgrid-universal/empty-warning-component": "~2.3.0",
"@slickgrid-universal/event-pub-sub": "~2.3.0",
"@slickgrid-universal/pagination-component": "~2.3.0",
"@slickgrid-universal/row-detail-view-plugin": "~2.3.0",
"@slickgrid-universal/rxjs-observable": "~2.3.0",
"@slickgrid-universal/common": "~2.4.0",
"@slickgrid-universal/custom-footer-component": "~2.4.0",
"@slickgrid-universal/empty-warning-component": "~2.4.0",
"@slickgrid-universal/event-pub-sub": "~2.4.0",
"@slickgrid-universal/pagination-component": "~2.4.0",
"@slickgrid-universal/row-detail-view-plugin": "~2.4.0",
"@slickgrid-universal/rxjs-observable": "~2.4.0",
"@types/jquery": "^3.5.16",
"dequal": "^2.0.3",
"dompurify": "^2.4.3",
Expand Down Expand Up @@ -88,12 +88,12 @@
"@ngx-translate/core": "^14.0.0",
"@ngx-translate/http-loader": "^7.0.0",
"@release-it/conventional-changelog": "^5.1.1",
"@slickgrid-universal/composite-editor-component": "~2.3.0",
"@slickgrid-universal/custom-tooltip-plugin": "~2.3.0",
"@slickgrid-universal/excel-export": "~2.3.0",
"@slickgrid-universal/graphql": "~2.3.0",
"@slickgrid-universal/odata": "~2.3.0",
"@slickgrid-universal/text-export": "~2.3.0",
"@slickgrid-universal/composite-editor-component": "~2.4.0",
"@slickgrid-universal/custom-tooltip-plugin": "~2.4.0",
"@slickgrid-universal/excel-export": "~2.4.0",
"@slickgrid-universal/graphql": "~2.4.0",
"@slickgrid-universal/odata": "~2.4.0",
"@slickgrid-universal/text-export": "~2.4.0",
"@types/dompurify": "^2.4.0",
"@types/flatpickr": "^3.1.2",
"@types/fnando__sparkline": "^0.3.4",
Expand Down
5 changes: 4 additions & 1 deletion src/app/examples/grid-headermenu.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,10 @@ export class GridHeaderMenuComponent implements OnInit, OnDestroy {
selectedLanguage: string;

constructor(private translate: TranslateService) {
this.selectedLanguage = this.translate.getDefaultLang();
// always start with English for Cypress E2E tests to be consistent
const defaultLang = 'en';
this.translate.use(defaultLang);
this.selectedLanguage = defaultLang;
}

ngOnDestroy() {
Expand Down
10 changes: 8 additions & 2 deletions src/app/examples/grid-resize-by-content.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,14 @@ <h4 class="ml-3">Container Width (950px)</h4>

<div class="mb-2">
<div class="btn-group btn-group-sm" role="group" aria-label="Basic Editing Commands">
<button type="button" class="btn btn-outline-secondary" (click)="setSelectedRowIds()"
data-test="set-dynamic-rows-btn"
title="Change Row Selection across multiple pages">
<span>Change Row Selection</span>
</button>
<button type="button" class="btn btn-outline-secondary" data-test="toggle-readonly-btn"
(click)="toggleGridEditReadonly()">
<i class="fa fa-table"></i> Toggle Edit/Readonly Grid
<i class="fa fa-table"></i> Toggle Readonly
</button>
<button type="button" class="btn btn-outline-secondary" data-test="undo-last-edit-btn"
(click)="undoLastEdit()">
Expand All @@ -56,7 +61,8 @@ <h4 class="ml-3">Container Width (950px)</h4>
[columnDefinitions]="columnDefinitions"
[gridOptions]="gridOptions"
[dataset]="dataset"
(onAngularGridCreated)="angularGridReady($event.detail)">
(onAngularGridCreated)="angularGridReady($event.detail)"
(onSelectedRowIdsChanged)="handleOnSelectedRowIdsChanged($event.detail.args)">
</angular-slickgrid>
</div>
</div>
23 changes: 22 additions & 1 deletion src/app/examples/grid-resize-by-content.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ export class GridResizeByContentComponent implements OnInit {

ngOnInit(): void {
this.defineGrid();
this.dataset = this.loadData(5000);
this.dataset = this.loadData(400);
}

// Grid2 definition
Expand Down Expand Up @@ -303,6 +303,11 @@ export class GridResizeByContentComponent implements OnInit {
rightPadding: 10
},
enableAutoResize: true,
enablePagination: true,
pagination: {
pageSize: 10,
pageSizes: [10, 200, 500, 5000]
},

// resizing by cell content is opt-in
// we first need to disable the 2 default flags to autoFit/autosize
Expand Down Expand Up @@ -463,6 +468,10 @@ export class GridResizeByContentComponent implements OnInit {
this.isUsingDefaultResize = false;
}

handleOnSelectedRowIdsChanged(args: any) {
console.log('Selected Ids:', args.selectedRowIds);
}

toggleGridEditReadonly() {
// first need undo all edits
this.undoAllEdits();
Expand Down Expand Up @@ -517,6 +526,18 @@ export class GridResizeByContentComponent implements OnInit {
}
}

// change row selection dynamically and apply it to the DataView and the Grid UI
setSelectedRowIds() {
// change row selection even across multiple pages via DataView
this.angularGrid.dataView?.setSelectedIds([3, 4, 11]);

// you can also provide optional options (all defaults to true)
// this.sgb.dataView?.setSelectedIds([4, 5, 8, 10], {
// isRowBeingAdded: true,
// shouldTriggerEvent: true,
// applyGridRowSelection: true
// });
}

saveAll() {
// Edit Queue (array increases every time a cell is changed, regardless of item object)
Expand Down
12 changes: 8 additions & 4 deletions src/app/examples/grid-rowselection.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,8 @@ export class GridRowSelectionComponent implements OnInit {
gridObj1!: any;
gridObj2!: any;
isGrid2WithPagination = true;
selectedTitles!: any[];
selectedTitle!: any;
selectedTitles = '';
selectedTitle = '';
selectedGrid2IDs!: number[];

constructor(private cd: ChangeDetectorRef) { }
Expand Down Expand Up @@ -158,7 +158,8 @@ export class GridRowSelectionComponent implements OnInit {
checkboxSelector: {
// you can toggle these 2 properties to show the "select all" checkbox in different location
hideInFilterHeaderRow: false,
hideInColumnTitleRow: true
hideInColumnTitleRow: true,
applySelectOnAllPages: true, // when clicking "Select All", should we apply it to all pages (defaults to true)
},
rowSelectionOptions: {
// True (Single Selection), False (Multiple Selections)
Expand Down Expand Up @@ -243,7 +244,10 @@ export class GridRowSelectionComponent implements OnInit {
if (gridStateChanges!.gridState!.rowSelection) {
this.selectedGrid2IDs = (gridStateChanges!.gridState!.rowSelection.filteredDataContextIds || []) as number[];
this.selectedGrid2IDs = this.selectedGrid2IDs.sort((a, b) => a - b); // sort by ID
this.selectedTitles = this.selectedGrid2IDs.map(dataContextId => `Task ${dataContextId}`);
this.selectedTitles = this.selectedGrid2IDs.map(dataContextId => `Task ${dataContextId}`).join(',');
if (this.selectedTitles.length > 293) {
this.selectedTitles = this.selectedTitles.substring(0, 293) + '...';
}
this.cd.detectChanges();
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/app/examples/grid-state.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,9 +72,9 @@ export class GridStateComponent implements OnInit, OnDestroy {

/** Clear the Grid State from Local Storage and reset the grid to it's original state */
clearGridStateFromLocalStorage() {
localStorage.removeItem(LOCAL_STORAGE_KEY);
this.angularGrid.gridService.resetGrid(this.columnDefinitions);
this.angularGrid.paginationService!.changeItemPerPage(DEFAULT_PAGE_SIZE);
setTimeout(() => localStorage[LOCAL_STORAGE_KEY] = null);
}

/* Define grid Options and Columns */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,7 @@ const mockDataView = {
onSetItemsCalled: new MockSlickEvent(),
reSort: jest.fn(),
setItems: jest.fn(),
setSelectedIds: jest.fn(),
syncGridSelection: jest.fn(),
};

Expand Down Expand Up @@ -1667,13 +1668,16 @@ describe('Angular-Slickgrid Custom Component instantiated via Constructor', () =
});
});

it('should call trigger a gridStage change and reset selected rows when pagination change is triggered and "enableRowSelection" is set', () => {
it('should trigger a gridStage change and reset selected rows when pagination change is triggered and "enableRowSelection" is set', () => {
const mockPagination = { pageNumber: 2, pageSize: 20 } as Pagination;
const pluginEaSpy = jest.spyOn(eventPubSubService, 'publish');
const setRowSpy = jest.spyOn(mockGrid, 'setSelectedRows');
jest.spyOn(gridStateServiceStub, 'getCurrentGridState').mockReturnValue({ columns: [], pagination: mockPagination } as GridState);

component.gridOptions = { enableRowSelection: true } as unknown as GridOption;
component.gridOptions = {
enableRowSelection: true,
backendServiceApi: { service: mockGraphqlService as any }
} as unknown as GridOption;
component.initialization(slickEventHandler);
component.paginationChanged(mockPagination);

Expand All @@ -1690,7 +1694,10 @@ describe('Angular-Slickgrid Custom Component instantiated via Constructor', () =
const setRowSpy = jest.spyOn(mockGrid, 'setSelectedRows');
jest.spyOn(gridStateServiceStub, 'getCurrentGridState').mockReturnValue({ columns: [], pagination: mockPagination } as GridState);

component.gridOptions = { enableCheckboxSelector: true } as unknown as GridOption;
component.gridOptions = {
enableCheckboxSelector: true,
backendServiceApi: { service: mockGraphqlService as any }
} as unknown as GridOption;
component.initialization(slickEventHandler);
component.paginationChanged(mockPagination);

Expand Down Expand Up @@ -1945,10 +1952,11 @@ describe('Angular-Slickgrid Custom Component instantiated via Constructor', () =
});
});

it('should NOT call the "setSelectedRows" when the Grid has Local Pagination and there are row selection presets with "dataContextIds" array set', (done) => {
it('should call the "setSelectedRows" and "setSelectedIds" when the Grid has Local Pagination and there are row selection presets with "dataContextIds" array set', () => {
const selectedGridRows = [22];
const mockData = [{ firstName: 'John', lastName: 'Doe' }, { firstName: 'Jane', lastName: 'Smith' }];
const selectRowSpy = jest.spyOn(mockGrid, 'setSelectedRows');
const gridSelectedRowSpy = jest.spyOn(mockGrid, 'setSelectedRows');
const dvSetSelectedIdSpy = jest.spyOn(mockDataView, 'setSelectedIds');
jest.spyOn(mockGrid, 'getSelectionModel').mockReturnValue(true);
jest.spyOn(mockDataView, 'getLength').mockReturnValue(mockData.length);

Expand All @@ -1962,11 +1970,9 @@ describe('Angular-Slickgrid Custom Component instantiated via Constructor', () =
component.isDatasetInitialized = false; // it won't call the preset unless we reset this flag
component.initialization(slickEventHandler);

setTimeout(() => {
expect(component.isDatasetInitialized).toBe(true);
expect(selectRowSpy).not.toHaveBeenCalled();
done();
}, 2);
expect(component.isDatasetInitialized).toBe(true);
expect(gridSelectedRowSpy).toHaveBeenCalledWith([2]);
expect(dvSetSelectedIdSpy).toHaveBeenCalledWith([22], { applyRowSelectionToGrid: true, isRowBeingAdded: true, shouldTriggerEvent: false });
});
});

Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
// import 3rd party vendor libs
import 'slickgrid/dist/slick.core.min';
import 'slickgrid/dist/slick.interactions.min';
import 'slickgrid/dist/slick.grid.min';
import 'slickgrid/dist/slick.dataview.min';
import 'slickgrid/slick.core';
import 'slickgrid/slick.interactions';
import 'slickgrid/slick.grid';
import 'slickgrid/slick.dataview';

// ...then everything else...
import { AfterViewInit, ApplicationRef, ChangeDetectorRef, Component, ElementRef, EventEmitter, Inject, Input, OnDestroy, Optional, Output, } from '@angular/core';
Expand Down Expand Up @@ -662,11 +662,11 @@ export class AngularSlickgridComponent implements AfterViewInit, OnDestroy {

/**
* On a Pagination changed, we will trigger a Grid State changed with the new pagination info
* Also if we use Row Selection or the Checkbox Selector, we need to reset any selection
* Also if we use Row Selection or the Checkbox Selector with a Backend Service (Odata, GraphQL), we need to reset any selection
*/
paginationChanged(pagination: ServicePagination) {
const isSyncGridSelectionEnabled = this.gridStateService?.needToPreserveRowSelection() ?? false;
if (!isSyncGridSelectionEnabled && (this.gridOptions.enableRowSelection || this.gridOptions.enableCheckboxSelector)) {
if (this.slickGrid && !isSyncGridSelectionEnabled && this.gridOptions?.backendServiceApi && (this.gridOptions.enableRowSelection || this.gridOptions.enableCheckboxSelector)) {
this.slickGrid.setSelectedRows([]);
}
const { pageNumber, pageSize } = pagination;
Expand Down Expand Up @@ -1179,16 +1179,14 @@ export class AngularSlickgridComponent implements AfterViewInit, OnDestroy {
} else if (Array.isArray(gridRowIndexes) && gridRowIndexes.length > 0) {
dataContextIds = this.dataView.mapRowsToIds(gridRowIndexes) || [];
}
this.gridStateService.selectedRowDataContextIds = dataContextIds;

// change the selected rows except UNLESS it's a Local Grid with Pagination
// local Pagination uses the DataView and that also trigger a change/refresh
// and we don't want to trigger 2 Grid State changes just 1
if ((this._isLocalGrid && !this.gridOptions.enablePagination) || !this._isLocalGrid) {
setTimeout(() => {
if (this.slickGrid && Array.isArray(gridRowIndexes)) {
this.slickGrid.setSelectedRows(gridRowIndexes);
}
// apply row selection when defined as grid presets
if (this.slickGrid && Array.isArray(gridRowIndexes)) {
this.slickGrid.setSelectedRows(gridRowIndexes);
this.dataView!.setSelectedIds(dataContextIds || [], {
isRowBeingAdded: true,
shouldTriggerEvent: false, // do not trigger when presetting the grid
applyRowSelectionToGrid: true
});
}
}
Expand Down
6 changes: 5 additions & 1 deletion src/app/modules/angular-slickgrid/global-grid-options.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,11 @@ export const GlobalGridOptions: Partial<GridOption> = {
}
},
dataView: {
syncGridSelection: true, // when enabled, this will preserve the row selection even after filtering/sorting/grouping
// when enabled, this will preserve the row selection even after filtering/sorting/grouping
syncGridSelection: {
preserveHidden: false,
preserveHiddenOnSelectionChange: true
},
syncGridSelectionWithBackendService: false, // but disable it when using backend services
},
datasetIdPropertyName: 'id',
Expand Down
4 changes: 2 additions & 2 deletions test/cypress/e2e/example01.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,13 @@ describe('Example 1 - Basic Grids', { retries: 1 }, () => {
.should('have.css', 'width', '800px');

cy.get('#slickGridContainer-grid1 > .slickgrid-container')
.should('have.css', 'height', '225px');
.should($el => expect(parseInt(`${$el.height()}`, 10)).to.eq(225));

cy.get('#slickGridContainer-grid2')
.should('have.css', 'width', '800px');

cy.get('#slickGridContainer-grid2 > .slickgrid-container')
.should('have.css', 'height', '225px');
.should($el => expect(parseInt(`${$el.height()}`, 10)).to.eq(225));
});

it('should have exact column titles on 1st grid', () => {
Expand Down
2 changes: 1 addition & 1 deletion test/cypress/e2e/example06.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ describe('Example 6 - GraphQL Grid', { retries: 1 }, () => {
.should('have.css', 'width', '900px');

cy.get('#slickGridContainer-grid6 > .slickgrid-container')
.should('have.css', 'height', '200px');
.should($el => expect(parseInt(`${$el.height()}`, 10)).to.eq(200));
});

it('should have English Text inside some of the Filters', () => {
Expand Down
Loading

0 comments on commit e6335be

Please sign in to comment.