Skip to content

Commit

Permalink
feat: add name option to CheckboxSelectColumn plugin on columDef (#…
Browse files Browse the repository at this point in the history
…1331)

- this will only work when the "Select All" checkbox is NOT shown in the column header titles row (`hideInColumnTitleRow: true`)
  • Loading branch information
ghiscoding committed Jan 15, 2024
1 parent b483e62 commit abe344b
Show file tree
Hide file tree
Showing 8 changed files with 166 additions and 27 deletions.
8 changes: 6 additions & 2 deletions examples/vite-demo-vanilla-bundle/src/examples/example04.html
Expand Up @@ -35,14 +35,18 @@ <h6 class="title is-6 italic">
<span class="icon mdi mdi-close"></span>
<span>Remove Frozen Columns</span>
</button>
<button class="button is-small" onclick.delegate="setFrozenColumns(2)" data-test="set-3frozen-columns">
<button class="button is-small" data-test="set-3frozen-columns" onclick.delegate="setFrozenColumns(2)">
<span class="icon mdi mdi-pin-outline"></span>
<span>Set 3 Frozen Columns</span>
</button>
<button class="button is-small" onclick.delegate="toggleFrozenBottomRows()">
<button class="button is-small" data-test="toggle-frozen-bottom" onclick.delegate="toggleFrozenBottomRows()">
<span class="icon mdi mdi-flip-vertical"></span>
<span>Toggle Pinned Rows (top/bottom)</span>
</button>
<button class="button is-small ml-3" data-test="toggle-select-all-row" onclick.delegate="toggleWhichRowToShowSelectAll()">
<span class="icon mdi mdi-swap-horizontal mdi-rotate-90"></span>
<span>Toggle which row to show "Select All" checkbox</span>
</button>
</span>
</div>

