Skip to content

Commit

Permalink
[Autocomplete] Reset TomSelect when updating controller attributes
Browse files Browse the repository at this point in the history
  • Loading branch information
pierredup authored and smnandre committed Dec 23, 2024
1 parent cddafa8 commit d8fb3fb
Show file tree
Hide file tree
Showing 5 changed files with 86 additions and 3 deletions.
4 changes: 4 additions & 0 deletions src/Autocomplete/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -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
Expand Down
1 change: 1 addition & 0 deletions src/Autocomplete/assets/dist/controller.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
4 changes: 3 additions & 1 deletion src/Autocomplete/assets/dist/controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,9 @@ class default_1 extends Controller {
}
}
}
urlValueChanged() {
this.resetTomSelect();
}
getMaxOptions() {
return this.selectElement ? this.selectElement.options.length : 50;
}
Expand Down Expand Up @@ -131,7 +134,6 @@ class default_1 extends Controller {
this.element.innerHTML = currentHtml;
this.initializeTomSelect();
this.tomSelect.setValue(currentValue);
this.startMutationObserver();
}
}
changeTomSelectDisabledState(isDisabled) {
Expand Down
6 changes: 4 additions & 2 deletions src/Autocomplete/assets/src/controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,10 @@ export default class extends Controller {
}
}

urlValueChanged() {
this.resetTomSelect();
}

#getCommonConfig(): Partial<TomSettings> {
const plugins: TPluginHash = {};

Expand Down Expand Up @@ -391,8 +395,6 @@ export default class extends Controller {
this.element.innerHTML = currentHtml;
this.initializeTomSelect();
this.tomSelect.setValue(currentValue);

this.startMutationObserver();
}
}

Expand Down
74 changes: 74 additions & 0 deletions src/Autocomplete/assets/test/controller.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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(`
<label for="the-select">Items</label>
<select
id="the-select"
data-testid="main-element"
data-controller="autocomplete"
data-autocomplete-url-value="/path/to/autocomplete"
></select>
`);

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 = `
<select
id="the-select"
data-testid="main-element"
data-controller="autocomplete"
data-autocomplete-url-value="/path/to/autocomplete2"
></select>
`;

// 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(`
<label for="the-input">Items</label>
Expand Down

0 comments on commit d8fb3fb

Please sign in to comment.