Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions docs/grid-functionalities/row-based-edit.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ If the [Excel Copy Buffer Plugin](excel-copy-buffer.md) is configured, the Row b
The idea of the plugin is to focus the users editing experience on specific individual rows and and save them individually. This is achieved by letting the user toggle one or more rows into edit mode.
When a that happens a potentially registered `onBeforeEditMode` callback is executed to handle various preparation or cleanup tasks. Now changes can be made to those rows and will be highlighted and tracked. The user may cancel the edit mode at any time and revert all cells changes. If the save button is pressed on the other hand an `onBeforeRowUpdated` hook, which you define via plugin options, is called and expects a `Promise<boolean>`. In that method you'd typically write the changes to your backend and return either true or false based on the operations outcome. If a negative boolean is returned the edit mode is kept, otherwise the row applies the changes and toggles back into readonly mode. That means, no modifications can be done on the grid. Additionally, when a row is deleted via the delete button, an `onAfterDelete` callback is executed, which you can use to e.g. remove the row from your backend.

Additionally, you can also register the optional `onBeforeCellEdit` hook which allows to control on a per cell level whether editing should be allowed or not, by returning a boolean.

Here's the respective code shown in Example22:

#### ViewModel
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ If the [Excel Copy Buffer Plugin](excel-copy-buffer.md) is configured, the Row b
The idea of the plugin is to focus the users editing experience on specific individual rows and and save them individually. This is achieved by letting the user toggle one or more rows into edit mode.
When a that happens a potentially registered `onBeforeEditMode` callback is executed to handle various preparation or cleanup tasks. Now changes can be made to those rows and will be highlighted and tracked. The user may cancel the edit mode at any time and revert all cells changes. If the save button is pressed on the other hand an `onBeforeRowUpdated` hook, which you define via plugin options, is called and expects a `Promise<boolean>`. In that method you'd typically write the changes to your backend and return either true or false based on the operations outcome. If a negative boolean is returned the edit mode is kept, otherwise the row applies the changes and toggles back into readonly mode. That means, no modifications can be done on the grid. Additionally, when a row is deleted via the delete button, an `onAfterDelete` callback is executed, which you can use to e.g. remove the row from your backend.

Additionally, you can also register the optional `onBeforeCellEdit` hook which allows to control on a per cell level whether editing should be allowed or not, by returning a boolean.

Here's the respective code shown in Example22:

#### ViewModel
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ If the [Excel Copy Buffer Plugin](excel-copy-buffer.md) is configured, the Row b
The idea of the plugin is to focus the users editing experience on specific individual rows and and save them individually. This is achieved by letting the user toggle one or more rows into edit mode.
When a that happens a potentially registered `onBeforeEditMode` callback is executed to handle various preparation or cleanup tasks. Now changes can be made to those rows and will be highlighted and tracked. The user may cancel the edit mode at any time and revert all cells changes. If the save button is pressed on the other hand an `onBeforeRowUpdated` hook, which you define via plugin options, is called and expects a `Promise<boolean>`. In that method you'd typically write the changes to your backend and return either true or false based on the operations outcome. If a negative boolean is returned the edit mode is kept, otherwise the row applies the changes and toggles back into readonly mode. That means, no modifications can be done on the grid. Additionally, when a row is deleted via the delete button, an `onAfterDelete` callback is executed, which you can use to e.g. remove the row from your backend.

Additionally, you can also register the optional `onBeforeCellEdit` hook which allows to control on a per cell level whether editing should be allowed or not, by returning a boolean.

Here's the respective code shown in Example22:

#### ViewModel
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ If the [Excel Copy Buffer Plugin](excel-copy-buffer.md) is configured, the Row b
The idea of the plugin is to focus the users editing experience on specific individual rows and and save them individually. This is achieved by letting the user toggle one or more rows into edit mode.
When a that happens a potentially registered `onBeforeEditMode` callback is executed to handle various preparation or cleanup tasks. Now changes can be made to those rows and will be highlighted and tracked. The user may cancel the edit mode at any time and revert all cells changes. If the save button is pressed on the other hand an `onBeforeRowUpdated` hook, which you define via plugin options, is called and expects a `Promise<boolean>`. In that method you'd typically write the changes to your backend and return either true or false based on the operations outcome. If a negative boolean is returned the edit mode is kept, otherwise the row applies the changes and toggles back into readonly mode. That means, no modifications can be done on the grid. Additionally, when a row is deleted via the delete button, an `onAfterDelete` callback is executed, which you can use to e.g. remove the row from your backend.

Additionally, you can also register the optional `onBeforeCellEdit` hook which allows to control on a per cell level whether editing should be allowed or not, by returning a boolean.

Here's the respective code shown in Example22:

