Skip to content

Commit 6a6a1c7

Browse files
committed
Form: fix get item by path (T1311534)
1 parent cee58b9 commit 6a6a1c7

File tree

3 files changed

+139
-27
lines changed

3 files changed

+139
-27
lines changed

packages/devextreme/js/__internal/ui/form/form.ts

Lines changed: 18 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1448,11 +1448,11 @@ class Form extends Widget<FormProperties> {
14481448
_getItemByField(field: string | {
14491449
fieldName: string;
14501450
fieldPath: string[];
1451-
}, items: PreparedItem[]): PreparedItem | false {
1451+
}, items: PreparedItem[]): PreparedItem | null {
14521452
const fieldParts = isObject(field) ? field : this._getFieldParts(field);
14531453
const { fieldName } = fieldParts;
14541454
const { fieldPath } = fieldParts;
1455-
let resultItem: PreparedItem | false = false;
1455+
let resultItem: PreparedItem | null = null;
14561456

14571457
if (items.length) {
14581458
each(items, (_index: number, item: PreparedItem): boolean => {
@@ -1491,34 +1491,24 @@ class Form extends Widget<FormProperties> {
14911491
fieldName: string;
14921492
fieldPath: string[];
14931493
} {
1494-
const fieldSeparator = '.';
1495-
let fieldName = field;
1496-
let separatorIndex = fieldName.indexOf(fieldSeparator);
1497-
const resultPath = [];
1498-
1499-
while (separatorIndex !== -1) {
1500-
// @ts-expect-error ts-error
1501-
resultPath.push(fieldName.substr(0, separatorIndex));
1502-
fieldName = fieldName.substr(separatorIndex + 1);
1503-
separatorIndex = fieldName.indexOf(fieldSeparator);
1504-
}
1494+
const [fieldName, ...fieldPath] = field.split('.').reverse();
15051495

15061496
return {
15071497
fieldName,
1508-
fieldPath: resultPath.reverse(),
1498+
fieldPath,
15091499
};
15101500
}
15111501

15121502
_getItemByFieldPath(
15131503
path: string[],
15141504
fieldName: string,
15151505
item: Item,
1516-
): Item | false {
1506+
): Item | null {
15171507
const { itemType } = item;
15181508
const subItemsField = this._getSubItemField(itemType);
15191509

15201510
const isItemWithSubItems = itemType === 'group' || itemType === 'tabbed' || (item as TabItem).title;
1521-
let result: Item | false = false;
1511+
let result: Item | null = null;
15221512

15231513
do {
15241514
if (isItemWithSubItems) {
@@ -1534,7 +1524,7 @@ class Form extends Widget<FormProperties> {
15341524
pathNode = path.pop();
15351525
}
15361526

1537-
if (!path.length) {
1527+
if (!path.length && nameWithoutSpaces === pathNode) {
15381528
result = this._getItemByField(fieldName, item[subItemsField]);
15391529

15401530
// eslint-disable-next-line max-depth
@@ -1543,10 +1533,15 @@ class Form extends Widget<FormProperties> {
15431533
}
15441534
}
15451535

1546-
if (!isGroupWithName || (isGroupWithName && nameWithoutSpaces === pathNode)) {
1536+
const isGroupPathNodeOrUnnamed = !isGroupWithName
1537+
|| (isGroupWithName && nameWithoutSpaces === pathNode);
1538+
1539+
if (isGroupPathNodeOrUnnamed && path.length) {
1540+
result = this._searchItemInEverySubItem(path, fieldName, item[subItemsField]);
1541+
15471542
// eslint-disable-next-line max-depth
1548-
if (path.length) {
1549-
result = this._searchItemInEverySubItem(path, fieldName, item[subItemsField]);
1543+
if (!result) {
1544+
break;
15501545
}
15511546
}
15521547
} else {
@@ -1565,20 +1560,17 @@ class Form extends Widget<FormProperties> {
15651560
path: string[],
15661561
fieldName: string,
15671562
items: Item[],
1568-
): Item | false {
1569-
let result: Item | false = false;
1563+
): Item | null {
1564+
let result: Item | null = null;
15701565
each(items, (_index: number, groupItem: GroupItem): boolean => {
15711566
result = this._getItemByFieldPath(path.slice(), fieldName, groupItem);
1567+
15721568
if (result) {
15731569
return false;
15741570
}
15751571
return true;
15761572
});
15771573

1578-
if (!result) {
1579-
return false;
1580-
}
1581-
15821574
return result;
15831575
}
15841576

packages/devextreme/js/__internal/ui/form/form.utils.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ export const tryGetTabPath = (fullPath: string): string => {
6262

6363
export const getItemPath = (
6464
items: PreparedItem[],
65-
item: PreparedItem | false,
65+
item: PreparedItem | null,
6666
isTabs?: boolean,
6767
): string => {
6868
if (!item) {

packages/devextreme/testing/tests/DevExpress.ui.widgets.form/form.tests.js

Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2580,6 +2580,126 @@ QUnit.test('Use \'itemOption\' with groups and one group has empty caption (T359
25802580
assert.equal($testContainer.find('.' + FORM_GROUP_CAPTION_CLASS).last().text(), 'custom', 'new caption rendered');
25812581
});
25822582

2583+
QUnit.test('Use \'itemOption\' with path when items have same name or caption (T1311534)', function(assert) {
2584+
const targetField = {
2585+
itemType: 'simple',
2586+
name: 'Target',
2587+
editorType: 'dxTextBox',
2588+
};
2589+
2590+
const targetGroup = {
2591+
itemType: 'group',
2592+
caption: 'Target',
2593+
items: [
2594+
{ itemType: 'simple', name: 'Field1', editorType: 'dxTextBox', },
2595+
{ itemType: 'simple', name: 'Field2', editorType: 'dxTextBox', },
2596+
{ itemType: 'simple', name: 'Field3', editorType: 'dxTextBox', },
2597+
],
2598+
};
2599+
2600+
const targetFieldInGroup = {
2601+
...targetField,
2602+
caption: 'Target in Group'
2603+
};
2604+
2605+
const form = $('#form').dxForm({
2606+
formData: {},
2607+
items: [
2608+
{
2609+
itemType: 'group',
2610+
name: 'ContainerGroup',
2611+
items: [
2612+
{ itemType: 'simple', name: 'Field4', editorType: 'dxTextBox', },
2613+
targetGroup,
2614+
]
2615+
},
2616+
{
2617+
itemType: 'group',
2618+
name: 'FieldGroup',
2619+
items: [
2620+
targetFieldInGroup,
2621+
{ itemType: 'simple', name: 'Field5', editorType: 'dxTextBox', },
2622+
],
2623+
},
2624+
targetField,
2625+
]
2626+
}).dxForm('instance');
2627+
2628+
assert.deepEqual(form.itemOption('Target'), targetField, 'Simple item retrieved by name');
2629+
assert.deepEqual(form.itemOption('ContainerGroup.Target'), targetGroup, 'Group item in group retrieved by path');
2630+
assert.deepEqual(form.itemOption('FieldGroup.Target'), targetFieldInGroup, 'Simple item in group retrieved by path');
2631+
});
2632+
2633+
QUnit.test('Use \'itemOption\' with path when items have same name in named and unnamed groups (T1311534)', function(assert) {
2634+
const targetField = {
2635+
itemType: 'simple',
2636+
name: 'Target',
2637+
editorType: 'dxTextBox',
2638+
};
2639+
2640+
const targetFieldInGroup = {
2641+
...targetField,
2642+
caption: 'Target in Group'
2643+
};
2644+
2645+
const form = $('#form').dxForm({
2646+
formData: {},
2647+
items: [
2648+
{
2649+
itemType: 'group',
2650+
name: 'FieldGroup',
2651+
items: [
2652+
targetFieldInGroup,
2653+
{ itemType: 'simple', name: 'Field5', editorType: 'dxTextBox', },
2654+
],
2655+
},
2656+
{
2657+
itemType: 'group',
2658+
items: [
2659+
{ itemType: 'simple', name: 'Field4', editorType: 'dxTextBox', },
2660+
targetField,
2661+
]
2662+
},
2663+
]
2664+
}).dxForm('instance');
2665+
2666+
assert.deepEqual(form.itemOption('Target'), targetField, 'Simple item in unnamed group retrieved by name');
2667+
assert.deepEqual(form.itemOption('FieldGroup.Target'), targetFieldInGroup, 'Simple item in group retrieved by path');
2668+
});
2669+
2670+
QUnit.test('Use \'itemOption\' with path in nested groups (T1311534)', function(assert) {
2671+
const targetField = {
2672+
itemType: 'simple',
2673+
name: 'Target',
2674+
editorType: 'dxTextBox',
2675+
};
2676+
2677+
const targetFieldInGroup = {
2678+
...targetField,
2679+
caption: 'Target in Group'
2680+
};
2681+
2682+
const form = $('#form').dxForm({
2683+
formData: {},
2684+
items: [{
2685+
itemType: 'group',
2686+
items: [
2687+
{
2688+
itemType: 'group',
2689+
name: 'FieldGroup',
2690+
items: [
2691+
targetFieldInGroup,
2692+
{ itemType: 'simple', name: 'Field5', editorType: 'dxTextBox', },
2693+
],
2694+
},
2695+
{ itemType: 'simple', name: 'Field4', editorType: 'dxTextBox', },
2696+
]
2697+
}]
2698+
}).dxForm('instance');
2699+
2700+
assert.deepEqual(form.itemOption('FieldGroup.Target'), targetFieldInGroup, 'Simple item in group retrieved by path');
2701+
});
2702+
25832703
QUnit.test('Use \'itemOption\' with tabs', function(assert) {
25842704
const $testContainer = $('#form').dxForm({
25852705
formData: { EmployeeID: 1, LastName: 'John', FirstName: 'Dow', BirthData: '01/01/1970', HireDate: '12/11/1995', Country: 'USA', City: 'Phoenix', Region: 'Arizona', Title: 'Ms' },

0 commit comments

Comments
 (0)