Skip to content

Commit b73e7cb

Browse files
authored
DataGrid - Add warning when trying to set fixed state for child columns (#30800)
1 parent c1bcb39 commit b73e7cb

File tree

6 files changed

+267
-9
lines changed

6 files changed

+267
-9
lines changed

e2e/testcafe-devextreme/tests/dataGrid/common/fixedColumns.ts

Lines changed: 209 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -436,3 +436,212 @@ test('DataGrid - Group summary is not updated when a column is fixed on the righ
436436
},
437437
],
438438
}));
439+
440+
const mockCountries = [
441+
{
442+
ID: 1,
443+
Country: 'Brazil',
444+
Area: 8515767,
445+
Population_Urban: 0.85,
446+
Population_Rural: 0.15,
447+
Population_Total: 205809000,
448+
GDP_Agriculture: 0.054,
449+
GDP_Industry: 0.274,
450+
GDP_Services: 0.672,
451+
GDP_Total: 2353025,
452+
},
453+
{
454+
ID: 2,
455+
Country: 'China',
456+
Area: 9388211,
457+
Population_Urban: 0.54,
458+
Population_Rural: 0.46,
459+
Population_Total: 1375530000,
460+
GDP_Agriculture: 0.091,
461+
GDP_Industry: 0.426,
462+
GDP_Services: 0.483,
463+
GDP_Total: 10380380,
464+
},
465+
{
466+
ID: 3,
467+
Country: 'France',
468+
Area: 675417,
469+
Population_Urban: 0.79,
470+
Population_Rural: 0.21,
471+
Population_Total: 64529000,
472+
GDP_Agriculture: 0.019,
473+
GDP_Industry: 0.183,
474+
GDP_Services: 0.798,
475+
GDP_Total: 2846889,
476+
},
477+
];
478+
479+
test('Warning should be shown when trying to set fixed state for child columns', async (t) => {
480+
const consoleMessages = await t.getBrowserConsoleMessages();
481+
const warnings = consoleMessages?.warn.filter((message) => message.startsWith('W1028')) || [];
482+
await t.expect(warnings.length).eql(1, 'There is warning W1028');
483+
}).before(async () => {
484+
await createWidget(
485+
'dxDataGrid',
486+
{
487+
dataSource: mockCountries,
488+
keyExpr: 'ID',
489+
columnAutoWidth: true,
490+
allowColumnReordering: true,
491+
width: 600,
492+
showBorders: true,
493+
columnChooser: { enabled: true },
494+
columns: [
495+
{
496+
dataField: 'Country',
497+
fixed: true,
498+
fixedPosition: 'left',
499+
},
500+
{
501+
dataField: 'Area',
502+
fixed: true,
503+
fixedPosition: 'left',
504+
},
505+
{
506+
caption: 'Population',
507+
columns: [
508+
{
509+
caption: 'Total',
510+
dataField: 'Population_Total',
511+
format: 'fixedPoint',
512+
fixed: true,
513+
fixedPosition: 'left',
514+
},
515+
{
516+
caption: 'Urban',
517+
dataField: 'Population_Urban',
518+
format: 'percent',
519+
fixed: true,
520+
fixedPosition: 'left',
521+
},
522+
],
523+
},
524+
],
525+
},
526+
'#container',
527+
);
528+
});
529+
530+
test('Warning should work when columns changed in real time', async (t) => {
531+
const grid = new DataGrid('#container');
532+
533+
let consoleMessages = await t.getBrowserConsoleMessages();
534+
let warnings = consoleMessages?.warn.filter((message) => message.startsWith('W1028')) || [];
535+
536+
await t.expect(warnings.length).eql(0, 'There is not any warning W1028');
537+
538+
await grid.option('columns', [
539+
{
540+
dataField: 'test3',
541+
caption: 'test3',
542+
},
543+
{
544+
caption: 'test3 group',
545+
columns: [
546+
{
547+
dataField: 'test4',
548+
caption: 'test4',
549+
fixed: true,
550+
},
551+
{
552+
dataField: 'test5',
553+
caption: 'test5',
554+
fixed: true,
555+
},
556+
],
557+
},
558+
]);
559+
consoleMessages = await t.getBrowserConsoleMessages();
560+
warnings = consoleMessages?.warn.filter((message) => message.startsWith('W1028')) || [];
561+
await t.expect(warnings.length).eql(1, 'There is warning W1028');
562+
}).before(async () => {
563+
await createWidget(
564+
'dxDataGrid',
565+
{
566+
dataSource: [],
567+
},
568+
'#container',
569+
);
570+
});
571+
572+
test('Warning should be shown one time for every dataGrid instance', async (t) => {
573+
const otherGrid = new DataGrid('#otherContainer');
574+
575+
await otherGrid.apiAddColumn({
576+
dataField: 'test',
577+
caption: 'test',
578+
columns: [
579+
{
580+
dataField: 'test1',
581+
caption: 'test1',
582+
fixed: true,
583+
},
584+
{
585+
dataField: 'test2',
586+
caption: 'test2',
587+
fixed: true,
588+
},
589+
],
590+
});
591+
const consoleMessages = await t.getBrowserConsoleMessages();
592+
const warnings = consoleMessages?.warn.filter((message) => message.startsWith('W1028')) || [];
593+
await t.expect(warnings.length).eql(2, 'There are two warnings W1028');
594+
}).before(async () => {
595+
await createWidget(
596+
'dxDataGrid',
597+
{
598+
dataSource: mockCountries,
599+
keyExpr: 'ID',
600+
columnAutoWidth: true,
601+
allowColumnReordering: true,
602+
width: 600,
603+
showBorders: true,
604+
columnChooser: { enabled: true },
605+
columns: [
606+
{
607+
dataField: 'Country',
608+
fixed: true,
609+
fixedPosition: 'left',
610+
},
611+
{
612+
dataField: 'Area',
613+
fixed: true,
614+
fixedPosition: 'left',
615+
},
616+
{
617+
caption: 'Population',
618+
columns: [
619+
{
620+
caption: 'Total',
621+
dataField: 'Population_Total',
622+
format: 'fixedPoint',
623+
fixed: true,
624+
fixedPosition: 'left',
625+
},
626+
{
627+
caption: 'Urban',
628+
dataField: 'Population_Urban',
629+
format: 'percent',
630+
fixed: true,
631+
fixedPosition: 'left',
632+
},
633+
],
634+
},
635+
],
636+
},
637+
'#container',
638+
);
639+
640+
await createWidget(
641+
'dxDataGrid',
642+
{
643+
dataSource: [],
644+
},
645+
'#otherContainer',
646+
);
647+
});

