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
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
import { TextBoxModel } from '@ts/ui/__tests__/__mock__/model/textbox';

const SELECTORS = {
editCell: 'dx-editor-cell',
invalidCell: 'invalid',
textBox: 'dx-textbox',
};

export class DataCellModel {
Expand All @@ -27,4 +30,9 @@ export class DataCellModel {
public getHTML(): string {
return this.root?.innerHTML ?? '';
}

public getEditor(): TextBoxModel {
const editorElement = this.root?.querySelector(`.${SELECTORS.textBox}`) as HTMLElement;
return new TextBoxModel(editorElement);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ const SELECTORS = {
editForm: 'edit-form',
headerCellIndicators: 'dx-column-indicators',
headerCellFilter: 'dx-header-filter',
revertButton: 'dx-revert-button',
};

export abstract class GridCoreModel<TInstance extends GridBase = GridBase> {
Expand Down Expand Up @@ -101,6 +102,10 @@ export abstract class GridCoreModel<TInstance extends GridBase = GridBase> {
return new ToastModel(this.getToastContainer());
}

public getRevertButton(): HTMLElement {
return document.body.querySelector(`.${SELECTORS.revertButton}`) as HTMLElement;
}

public addWidgetPrefix(classNames: string): string {
const componentName = this.NAME;

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
import {
afterEach, beforeEach, describe, expect, it, jest,
} from '@jest/globals';
import {
afterTest,
beforeTest,
createDataGrid,
} from '@ts/grids/grid_core/__tests__/__mock__/helpers/utils';

describe('DataGrid Cell Editing', () => {
beforeEach(beforeTest);
afterEach(afterTest);

// T1308327
describe('when showEditorAlways and repaintChangesOnly is enabled', () => {
it('should restore the value after canceling changes with validation error (T1308327)', async () => {
const data = [
{ id: 1, name: 'Job 1', article: 'Article A' },
{ id: 2, name: 'Job 2', article: 'Article B' },
];

const { instance, component } = await createDataGrid({
dataSource: data,
keyExpr: 'id',
repaintChangesOnly: true,
editing: {
mode: 'cell',
allowUpdating: true,
},
columns: [
{
dataField: 'name',
showEditorAlways: true,
validationRules: [
{ type: 'required', message: 'Required field' },
],
},
{
dataField: 'article',
},
],
});

const firstCell = component.getDataCell(0, 0);
const firstEditor = firstCell.getEditor();

firstEditor.setValue('');
jest.runAllTimers();

expect(component.getDataCell(0, 0).isValidCell).toBe(false);

component.getRevertButton().click();
jest.runAllTimers();

expect(instance.cellValue(0, 'name')).toBe('Job 1');
expect(component.getDataCell(0, 0).isValidCell).toBe(true);

const secondCell = component.getDataCell(1, 0);
const secondEditor = secondCell.getEditor();

secondEditor.setValue('');
jest.runAllTimers();

expect(component.getDataCell(1, 0).isValidCell).toBe(false);

component.getRevertButton().click();
jest.runAllTimers();

expect(instance.cellValue(1, 'name')).toBe('Job 2');
expect(component.getDataCell(1, 0).isValidCell).toBe(true);
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,34 @@ export class ValidatingController extends modules.Controller {
this._validationStateCache = {};
}

public resetValidationStateForChanges(changes) {
if (!changes?.length) {
return;
}

changes.forEach(({ key }) => {
this._removeValidationData(key);
});
}

private _removeValidationData(key) {
if (!this._validationState?.length) {
return;
}

const keyHash = getKeyHash(key);
const isObjectKeyHash = isObject(keyHash);

if (!isObjectKeyHash && this._validationStateCache) {
// eslint-disable-next-line @typescript-eslint/no-dynamic-delete
delete this._validationStateCache[keyHash];
}

this._validationState = this._validationState.filter((data) => (
isObjectKeyHash ? !equalByValue(data.key, key) : data.key !== key
));
}

public _rowIsValidated(change) {
const validationData = this._getValidationData(change?.key);

Expand Down Expand Up @@ -936,14 +964,7 @@ export const validatingEditingExtender = (Base: ModuleType<EditingController>) =
});
this._focusEditingCell();
} else if (!cancel) {
let shouldResetValidationState = true;

if (isCellEditMode) {
const columns = this._columnsController.getColumns();
const columnsWithValidatingEditors = columns.filter((col) => col.showEditorAlways && col.validationRules?.length > 0).length > 0;

shouldResetValidationState = !columnsWithValidatingEditors;
}
const shouldResetValidationState = this._shouldResetValidationState();

if (shouldResetValidationState) {
this._validatingController.initValidationState();
Expand Down Expand Up @@ -979,11 +1000,34 @@ export const validatingEditingExtender = (Base: ModuleType<EditingController>) =
}

protected _beforeCancelEditData() {
this._validatingController.initValidationState();
const validatingController = this._validatingController;
const shouldResetValidationState = this._shouldResetValidationState();

if (shouldResetValidationState) {
validatingController.initValidationState();
} else {
const changes = this.getChanges();
validatingController.resetValidationStateForChanges(changes);
}

super._beforeCancelEditData();
}

private _shouldResetValidationState(): boolean {
const isCellEditMode = this.getEditMode() === EDIT_MODE_CELL;

if (isCellEditMode) {
const columns = this._columnsController.getColumns();
const columnsWithValidatingEditors = columns.filter(
(col) => col.showEditorAlways && col.validationRules?.length > 0,
);

return columnsWithValidatingEditors.length === 0;
}

return true;
}

private _showErrorRow(change) {
let $popupContent;
const items = this._dataController.items();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2809,10 +2809,9 @@ QUnit.module('Editing', baseModuleConfig, () => {
this.clock.tick(10);
$(grid.getCellElement(0, 1)).trigger('dxclick');
this.clock.tick(10);
const callCount = action === 'close edit cell' ? 3 : 4;

// assert
assert.equal(validationCallback.callCount, callCount, 'validation callback call count');
assert.equal(validationCallback.callCount, 3, 'validation callback call count');
});
});

Expand Down
Loading