Skip to content
Open
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
@@ -0,0 +1,170 @@
import DataGrid from 'devextreme-testcafe-models/dataGrid';
import { GridsEditMode } from 'devextreme/ui/data_grid';
import { createWidget } from '../../../../helpers/createWidget';
import url from '../../../../helpers/getPageUrl';

fixture.disablePageReloads`Editing - showEditorAlways cell in new row should be editable (T1323684)`
.page(url(__dirname, '../../../container.html'));

const READONLY_CLASS = 'dx-datagrid-readonly';
const CELL_FOCUS_DISABLED_CLASS = 'dx-cell-focus-disabled';

(['cell', 'batch'] as GridsEditMode[]).forEach((mode) => {
test(`showEditorAlways editor should be editable in a new row when allowUpdating is false, ${mode} mode`, async (t) => {
const dataGrid = new DataGrid('#container');
const addRowButton = dataGrid.getHeaderPanel().getAddRowButton();

await t.click(addRowButton);

const newRow = dataGrid.getDataRow(0);
await t.expect(newRow.isInserted).ok();

const cell = dataGrid.getDataCell(0, 1);
const editor = cell.getEditor();

await t
.expect(cell.element.hasClass(READONLY_CLASS))
.notOk('showEditorAlways cell in new row should not have readonly class')
.expect(cell.element.hasClass(CELL_FOCUS_DISABLED_CLASS))
.notOk('showEditorAlways cell in new row should not have cell-focus-disabled class');

await t
.click(editor.element)
.expect(cell.isFocused)
.ok('showEditorAlways cell should be focused after click')
.expect(editor.element.focused)
.ok('editor should be focused after click')
.typeText(editor.element, 'test value', { replace: true })
.expect(editor.element.value)
.eql('test value');
}).before(async () => createWidget('dxDataGrid', {
keyExpr: 'ID',
dataSource: [
{ ID: 1, FirstName: 'John', LastName: 'Heart' },
{ ID: 2, FirstName: 'Olivia', LastName: 'Peyton' },
],
showBorders: true,
editing: {
mode,
allowUpdating: false,
allowAdding: true,
},
columns: [
'LastName',
{ dataField: 'FirstName', showEditorAlways: true },
],
}));

test(`Boolean editor should be editable in a new row when allowUpdating is false, ${mode} mode`, async (t) => {
const dataGrid = new DataGrid('#container');
const addRowButton = dataGrid.getHeaderPanel().getAddRowButton();

await t.click(addRowButton);

const newRow = dataGrid.getDataRow(0);
await t.expect(newRow.isInserted).ok();

const booleanCell = dataGrid.getDataCell(0, 1);

await t
.expect(booleanCell.element.hasClass(READONLY_CLASS))
.notOk('boolean cell in new row should not have readonly class');

await t
.click(booleanCell.element)
.click(booleanCell.getCheckbox())
.expect(booleanCell.getEditor().isChecked())
.ok('checkbox in new row should be checked after click in it');
}).before(async () => createWidget('dxDataGrid', {
keyExpr: 'ID',
dataSource: [
{ ID: 1, Name: 'John', Active: false },
{ ID: 2, Name: 'Olivia', Active: true },
],
showBorders: true,
editing: {
mode,
allowUpdating: false,
allowAdding: true,
},
columns: [
'Name',
{ dataField: 'Active', dataType: 'boolean' },
],
}));

test(`showEditorAlways editor in existing rows should remain readonly when allowUpdating is false, ${mode} mode`, async (t) => {
const dataGrid = new DataGrid('#container');
const existingCell = dataGrid.getDataCell(0, 1);

await t
.expect(existingCell.element.hasClass(READONLY_CLASS))
.ok('showEditorAlways cell in existing row should have readonly class when allowUpdating is false');

await t
.click(existingCell.getEditor().element)
.expect(existingCell.element.hasClass(READONLY_CLASS))
.ok('showEditorAlways cell in existing row should remain readonly after click');
}).before(async () => createWidget('dxDataGrid', {
keyExpr: 'ID',
dataSource: [
{ ID: 1, FirstName: 'John', LastName: 'Heart' },
{ ID: 2, FirstName: 'Olivia', LastName: 'Peyton' },
],
showBorders: true,
editing: {
mode,
allowUpdating: false,
allowAdding: true,
},
columns: [
'LastName',
{ dataField: 'FirstName', showEditorAlways: true },
],
}));
});

