diff --git a/docs/resources/changelog.md b/docs/resources/changelog.md index 48a864968..0bc9ad663 100644 --- a/docs/resources/changelog.md +++ b/docs/resources/changelog.md @@ -17,6 +17,7 @@ New versions of Shoelace are released as-needed and generally occur when a criti - Fixed a bug in `` that caused `sl-tab-show` to be emitted when activating the close button - Fixed a bug in `` that caused `--track-color` to be invisible with certain colors - Fixed a bug in `` that caused the focus color to show when selecting menu items with a mouse or touch device +- Fixed a bug in `` that caused `sl-change` and `sl-input` to be emitted too early [#1201](https://github.com/shoelace-style/shoelace/issues/1201) - Updated `@shoelace-style/localize` to 3.1.0 When using `` the default value for `autocapitalize`, `autocomplete`, and `autocorrect` may be affected due to the bug fixed in [#1205](https://github.com/shoelace-style/shoelace/issues/1205). For any affected users, setting these attributes to `off` will restore the previous behavior. diff --git a/src/components/select/select.test.ts b/src/components/select/select.test.ts index 099ded92d..6976fc868 100644 --- a/src/components/select/select.test.ts +++ b/src/components/select/select.test.ts @@ -162,6 +162,32 @@ describe('', () => { await el.updateComplete; }); + + it('should emit sl-change and sl-input with the correct validation message when the value changes', async () => { + const el = await fixture(html` + + Option 1 + Option 2 + Option 3 + + `); + const option2 = el.querySelectorAll('sl-option')[1]; + const handler = sinon.spy((event: CustomEvent) => { + if (el.validationMessage) { + expect.fail(`Validation message should be empty when ${event.type} is emitted and a value is set`); + } + }); + + el.addEventListener('sl-change', handler); + el.addEventListener('sl-input', handler); + + await clickOnElement(el); + await aTimeout(500); + await clickOnElement(option2); + await el.updateComplete; + + expect(handler).to.be.calledTwice; + }); }); it('should open the listbox when any letter key is pressed with sl-select is on focus', async () => { diff --git a/src/components/select/select.ts b/src/components/select/select.ts index 373b169c3..30e6ec556 100644 --- a/src/components/select/select.ts +++ b/src/components/select/select.ts @@ -253,8 +253,11 @@ export default class SlSelect extends ShoelaceElement implements ShoelaceFormCon this.setSelectedOptions(this.currentOption); } - this.emit('sl-input'); - this.emit('sl-change'); + // Emit after updating + this.updateComplete.then(() => { + this.emit('sl-input'); + this.emit('sl-change'); + }); if (!this.multiple) { this.hide(); @@ -378,9 +381,13 @@ export default class SlSelect extends ShoelaceElement implements ShoelaceFormCon if (this.value !== '') { this.setSelectedOptions([]); this.displayInput.focus({ preventScroll: true }); - this.emit('sl-clear'); - this.emit('sl-input'); - this.emit('sl-change'); + + // Emit after update + this.updateComplete.then(() => { + this.emit('sl-clear'); + this.emit('sl-input'); + this.emit('sl-change'); + }); } } @@ -406,8 +413,11 @@ export default class SlSelect extends ShoelaceElement implements ShoelaceFormCon this.updateComplete.then(() => this.displayInput.focus({ preventScroll: true })); if (this.value !== oldValue) { - this.emit('sl-input'); - this.emit('sl-change'); + // Emit after updating + this.updateComplete.then(() => { + this.emit('sl-input'); + this.emit('sl-change'); + }); } if (!this.multiple) { @@ -442,8 +452,12 @@ export default class SlSelect extends ShoelaceElement implements ShoelaceFormCon if (!this.disabled) { this.toggleOptionSelection(option, false); - this.emit('sl-input'); - this.emit('sl-change'); + + // Emit after updating + this.updateComplete.then(() => { + this.emit('sl-input'); + this.emit('sl-change'); + }); } }