Skip to content

Commit

Permalink
fix: allow propagating enter key event after selecting value (#5477) (#…
Browse files Browse the repository at this point in the history
…5490)

Co-authored-by: Sascha Ißbrücker <sissbruecker@vaadin.com>
  • Loading branch information
vaadin-bot and sissbruecker authored Feb 7, 2023
1 parent d022b09 commit 29392db
Show file tree
Hide file tree
Showing 2 changed files with 62 additions and 26 deletions.
6 changes: 5 additions & 1 deletion packages/combo-box/src/vaadin-combo-box-mixin.js
Original file line number Diff line number Diff line change
Expand Up @@ -764,7 +764,11 @@ export const ComboBoxMixin = (subclass) =>
// Do not commit value when custom values are disallowed and input value is not a valid option
// also stop propagation of the event, otherwise the user could submit a form while the input
// still contains an invalid value
if (!this.allowCustomValue && this._inputElementValue !== '' && this._focusedIndex < 0) {
const hasInvalidOption =
this._focusedIndex < 0 &&
this._inputElementValue !== '' &&
this._getItemLabel(this.selectedItem) !== this._inputElementValue;
if (!this.allowCustomValue && hasInvalidOption) {
// Do not submit the surrounding form.
e.preventDefault();
// Do not trigger global listeners
Expand Down
82 changes: 57 additions & 25 deletions packages/combo-box/test/keyboard.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,13 @@ describe('keyboard', () => {
});

describe('selecting items', () => {
const verifyEnterKeyPropagation = (allowPropagation) => {
const enterEvent = keyboardEventFor('keydown', 13, [], 'Enter');
const stopPropagationSpy = sinon.spy(enterEvent, 'stopPropagation');
input.dispatchEvent(enterEvent);
expect(stopPropagationSpy.called).to.equal(!allowPropagation);
};

describe('auto-open', () => {
beforeEach(async () => {
comboBox.value = 'bar';
Expand Down Expand Up @@ -199,18 +206,41 @@ describe('keyboard', () => {
});

it('should stop propagation of the keyboard enter event when dropdown is opened', () => {
const keydownSpy = sinon.spy();
document.addEventListener('keydown', keydownSpy);
enterKeyDown(input);
expect(keydownSpy.called).to.be.false;
verifyEnterKeyPropagation(false);
});

it('should stop propagation of the keyboard enter event when input value is invalid', () => {
setInputValue(comboBox, 'foobar');
const keydownSpy = sinon.spy();
document.addEventListener('keydown', keydownSpy);

verifyEnterKeyPropagation(false);
});

it('should propagate keyboard enter event after entering an unknown option when custom values are allowed', () => {
comboBox.allowCustomValue = true;
setInputValue(comboBox, 'foobar');
enterKeyDown(input);

verifyEnterKeyPropagation(true);
});

it('should propagate keyboard enter event if filtered items are cleared after selecting a predefined option', () => {
setInputValue(comboBox, 'foo');
enterKeyDown(input);
// Simulate user or data provider mixin resetting filtered items after closing overlay
comboBox.filteredItems = [];
expect(comboBox._focusedIndex).to.equal(-1);

verifyEnterKeyPropagation(true);
});

it('should propagate keyboard enter event after clearing the value', () => {
setInputValue(comboBox, 'foo');
enterKeyDown(input);

setInputValue(comboBox, '');
enterKeyDown(input);
expect(keydownSpy.called).to.be.false;

verifyEnterKeyPropagation(true);
});

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

it('should stop propagation of the keyboard enter event when input value is invalid', () => {
setInputValue(comboBox, 'foobar');
const keydownSpy = sinon.spy();
document.addEventListener('keydown', keydownSpy);
enterKeyDown(input);
expect(keydownSpy.called).to.be.false;

verifyEnterKeyPropagation(false);
});

it('should not stop propagation of the keyboard enter event when input has a predefined option', () => {
it('should propagate the keyboard enter event when input has a predefined option', () => {
setInputValue(comboBox, 'foo');
expect(comboBox.opened).to.be.false;
const keydownSpy = sinon.spy();
document.addEventListener('keydown', keydownSpy);

verifyEnterKeyPropagation(true);
});

it('should propagate keyboard enter event if filtered items are cleared after selecting a predefined option', () => {
setInputValue(comboBox, 'foo');
enterKeyDown(input);
expect(keydownSpy.called).to.be.true;
// Simulate user or data provider mixin resetting filtered items after closing overlay
comboBox.filteredItems = [];
expect(comboBox._focusedIndex).to.equal(-1);

verifyEnterKeyPropagation(true);
});

it('should not stop propagation of the keyboard enter event when input has a custom value', () => {
it('should propagate the keyboard enter event when input has a custom value', () => {
comboBox.allowCustomValue = true;
setInputValue(comboBox, 'foobar');
const keydownSpy = sinon.spy();
document.addEventListener('keydown', keydownSpy);
enterKeyDown(input);
expect(keydownSpy.called).to.be.true;

verifyEnterKeyPropagation(true);
});

it('should not stop propagation of the keyboard enter event when input is empty', () => {
it('should propagate the keyboard enter event when input is empty', () => {
comboBox.allowCustomValue = true;
setInputValue(comboBox, '');
const keydownSpy = sinon.spy();
document.addEventListener('keydown', keydownSpy);
enterKeyDown(input);
expect(keydownSpy.called).to.be.true;

verifyEnterKeyPropagation(true);
});
});
});
Expand Down

0 comments on commit 29392db

Please sign in to comment.