Skip to content

Commit 85c295c

Browse files
fix: allow propagating enter key event after selecting value (#5477) (#5488)
Co-authored-by: Sascha Ißbrücker <sissbruecker@vaadin.com>
1 parent 6531493 commit 85c295c

File tree

2 files changed

+62
-26
lines changed

2 files changed

+62
-26
lines changed

packages/combo-box/src/vaadin-combo-box-mixin.js

+5-1
Original file line numberDiff line numberDiff line change
@@ -782,7 +782,11 @@ export const ComboBoxMixin = (subclass) =>
782782
// Do not commit value when custom values are disallowed and input value is not a valid option
783783
// also stop propagation of the event, otherwise the user could submit a form while the input
784784
// still contains an invalid value
785-
if (!this.allowCustomValue && this._inputElementValue !== '' && this._focusedIndex < 0) {
785+
const hasInvalidOption =
786+
this._focusedIndex < 0 &&
787+
this._inputElementValue !== '' &&
788+
this._getItemLabel(this.selectedItem) !== this._inputElementValue;
789+
if (!this.allowCustomValue && hasInvalidOption) {
786790
// Do not submit the surrounding form.
787791
e.preventDefault();
788792
// Do not trigger global listeners

packages/combo-box/test/keyboard.test.js

+57-25
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,13 @@ describe('keyboard', () => {
164164
});
165165

166166
describe('selecting items', () => {
167+
const verifyEnterKeyPropagation = (allowPropagation) => {
168+
const enterEvent = keyboardEventFor('keydown', 13, [], 'Enter');
169+
const stopPropagationSpy = sinon.spy(enterEvent, 'stopPropagation');
170+
input.dispatchEvent(enterEvent);
171+
expect(stopPropagationSpy.called).to.equal(!allowPropagation);
172+
};
173+
167174
describe('auto-open', () => {
168175
beforeEach(async () => {
169176
comboBox.value = 'bar';
@@ -199,18 +206,41 @@ describe('keyboard', () => {
199206
});
200207

201208
it('should stop propagation of the keyboard enter event when dropdown is opened', () => {
202-
const keydownSpy = sinon.spy();
203-
document.addEventListener('keydown', keydownSpy);
204-
enterKeyDown(input);
205-
expect(keydownSpy.called).to.be.false;
209+
verifyEnterKeyPropagation(false);
206210
});
207211

208212
it('should stop propagation of the keyboard enter event when input value is invalid', () => {
209213
setInputValue(comboBox, 'foobar');
210-
const keydownSpy = sinon.spy();
211-
document.addEventListener('keydown', keydownSpy);
214+
215+
verifyEnterKeyPropagation(false);
216+
});
217+
218+
it('should propagate keyboard enter event after entering an unknown option when custom values are allowed', () => {
219+
comboBox.allowCustomValue = true;
220+
setInputValue(comboBox, 'foobar');
221+
enterKeyDown(input);
222+
223+
verifyEnterKeyPropagation(true);
224+
});
225+
226+
it('should propagate keyboard enter event if filtered items are cleared after selecting a predefined option', () => {
227+
setInputValue(comboBox, 'foo');
228+
enterKeyDown(input);
229+
// Simulate user or data provider mixin resetting filtered items after closing overlay
230+
comboBox.filteredItems = [];
231+
expect(comboBox._focusedIndex).to.equal(-1);
232+
233+
verifyEnterKeyPropagation(true);
234+
});
235+
236+
it('should propagate keyboard enter event after clearing the value', () => {
237+
setInputValue(comboBox, 'foo');
238+
enterKeyDown(input);
239+
240+
setInputValue(comboBox, '');
212241
enterKeyDown(input);
213-
expect(keydownSpy.called).to.be.false;
242+
243+
verifyEnterKeyPropagation(true);
214244
});
215245

216246
it('should not close the overlay with enter when custom values are not allowed', () => {
@@ -399,37 +429,39 @@ describe('keyboard', () => {
399429

400430
it('should stop propagation of the keyboard enter event when input value is invalid', () => {
401431
setInputValue(comboBox, 'foobar');
402-
const keydownSpy = sinon.spy();
403-
document.addEventListener('keydown', keydownSpy);
404-
enterKeyDown(input);
405-
expect(keydownSpy.called).to.be.false;
432+
433+
verifyEnterKeyPropagation(false);
406434
});
407435

408-
it('should not stop propagation of the keyboard enter event when input has a predefined option', () => {
436+
it('should propagate the keyboard enter event when input has a predefined option', () => {
409437
setInputValue(comboBox, 'foo');
410438
expect(comboBox.opened).to.be.false;
411-
const keydownSpy = sinon.spy();
412-
document.addEventListener('keydown', keydownSpy);
439+
440+
verifyEnterKeyPropagation(true);
441+
});
442+
443+
it('should propagate keyboard enter event if filtered items are cleared after selecting a predefined option', () => {
444+
setInputValue(comboBox, 'foo');
413445
enterKeyDown(input);
414-
expect(keydownSpy.called).to.be.true;
446+
// Simulate user or data provider mixin resetting filtered items after closing overlay
447+
comboBox.filteredItems = [];
448+
expect(comboBox._focusedIndex).to.equal(-1);
449+
450+
verifyEnterKeyPropagation(true);
415451
});
416452

417-
it('should not stop propagation of the keyboard enter event when input has a custom value', () => {
453+
it('should propagate the keyboard enter event when input has a custom value', () => {
418454
comboBox.allowCustomValue = true;
419455
setInputValue(comboBox, 'foobar');
420-
const keydownSpy = sinon.spy();
421-
document.addEventListener('keydown', keydownSpy);
422-
enterKeyDown(input);
423-
expect(keydownSpy.called).to.be.true;
456+
457+
verifyEnterKeyPropagation(true);
424458
});
425459

426-
it('should not stop propagation of the keyboard enter event when input is empty', () => {
460+
it('should propagate the keyboard enter event when input is empty', () => {
427461
comboBox.allowCustomValue = true;
428462
setInputValue(comboBox, '');
429-
const keydownSpy = sinon.spy();
430-
document.addEventListener('keydown', keydownSpy);
431-
enterKeyDown(input);
432-
expect(keydownSpy.called).to.be.true;
463+
464+
verifyEnterKeyPropagation(true);
433465
});
434466
});
435467
});

0 commit comments

Comments
 (0)