packages/devextreme/js/__internal/grids/grid_core/columns_controller/const.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,3 +27,10 @@ export const COLUMN_INDEX_OPTIONS = {
2727
};
2828
export const GROUP_LOCATION = 'group';
2929
export const COLUMN_CHOOSER_LOCATION = 'columnChooser';
30+
31+
export const UNSUPPORTED_PROPERTIES_FOR_CHILD_COLUMNS = [
32+
'fixed',
33+
'fixedPosition',
34+
'type',
35+
'buttons',
36+
];

packages/devextreme/js/__internal/grids/grid_core/columns_controller/m_columns_controller.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,8 @@ export class ColumnsController extends modules.Controller {
136136

137137
protected _stateStoringController!: StateStoringController;
138138

139+
public _isWarnedAboutUnsupportedProperties?: boolean;
140+
139141
public init(isApplyingUserState?): void {
140142
this._dataController = this.getController('data');
141143
this._focusController = this.getController('focus');

packages/devextreme/js/__internal/grids/grid_core/columns_controller/m_columns_controller_utils.ts

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import {
1212
isDefined, isFunction, isNumeric, isObject, isString, type,
1313
} from '@js/core/utils/type';
1414
import variableWrapper from '@js/core/utils/variable_wrapper';
15+
import errors from '@js/ui/widget/ui.errors';
1516

1617
import { HIDDEN_COLUMNS_WIDTH } from '../adaptivity/const';
1718
import gridCoreUtils from '../m_utils';
@@ -24,11 +25,36 @@ import {
2425
GROUP_COMMAND_COLUMN_NAME,
2526
GROUP_LOCATION,
2627
IGNORE_COLUMN_OPTION_NAMES,
28+
UNSUPPORTED_PROPERTIES_FOR_CHILD_COLUMNS,
2729
USER_STATE_FIELD_NAMES,
2830
USER_STATE_FIELD_NAMES_15_1,
2931
} from './const';
3032
import type { ColumnsController } from './m_columns_controller';
3133

34+
const warnFixedInChildColumnsOnce = (controller: ColumnsController, childColumns: any[]): void => {
35+
if (controller?._isWarnedAboutUnsupportedProperties) return;
36+
if (!childColumns || !Array.isArray(childColumns) || childColumns?.length === 0) return;
37+
38+
let unsupportedProperty: string | null = null;
39+
40+
for (const column of childColumns) {
41+
if (unsupportedProperty) break;
42+
if (!column || typeof column !== 'object' || column === null) continue;
43+
44+
for (const property of UNSUPPORTED_PROPERTIES_FOR_CHILD_COLUMNS) {
45+
if (property in column) {
46+
unsupportedProperty = property;
47+
break;
48+
}
49+
}
50+
}
51+
52+
if (unsupportedProperty) {
53+
controller && (controller._isWarnedAboutUnsupportedProperties = true);
54+
errors.log('W1028', unsupportedProperty);
55+
}
56+
};
57+
3258
export const setFilterOperationsAsDefaultValues = function (column) {
3359
column.filterOperations = column.defaultFilterOperations;
3460
};
@@ -47,7 +73,7 @@ export const createColumn = function (that: ColumnsController, columnOptions, us
4773

4874
that.setName(columnOptions);
4975

50-
let result = { };
76+
let result = {};
5177
if (columnOptions.command) {
5278
result = deepExtendArraySafe(commonColumnOptions, columnOptions);
5379
} else {
@@ -90,6 +116,7 @@ export const createColumnsFromOptions = function (that: ColumnsController, colum
90116
result.push(column);
91117

92118
if (column.columns) {
119+
warnFixedInChildColumnsOnce(that, column.columns);
93120
result = result.concat(createColumnsFromOptions(that, column.columns, column, result.length));
94121
delete column.columns;
95122
column.hasColumns = true;
@@ -945,7 +972,7 @@ const isFirstOrLastBandColumn = function (
945972
fixedPosition?: StickyPosition,
946973
): boolean {
947974
return bandColumns.every((column, index) => onlyWithinBandColumn && index === 0
948-
|| isFirstOrLastColumnCore(that, column, index, onlyWithinBandColumn, isLast, fixedPosition));
975+
|| isFirstOrLastColumnCore(that, column, index, onlyWithinBandColumn, isLast, fixedPosition));
949976
};
950977

951978
const isFirstOrLastColumnCore = function (

packages/devextreme/js/ui/widget/ui.errors.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -368,4 +368,8 @@ export default errorUtils(errors.ERROR_MESSAGES, {
368368
* @name ErrorsUIWidgets.W1027
369369
*/
370370
W1027: 'A prompt should be specified for a custom command.',
371+
/**
372+
* @name ErrorsUIWidgets.W1028
373+
*/
374+
W1028: 'Nested/banded columns do not support the following properties: {0}.',
371375
});

packages/testcafe-models/dataGrid/index.ts

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -218,7 +218,7 @@ export default class DataGrid extends GridCore {
218218

219219
getFilterEditor<T>(
220220
columnIndex: number,
221-
EditorType: new(mainElement: Selector) => T,
221+
EditorType: new (mainElement: Selector) => T,
222222
): T {
223223
return new EditorType(this.getHeaders().getFilterRow().getFilterCell(columnIndex).getEditor());
224224
}
@@ -592,7 +592,7 @@ export default class DataGrid extends GridCore {
592592
const { getInstance } = this;
593593
return ClientFunction(
594594
() => {
595-
(getInstance() as DataGridInstance).refresh().catch(() => {});
595+
(getInstance() as DataGridInstance).refresh().catch(() => { });
596596
},
597597
{ dependencies: { getInstance } },
598598
)();
@@ -651,6 +651,15 @@ export default class DataGrid extends GridCore {
651651
)();
652652
}
653653

654+
apiAddColumn(config: any): Promise<void> {
655+
const { getInstance } = this;
656+
657+
return ClientFunction(
658+
() => (getInstance() as DataGridInstance).addColumn(config),
659+
{ dependencies: { getInstance, config } },
660+
)();
661+
}
662+
654663
moveRow(rowIndex: number, x: number, y: number, isStart = false): Promise<void> {
655664
const { getInstance } = this;
656665

@@ -672,7 +681,7 @@ export default class DataGrid extends GridCore {
672681
)();
673682
}
674683

675-
resizeHeader(columnIndex: number, offset: number, needToTriggerPointerUp = true): Promise<void> {
684+
resizeHeader(columnIndex: number, offset: number, needToTriggerPointerUp = true): Promise<void> {
676685
const { getInstance } = this;
677686

678687
return ClientFunction(
@@ -852,10 +861,10 @@ export default class DataGrid extends GridCore {
852861
): Promise<void> {
853862
const { getInstance } = this;
854863
return ClientFunction(
855-
() => {
856-
(getInstance() as DataGridInstance).option('selection.sensitivity', sensitivity);
857-
},
858-
{ dependencies: { getInstance, sensitivity } },
864+
() => {
865+
(getInstance() as DataGridInstance).option('selection.sensitivity', sensitivity);
866+
},
867+
{ dependencies: { getInstance, sensitivity } },
859868
)();
860869
}
861870
}

0 commit comments

Comments
 (0)