diff --git a/src/Autocomplete/CHANGELOG.md b/src/Autocomplete/CHANGELOG.md index d7384fee5f9..2498c7b9bfb 100644 --- a/src/Autocomplete/CHANGELOG.md +++ b/src/Autocomplete/CHANGELOG.md @@ -1,5 +1,9 @@ # CHANGELOG +## 2.23.0 + +- Reset TomSelect when updating url attribute #1505 + ## 2.22.0 - Take `labelField` TomSelect option into account #2382 diff --git a/src/Autocomplete/assets/dist/controller.d.ts b/src/Autocomplete/assets/dist/controller.d.ts index 59938a721c6..d5cc6b3e272 100644 --- a/src/Autocomplete/assets/dist/controller.d.ts +++ b/src/Autocomplete/assets/dist/controller.d.ts @@ -40,6 +40,7 @@ export default class extends Controller { connect(): void; initializeTomSelect(): void; disconnect(): void; + urlValueChanged(): void; private getMaxOptions; get selectElement(): HTMLSelectElement | null; get formElement(): HTMLInputElement | HTMLSelectElement; diff --git a/src/Autocomplete/assets/dist/controller.js b/src/Autocomplete/assets/dist/controller.js index fb04294a331..e021770d8b5 100644 --- a/src/Autocomplete/assets/dist/controller.js +++ b/src/Autocomplete/assets/dist/controller.js @@ -91,6 +91,9 @@ class default_1 extends Controller { } } } + urlValueChanged() { + this.resetTomSelect(); + } getMaxOptions() { return this.selectElement ? this.selectElement.options.length : 50; } @@ -131,7 +134,6 @@ class default_1 extends Controller { this.element.innerHTML = currentHtml; this.initializeTomSelect(); this.tomSelect.setValue(currentValue); - this.startMutationObserver(); } } changeTomSelectDisabledState(isDisabled) { diff --git a/src/Autocomplete/assets/src/controller.ts b/src/Autocomplete/assets/src/controller.ts index 38b324fcb68..6b68283b51d 100644 --- a/src/Autocomplete/assets/src/controller.ts +++ b/src/Autocomplete/assets/src/controller.ts @@ -128,6 +128,10 @@ export default class extends Controller { } } + urlValueChanged() { + this.resetTomSelect(); + } + #getCommonConfig(): Partial { const plugins: TPluginHash = {}; @@ -391,8 +395,6 @@ export default class extends Controller { this.element.innerHTML = currentHtml; this.initializeTomSelect(); this.tomSelect.setValue(currentValue); - - this.startMutationObserver(); } } diff --git a/src/Autocomplete/assets/test/controller.test.ts b/src/Autocomplete/assets/test/controller.test.ts index e17dc6ae8d3..5b72e7fb075 100644 --- a/src/Autocomplete/assets/test/controller.test.ts +++ b/src/Autocomplete/assets/test/controller.test.ts @@ -138,6 +138,80 @@ describe('AutocompleteController', () => { expect(fetchMock.requests()[1].url).toEqual('/path/to/autocomplete?query=foo'); }); + it('resets when ajax URL attribute on a select element changes', async () => { + const { container, tomSelect } = await startAutocompleteTest(` + + + `); + + const selectElement = getByTestId(container, 'main-element') as HTMLSelectElement; + + // initial Ajax request on focus + fetchMock.mockResponseOnce( + JSON.stringify({ + results: [ + { + value: 3, + text: 'salad', + }, + ], + }) + ); + + fetchMock.mockResponseOnce( + JSON.stringify({ + results: [ + { + value: 1, + text: 'pizza', + }, + { + value: 2, + text: 'popcorn', + }, + ], + }) + ); + + const controlInput = tomSelect.control_input; + + // wait for the initial Ajax request to finish + userEvent.click(controlInput); + await waitFor(() => { + expect(container.querySelectorAll('.option[data-selectable]')).toHaveLength(1); + }); + + controlInput.value = 'foo'; + controlInput.dispatchEvent(new Event('input')); + + await waitFor(() => { + expect(container.querySelectorAll('.option[data-selectable]')).toHaveLength(2); + }); + + expect(selectElement.value).toBe(''); + tomSelect.addItem('2'); + expect(selectElement.value).toBe('2'); + + selectElement.outerHTML = ` + + `; + + // wait for the MutationObserver to flush these changes + await shortDelay(10); + + expect(selectElement.value).toBe(''); + }); + it('connect with ajax URL on an input element', async () => { const { container, tomSelect } = await startAutocompleteTest(`