test('showEditorAlways editor should be editable in a new row when allowUpdating is a function returning false, cell mode', async (t) => {
const dataGrid = new DataGrid('#container');
const addRowButton = dataGrid.getHeaderPanel().getAddRowButton();

await t.click(addRowButton);

const newRow = dataGrid.getDataRow(0);
await t.expect(newRow.isInserted).ok();

const cell = dataGrid.getDataCell(0, 1);
const editor = cell.getEditor();

await t
.expect(cell.element.hasClass(READONLY_CLASS))
.notOk('showEditorAlways cell in new row should not have readonly class')
.expect(cell.element.hasClass(CELL_FOCUS_DISABLED_CLASS))
.notOk('showEditorAlways cell in new row should not have cell-focus-disabled class');

await t
.click(editor.element)
.expect(cell.isFocused)
.ok('showEditorAlways cell should be focused after click')
.expect(editor.element.focused)
.ok('editor should be focused after click')
.typeText(editor.element, 'test value', { replace: true })
.expect(editor.element.value)
.eql('test value');
}).before(async () => createWidget('dxDataGrid', {
keyExpr: 'ID',
dataSource: [
{ ID: 1, FirstName: 'John', LastName: 'Heart' },
{ ID: 2, FirstName: 'Olivia', LastName: 'Peyton' },
],
showBorders: true,
editing: {
mode: 'cell' as GridsEditMode,
allowUpdating: () => false,
allowAdding: true,
},
columns: [
'LastName',
{ dataField: 'FirstName', showEditorAlways: true },
],
}));
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,7 @@ import * as iconUtils from '@js/core/utils/icon';
import { each } from '@js/core/utils/iterator';
import { deepExtendArraySafe } from '@js/core/utils/object';
import {
isDefined, isEmptyObject,
isFunction, isObject,
isDefined, isEmptyObject, isFunction, isObject,
} from '@js/core/utils/type';
import { confirm } from '@js/ui/dialog';
import { current, isFluent } from '@js/ui/themes';
Expand Down Expand Up @@ -2254,23 +2253,33 @@ class EditingControllerImpl extends modules.ViewController {
}

public getColumnTemplate(options) {
const { column } = options;
const rowIndex = options.row && options.row.rowIndex;
const { column, row, rowType } = options;
const rowIndex = row?.rowIndex;
let template;

const isRowMode = this.isRowBasedEditMode();
const isRowEditing = this.isEditRow(rowIndex);
const isCellEditing = this.isEditCell(rowIndex, options.columnIndex);
let editingStartOptions;

if ((column.showEditorAlways || column.setCellValue && (isRowEditing && column.allowEditing || isCellEditing))
&& (options.rowType === 'data' || options.rowType === 'detailAdaptive') && !column.command) {
const allowUpdating = this.allowUpdating(options);
if (((allowUpdating || isRowEditing) && column.allowEditing || isCellEditing) && (isRowEditing || !isRowMode)) {
const isEditableRowType = rowType === 'data' || rowType === 'detailAdaptive';
const isEditableByRowState = isRowEditing && !!column.allowEditing;
const needsEditorTemplate = !!column.showEditorAlways
|| (column.setCellValue && (isEditableByRowState || isCellEditing));

if (needsEditorTemplate && isEditableRowType && !column.command) {
const allowUpdating = !!this.allowUpdating(options);
const canModifyCell = (allowUpdating || isRowEditing || !!row?.isNewRow)
&& !!column.allowEditing;
const isEditable = (canModifyCell || isCellEditing) && (isRowEditing || !isRowMode);

if (isEditable) {
// eslint-disable-next-line @typescript-eslint/init-declarations
let editingStartOptions;
if (column.showEditorAlways && !isRowMode) {
editingStartOptions = {
cancel: false,
key: options.row.isNewRow ? undefined : options.row.key,
data: options.row.data,
key: row?.isNewRow ? undefined : row.key,
data: row.data,
column,
};
this._isEditingStart(editingStartOptions);
Expand All @@ -2282,7 +2291,7 @@ class EditingControllerImpl extends modules.ViewController {
}
}
template = column.editCellTemplate || this._getDefaultEditorTemplate();
} else if (column.command === 'detail' && options.rowType === 'detail' && isRowEditing) {
} else if (column.command === 'detail' && rowType === 'detail' && isRowEditing) {
template = (this as any)?.getEditFormTemplate(options);
}

Expand Down
Loading