#### ViewModel
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ If the [Excel Copy Buffer Plugin](excel-copy-buffer.md) is configured, the Row b
The idea of the plugin is to focus the users editing experience on specific individual rows and and save them individually. This is achieved by letting the user toggle one or more rows into edit mode.
When a that happens a potentially registered `onBeforeEditMode` callback is executed to handle various preparation or cleanup tasks. Now changes can be made to those rows and will be highlighted and tracked. The user may cancel the edit mode at any time and revert all cells changes. If the save button is pressed on the other hand an `onBeforeRowUpdated` hook, which you define via plugin options, is called and expects a `Promise<boolean>`. In that method you'd typically write the changes to your backend and return either true or false based on the operations outcome. If a negative boolean is returned the edit mode is kept, otherwise the row applies the changes and toggles back into readonly mode. That means, no modifications can be done on the grid. Additionally, when a row is deleted via the delete button, an `onAfterDelete` callback is executed, which you can use to e.g. remove the row from your backend.

Additionally, you can also register the optional `onBeforeCellEdit` hook which allows to control on a per cell level whether editing should be allowed or not, by returning a boolean.

Here's the respective code shown in Example22:

#### ViewModel
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,15 @@ import { afterEach, beforeEach, describe, expect, it, vi, type Mock } from 'vite
import { TranslateServiceStub } from '../../../../../test/translateServiceStub.js';
import { SlickEvent, type SlickGrid } from '../../core/index.js';
import { Editors } from '../../editors/editors.index.js';
import type { Column, EditCommand, GridOption, OnBeforeEditCellEventArgs, OnSetOptionsEventArgs, RowBasedEditOptions } from '../../interfaces/index.js';
import type {
Column,
EditCommand,
GridOption,
OnBeforeEditCellEventArgs,
OnEventArgs,
OnSetOptionsEventArgs,
RowBasedEditOptions,
} from '../../interfaces/index.js';
import { GridService } from '../../services/grid.service.js';
import type { ExtensionUtility } from '../extensionUtility.js';
import {
Expand Down Expand Up @@ -148,6 +156,36 @@ describe('Row Based Edit Plugin', () => {
expect(onBeforeEditCellHandler({} as Event, { item: fakeItem } as OnBeforeEditCellEventArgs)).toBe(true);
});

it('should respect user provided custom onBeforeCellEdit hooks', () => {
const fakeItem = { id: 'test' };

gridStub.getData.mockReturnValue({ getItem: () => fakeItem });
gridStub.getOptions.mockReturnValue({ ...optionsMock });
let userCanEdit = false;
plugin = new SlickRowBasedEdit(extensionUtilityStub, pubSubServiceStub, {
...addonOptions,
onBeforeCellEdit: (_args: OnEventArgs) => (() => userCanEdit)(),
});
(plugin as any)._eventHandler = {
subscribe: vi.fn(),
unsubscribeAll: vi.fn(),
};
plugin.init(gridStub, gridService);

const onBeforeEditCellHandler = (plugin.eventHandler.subscribe as Mock<any>).mock.calls[0][1] as (e: Event, args: OnBeforeEditCellEventArgs) => boolean;
expect(onBeforeEditCellHandler({} as Event, { item: fakeItem } as OnBeforeEditCellEventArgs)).toBe(false);

// set row to edit mode
plugin.rowBasedEditCommandHandler(fakeItem, {} as Column, {} as EditCommand);

// should still fail
expect(onBeforeEditCellHandler({} as Event, { item: fakeItem } as OnBeforeEditCellEventArgs)).toBe(false);

// change to allow in userland
userCanEdit = true;
expect(onBeforeEditCellHandler({} as Event, { item: fakeItem } as OnBeforeEditCellEventArgs)).toBe(true);
});

it('should throw an error when "enableRowEdit" is set without "enableCellNavigation"', () => {
gridStub.getOptions.mockReturnValue({});

Expand Down
11 changes: 9 additions & 2 deletions packages/common/src/extensions/slickRowBasedEdit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -472,8 +472,15 @@ export class SlickRowBasedEdit {
return actionFragment;
}

protected onBeforeEditCellHandler = (_e: SlickEventData, args: OnBeforeEditCellEventArgs) => {
return this._editedRows.has(args.item?.[this.gridOptions.datasetIdPropertyName ?? 'id']) as boolean;
protected onBeforeEditCellHandler = (_e: SlickEventData, args: OnBeforeEditCellEventArgs): boolean => {
const hasOnBeforeCellEditFn = typeof this._addonOptions?.onBeforeCellEdit === 'function';
const canEdit = this._editedRows.has(args.item?.[this.gridOptions.datasetIdPropertyName ?? 'id']) as boolean;
let userCanEdit = true;
if (hasOnBeforeCellEditFn) {
userCanEdit = this._addonOptions?.onBeforeCellEdit!(args as unknown as OnEventArgs) ?? true;
}

return canEdit && userCanEdit;
};

protected toggleEditmode(dataContext: any, editMode: boolean): void {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,9 @@ export interface RowBasedEditOptions {
/** method called before a row enters edit mode. */
onBeforeEditMode?: (args: OnEventArgs) => void;

/** method deciding whether an individual cell can be toggled to edit mode */
onBeforeCellEdit?: (args: OnEventArgs) => boolean;

/** method called after a row is deleted. */
onAfterDelete?: (args: OnEventArgs) => void;
}
Loading