Skip to content

Commit 76fa476

Browse files
committed
fix: Resolve ComboBox value update failure with internalId (#9071)
- ComboBox: Parse DOM ID using list.getItemRecordId before store lookup. - Added unit test to verify ComboBox selection with internalId.
1 parent 901636f commit 76fa476

2 files changed

Lines changed: 121 additions & 1 deletion

File tree

src/form/field/ComboBox.mjs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -599,7 +599,8 @@ class ComboBox extends Picker {
599599
record;
600600

601601
if (typeof selected === 'string') {
602-
record = store.get(selected);
602+
selected = list.getItemRecordId(selected);
603+
record = store.get(selected);
603604

604605
if (!record && list.useInternalId) {
605606
record = store.items.find(r => list.getRecordId(r) === selected)
Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
2+
import {setup} from '../../../setup.mjs';
3+
4+
const appName = 'ComboBoxInternalIdTest';
5+
6+
setup({
7+
neoConfig: {
8+
allowVdomUpdatesInTests: true,
9+
unitTestMode : true,
10+
useDomApiRenderer : true,
11+
useVdomWorker : false
12+
},
13+
appConfig: {
14+
name : appName,
15+
isMounted : () => true,
16+
vnodeInitialising: false
17+
}
18+
});
19+
20+
import {test, expect} from '@playwright/test';
21+
import Neo from '../../../../../src/Neo.mjs';
22+
import * as core from '../../../../../src/core/_export.mjs';
23+
import InstanceManager from '../../../../../src/manager/Instance.mjs';
24+
import ComponentManager from '../../../../../src/manager/Component.mjs';
25+
import VdomHelper from '../../../../../src/vdom/Helper.mjs';
26+
import DomApiVnodeCreator from '../../../../../src/vdom/util/DomApiVnodeCreator.mjs';
27+
import ComboBox from '../../../../../src/form/field/ComboBox.mjs';
28+
import Store from '../../../../../src/data/Store.mjs';
29+
import Model from '../../../../../src/data/Model.mjs';
30+
31+
test.describe('Neo.form.field.ComboBox InternalId Support', () => {
32+
let combo, store;
33+
34+
class TestModel extends Model {
35+
static config = {
36+
className: 'Test.Unit.Combo.InternalId.TestModel',
37+
fields : [{name: 'id', type: 'Integer'}, {name: 'name', type: 'String'}]
38+
}
39+
}
40+
TestModel = Neo.setupClass(TestModel);
41+
42+
test.beforeEach(async () => {
43+
// Mock Neo.main.DomAccess
44+
Neo.main = {
45+
DomAccess: {
46+
focus: () => {}
47+
},
48+
addon: {
49+
Navigator: {
50+
subscribe: () => {},
51+
unsubscribe: () => {},
52+
navigateTo: () => {}
53+
}
54+
}
55+
};
56+
Neo.currentWorker = {};
57+
Neo.currentWorker.promiseMessage = async () => ({});
58+
59+
store = Neo.create(Store, {
60+
model: TestModel,
61+
autoInitRecords: true,
62+
data: [
63+
{id: 1, name: 'Item 1'},
64+
{id: 2, name: 'Item 2'}
65+
]
66+
});
67+
68+
combo = Neo.create(ComboBox, {
69+
appName,
70+
store,
71+
displayField: 'name',
72+
valueField : 'id',
73+
labelPosition: 'top' // Avoid inline layout complexities for unit test
74+
});
75+
76+
await combo.initVnode();
77+
combo.mounted = true;
78+
79+
// Force picker creation
80+
combo.getPicker();
81+
});
82+
83+
test.afterEach(() => {
84+
combo?.destroy();
85+
store?.destroy();
86+
});
87+
88+
test('Selection from list with internalId should update value', async () => {
89+
// 1. Get the list component
90+
const list = combo.list;
91+
expect(list).toBeDefined();
92+
93+
// 2. Verify List is using internalId
94+
expect(list.useInternalId).toBe(true);
95+
96+
// 3. Simulate selection from List
97+
// ListModel stores DOM IDs (e.g., "neo-list-1__neo-record-1")
98+
const record = store.getAt(0);
99+
const internalId = store.getInternalId(record);
100+
const domId = list.getItemId(record); // "combo-list-id__neo-record-1"
101+
102+
expect(domId).toContain(internalId);
103+
expect(domId).toContain('__');
104+
105+
// 4. Trigger selection change event from the list's selection model
106+
// We simulate what ListModel fires: { selection: [domId] }
107+
await combo.onListItemSelectionChange({
108+
selection: [domId]
109+
});
110+
111+
// 5. Assert ComboBox value
112+
// The value should be the record itself (since forceSelection is true default behavior for internal set)
113+
// or the record ID depending on how we check. ComboBox.value usually holds the record or valueField.
114+
// Actually ComboBox.value holds the record if selected via list.
115+
116+
expect(combo.value).toBe(record);
117+
expect(combo.inputValue).toBe('Item 1');
118+
});
119+
});

0 commit comments

Comments
 (0)