Skip to content

Commit

Permalink
feature #1505 [Autocomplete] Reset TomSelect when updating controller…
Browse files Browse the repository at this point in the history
… attributes (pierredup)

This PR was squashed before being merged into the 2.x branch.

Discussion
----------

[Autocomplete] Reset TomSelect when updating controller attributes

| Q             | A
| ------------- | ---
| Bug fix?      | yes
| New feature?  | no
| Issues        | Fix #1500
| License       | MIT

When using remote data for Autocomplete, the mutation observer is not started, so the select cannot be reset when some options change (E.G when limiting the options returned after selecting other options using extra_options from #1322).

Instead, we start the mutation observer when using remote data. When the observer runs and checks if the options have changes, we explicitly set the `areOptionsEquivalent` to `true`, since the page will just render an empty `select`. We also check if any of the `data-autocomplete` attributes changes and forces a reset (E.G using extra_options, the `data-autocomplete-url` value can be different when using extra options, so we reset the select when this attribute changes).

This fixes only one of the issues from #1500, I'll investigate the other issues and create separate PRs.

Commits
-------

d8fb3fb [Autocomplete] Reset TomSelect when updating controller attributes
  • Loading branch information
smnandre committed Dec 23, 2024
2 parents cddafa8 + d8fb3fb commit f8ed736
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 f8ed736

Please sign in to comment.