Expand Down
17 changes: 17 additions & 0 deletions examples/vite-demo-vanilla-bundle/src/examples/example04.ts
Expand Up @@ -11,6 +11,7 @@ import {
type GridOption,
OperatorType,
type SlickDataView,
type SlickCheckboxSelectColumn,
} from '@slickgrid-universal/common';
import { BindingEventService } from '@slickgrid-universal/binding';
import { ExcelExportService } from '@slickgrid-universal/excel-export';
Expand Down Expand Up @@ -61,6 +62,8 @@ export default class Example04 {
frozenRowCount = 3;
isFrozenBottom = false;
sgb: SlickVanillaGridBundle;
checkboxSelectorInstance: SlickCheckboxSelectColumn;
isSelectAllShownAsColumnTitle = false;

constructor() {
this._bindingEventService = new BindingEventService();
Expand Down Expand Up @@ -372,6 +375,12 @@ export default class Example04 {
selectActiveRow: false
},
enableCheckboxSelector: true,
checkboxSelector: {
hideInColumnTitleRow: !this.isSelectAllShownAsColumnTitle,
hideInFilterHeaderRow: this.isSelectAllShownAsColumnTitle,
name: 'Sel', // column name will only show when `hideInColumnTitleRow` is true
onExtensionRegistered: (instance) => this.checkboxSelectorInstance = instance,
},
enableRowSelection: true,
frozenColumn: this.frozenColumnCount,
frozenRow: this.frozenRowCount,
Expand Down Expand Up @@ -546,6 +555,14 @@ export default class Example04 {
}
}

toggleWhichRowToShowSelectAll() {
this.isSelectAllShownAsColumnTitle = !this.isSelectAllShownAsColumnTitle;
this.checkboxSelectorInstance.setOptions({
hideInColumnTitleRow: !this.isSelectAllShownAsColumnTitle,
hideInFilterHeaderRow: this.isSelectAllShownAsColumnTitle,
});
}

executeCommand(_e, args) {
// const columnDef = args.column;
const command = args.command;
Expand Down
Expand Up @@ -64,14 +64,6 @@ const gridStub = {
onSelectedRowsChanged: new SlickEvent(),
} as unknown as SlickGrid;

const mockAddon = jest.fn().mockImplementation(() => ({
init: jest.fn(),
dispose: jest.fn(),
getColumnDefinition: jest.fn(),
onBeforeMoveRows: new SlickEvent(),
onMoveRows: new SlickEvent(),
}));

const mockRowSelectionModel = {
constructor: jest.fn(),
init: jest.fn(),
Expand Down Expand Up @@ -121,6 +113,7 @@ describe('SlickCheckboxSelectColumn Plugin', () => {
cssClass: null,
field: '_checkbox_selector',
hideSelectAllCheckbox: false,
name: '',
toolTip: 'Select/Deselect All',
width: 30,
hideInColumnTitleRow: false,
Expand All @@ -144,6 +137,7 @@ describe('SlickCheckboxSelectColumn Plugin', () => {
cssClass: 'some-class',
field: '_checkbox_selector',
hideSelectAllCheckbox: true,
name: '',
toolTip: 'Select/Deselect All',
width: 30,
hideInColumnTitleRow: true,
Expand All @@ -162,6 +156,17 @@ describe('SlickCheckboxSelectColumn Plugin', () => {
expect(updateColHeaderSpy).toHaveBeenCalledWith('_checkbox_selector', '', '');
});

it('should create the plugin and call "setOptions" and expect options changed and call grid "updateColumnHeader()" when setting "hideInColumnTitleRow: true" and a column "name"', () => {
const colName = 'Selection';
const updateColHeaderSpy = jest.spyOn(gridStub, 'updateColumnHeader');

plugin.init(gridStub);
plugin.setOptions({ hideInColumnTitleRow: true, hideSelectAllCheckbox: false, cssClass: 'some-class', name: colName });

expect(plugin).toBeTruthy();
expect(updateColHeaderSpy).toHaveBeenCalledWith('_checkbox_selector', colName, '');
});

it('should create the plugin and call "setOptions" and expect options changed and render the Select All toggle when "hideInColumnTitleRow: false"', () => {
const updateColHeaderSpy = jest.spyOn(gridStub, 'updateColumnHeader');
jest.spyOn(gridStub.getEditorLock(), 'isActive').mockReturnValue(true);
Expand Down Expand Up @@ -463,6 +468,30 @@ describe('SlickCheckboxSelectColumn Plugin', () => {
});
});

it('should add a "name" and "hideSelectAllCheckbox: true" and call the "create" method and expect plugin to be created with a column name and without a checkbox', () => {
const colName = 'Selection';
plugin.create(mockColumns, { checkboxSelector: { columnIndexPosition: 1, name: colName, hideSelectAllCheckbox: true } });

expect(plugin).toBeTruthy();
expect(mockColumns[1]).toEqual({
cssClass: null,
excludeFromColumnPicker: true,
excludeFromExport: true,
excludeFromGridMenu: true,
excludeFromHeaderMenu: true,
excludeFromQuery: true,
field: '_checkbox_selector',
formatter: expect.toBeFunction(),
hideSelectAllCheckbox: true,
id: '_checkbox_selector',
name: colName,
resizable: false,
sortable: false,
toolTip: '',
width: 30,
});
});

it('should process the "checkboxSelectionFormatter" and expect necessary Formatter to return null when selectableOverride is returning False', () => {
plugin.selectableOverride(() => false);
plugin.create(mockColumns, {});
Expand Down
10 changes: 8 additions & 2 deletions packages/common/src/extensions/slickCheckboxSelectColumn.ts
Expand Up @@ -14,6 +14,7 @@ export class SlickCheckboxSelectColumn<T = any> {
cssClass: null,
field: '_checkbox_selector',
hideSelectAllCheckbox: false,
name: '',
toolTip: 'Select/Deselect All',
width: 30,
applySelectOnAllPages: true, // when that is enabled the "Select All" will be applied to all pages (when using Pagination)
Expand Down Expand Up @@ -158,6 +159,9 @@ export class SlickCheckboxSelectColumn<T = any> {
this._eventHandler.subscribe(this._grid.onHeaderClick, this.handleHeaderClick.bind(this));
} else {
this.hideSelectAllFromColumnHeaderTitleRow();
if (this._addonOptions.name) {
this._grid.updateColumnHeader(this._addonOptions.columnId || '', this._addonOptions.name, '');
}
}

if (!this._addonOptions.hideInFilterHeaderRow) {
Expand Down Expand Up @@ -203,7 +207,9 @@ export class SlickCheckboxSelectColumn<T = any> {

return {
id: columnId,
name: (this._addonOptions.hideSelectAllCheckbox || this._addonOptions.hideInColumnTitleRow) ? '' : `<input id="header-selector${this._selectAll_UID}" type="checkbox"><label for="header-selector${this._selectAll_UID}"></label>`,
name: (this._addonOptions.hideSelectAllCheckbox || this._addonOptions.hideInColumnTitleRow)
? this._addonOptions.name || ''
: `<input id="header-selector${this._selectAll_UID}" type="checkbox"><label for="header-selector${this._selectAll_UID}"></label>`,
toolTip: (this._addonOptions.hideSelectAllCheckbox || this._addonOptions.hideInColumnTitleRow) ? '' : this._addonOptions.toolTip,
field: columnId,
cssClass: this._addonOptions.cssClass,
Expand All @@ -221,7 +227,7 @@ export class SlickCheckboxSelectColumn<T = any> {
}

hideSelectAllFromColumnHeaderTitleRow() {
this._grid.updateColumnHeader(this._addonOptions.columnId || '', '', '');
this._grid.updateColumnHeader(this._addonOptions.columnId || '', this._addonOptions.name || '', '');
}

hideSelectAllFromColumnHeaderFilterRow() {
Expand Down
13 changes: 13 additions & 0 deletions packages/common/src/interfaces/checkboxSelectorOption.interface.ts
@@ -1,5 +1,6 @@
import type { SlickEventData } from '../core';
import type { UsabilityOverrideFn } from '../enums/usabilityOverrideFn.type';
import type { SlickCheckboxSelectColumn } from '../extensions/slickCheckboxSelectColumn';

export interface CheckboxSelectorOption {
/**
Expand Down Expand Up @@ -33,6 +34,12 @@ export interface CheckboxSelectorOption {
/** defaults to true, do we want to hide the "Select All" checkbox from the Column Header Filter Row? */
hideInFilterHeaderRow?: boolean;

/**
* defaults to empty string, column name.
* This will only work when the "Select All" checkbox is NOT shown in the column header row (`hideInColumnTitleRow: true`)
*/
name?: string;

/** Defaults to "Select/Deselect All", provide a tooltip that will be shown over the "Select All" checkbox */
toolTip?: string;

Expand All @@ -42,6 +49,12 @@ export interface CheckboxSelectorOption {
/** Override the logic for showing (or not) the expand icon (use case example: only every 2nd row is expandable) */
selectableOverride?: UsabilityOverrideFn;

// --
// Events

/** Fired after extension is registered by SlickGrid */
onExtensionRegistered?: (plugin: SlickCheckboxSelectColumn) => void;

/** Optional callback method to be executed when the row checkbox gets clicked but prior to the actual toggling itself. */
onRowToggleStart?: (e: SlickEventData | Event | null, args: { row: number; previousSelectedRows: number[]; }) => void;

Expand Down
36 changes: 31 additions & 5 deletions packages/common/src/services/__tests__/extension.service.spec.ts
Expand Up @@ -311,7 +311,7 @@ describe('ExtensionService', () => {

it('should register the ColumnPicker addon when "enableColumnPicker" is set in the grid options', () => {
const gridOptionsMock = { enableColumnPicker: true } as GridOption;
jest.spyOn(extensionColumnPickerStub, 'register').mockReturnValue(instanceMock);
jest.spyOn(extensionColumnPickerStub, 'register').mockReturnValueOnce(instanceMock);
const gridSpy = jest.spyOn(SharedService.prototype, 'gridOptions', 'get').mockReturnValue(gridOptionsMock);

service.bindDifferentExtensions();
Expand Down Expand Up @@ -382,7 +382,7 @@ describe('ExtensionService', () => {
it('should register the CheckboxSelector addon when "enableCheckboxSelector" is set in the grid options', () => {
const columnsMock = [{ id: 'field1', field: 'field1', width: 100, cssClass: 'red' }] as Column[];
const gridOptionsMock = { enableCheckboxSelector: true } as GridOption;
const extCreateSpy = jest.spyOn(mockCheckboxSelectColumn, 'create').mockReturnValue(mockCheckboxSelectColumn);
const extCreateSpy = jest.spyOn(mockCheckboxSelectColumn, 'create').mockReturnValueOnce(mockCheckboxSelectColumn);
const gridSpy = jest.spyOn(SharedService.prototype, 'gridOptions', 'get').mockReturnValue(gridOptionsMock);
const rowSelectionSpy = jest.spyOn(SlickRowSelectionModel.prototype, 'constructor' as any);

Expand All @@ -398,6 +398,32 @@ describe('ExtensionService', () => {
expect(output).toEqual({ name: ExtensionName.checkboxSelector, instance: mockCheckboxSelectColumn as unknown } as ExtensionModel<any>);
});

it('should call "onExtensionRegistered" when defined in grid option and the CheckboxSelectColumn plugin gets created', () => {
const onRegisteredMock = jest.fn();
const columnsMock = [{ id: 'field1', field: 'field1', width: 100, cssClass: 'red' }] as Column[];
const gridOptionsMock = {
enableCheckboxSelector: true,
checkboxSelector: {
onExtensionRegistered: onRegisteredMock
}
} as GridOption;
const extCreateSpy = jest.spyOn(mockCheckboxSelectColumn, 'create').mockReturnValueOnce(mockCheckboxSelectColumn);
const gridSpy = jest.spyOn(SharedService.prototype, 'gridOptions', 'get').mockReturnValue(gridOptionsMock);
const rowSelectionSpy = jest.spyOn(SlickRowSelectionModel.prototype, 'constructor' as any);

service.createExtensionsBeforeGridCreation(columnsMock, gridOptionsMock);
service.bindDifferentExtensions();
const rowSelectionInstance = service.getExtensionByName(ExtensionName.rowSelection);
const output = service.getExtensionByName(ExtensionName.checkboxSelector);

expect(gridSpy).toHaveBeenCalled();
expect(extCreateSpy).toHaveBeenCalledWith(columnsMock, gridOptionsMock);
expect(rowSelectionInstance).not.toBeNull();
expect(rowSelectionSpy).toHaveBeenCalledWith({});
expect(output).toEqual({ name: ExtensionName.checkboxSelector, instance: mockCheckboxSelectColumn as unknown } as ExtensionModel<any>);
expect(onRegisteredMock).toHaveBeenCalledWith(expect.any(Object));
});

it('should register the RowMoveManager addon when "enableRowMoveManager" is set in the grid options', () => {
const columnsMock = [{ id: 'field1', field: 'field1', width: 100, cssClass: 'red' }] as Column[];
const gridOptionsMock = { enableRowMoveManager: true } as GridOption;
Expand Down Expand Up @@ -538,7 +564,7 @@ describe('ExtensionService', () => {

service.createExtensionsBeforeGridCreation(columnsMock, gridOptionsMock);
const instance = service.getCreatedExtensionByName<SlickDraggableGrouping>(ExtensionName.draggableGrouping);
service.addExtensionToList(ExtensionName.draggableGrouping, { name: ExtensionName.draggableGrouping, instance })
service.addExtensionToList(ExtensionName.draggableGrouping, { name: ExtensionName.draggableGrouping, instance });
const instance2 = service.getCreatedExtensionByName(ExtensionName.draggableGrouping);

expect(instance).toBeTruthy();
Expand Down Expand Up @@ -794,7 +820,7 @@ describe('ExtensionService', () => {
] as Column[];
const instanceMock = { translateColumnPicker: jest.fn() };
const gridOptionsMock = { enableColumnPicker: true } as GridOption;
jest.spyOn(extensionColumnPickerStub, 'register').mockReturnValue(instanceMock);
jest.spyOn(extensionColumnPickerStub, 'register').mockReturnValueOnce(instanceMock);
jest.spyOn(SharedService.prototype, 'gridOptions', 'get').mockReturnValue(gridOptionsMock);
jest.spyOn(SharedService.prototype, 'allColumns', 'get').mockReturnValue(columnsMock);
const setColumnsSpy = jest.spyOn(gridStub, 'setColumns');
Expand All @@ -813,7 +839,7 @@ describe('ExtensionService', () => {
] as Column[];
const instanceMock = { translateGridMenu: jest.fn() };
const gridOptionsMock = { enableGridMenu: true } as GridOption;
jest.spyOn(extensionGridMenuStub, 'register').mockReturnValue(instanceMock);
jest.spyOn(extensionGridMenuStub, 'register').mockReturnValueOnce(instanceMock);
jest.spyOn(SharedService.prototype, 'gridOptions', 'get').mockReturnValue(gridOptionsMock);
jest.spyOn(SharedService.prototype, 'allColumns', 'get').mockReturnValue(columnsMock);
const setColumnsSpy = jest.spyOn(gridStub, 'setColumns');
Expand Down
5 changes: 4 additions & 1 deletion packages/common/src/services/extension.service.ts
Expand Up @@ -207,8 +207,11 @@ export class ExtensionService {
this._checkboxSelectColumn = this._checkboxSelectColumn || new SlickCheckboxSelectColumn(this.pubSubService, this.gridOptions.checkboxSelector);
this._checkboxSelectColumn.init(this.sharedService.slickGrid);
const createdExtension = this.getCreatedExtensionByName(ExtensionName.checkboxSelector); // get the instance from when it was really created earlier
const instance = createdExtension && createdExtension.instance;
const instance = createdExtension?.instance;
if (instance) {
if (this.gridOptions.checkboxSelector?.onExtensionRegistered) {
this.gridOptions.checkboxSelector.onExtensionRegistered(instance);
}
this._extensionList[ExtensionName.checkboxSelector] = { name: ExtensionName.checkboxSelector, instance: this._checkboxSelectColumn };
}
}
Expand Down

0 comments on commit abe344b

Please sign in to comment.