-
-
Notifications
You must be signed in to change notification settings - Fork 327
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Autocomplete][LiveComponent] Select box doesn't reset when used in a live component #1500
Comments
Hey @pierredup! Ok, let's see if we can fix this :). The underlying problem is that TomSelect does NOT like to reset itself when things change on the underlying A) A The autocomplete live controller has logic to try to determine when TomSelect needs to be reset - https://github.com/symfony/ux/blob/2.x/src/Autocomplete/assets/src/controller.ts#L398-L401 It looks like we may need more there. We already check to see if the options are different between the existing Additionally, it seems like we should perhaps look at the "selected" values before vs after. And if those are different, also trigger a reset. Let me know if this can help you dig a bit deeper about the issue. I have #1502 open which makes changes in this same area, but I don't think it addresses your issue. |
Yes that's correct.
Correct again :)
When the component re-renders, the select is empty (since it lazy loads the options when opening the select for the first time). So I'm not sure if it will be possible to know which items are selected
I don't set any default form values, so selecting any option won't have it selected by default on re-render (or page reload). |
When using #1322, the only thing that is different from the rendered content, is the |
So, if you have 2 items selected, then you submit the form and the new html renders either an empty select (meaning, of course, that zero options are selected), that should trigger TomSelect to reset I think. Btw, another solution in general to think about is leveraging morphing events. For example, turbo 8 dispatches several events during morphing and at some point, live components will do the same to match. Perhaps leveraging those somehow might be easier than a mutation observer. They could allow us, at least, to easily know which attributes are being modified on which elements in a more standard way. |
This does not happen, because there is nothing to trigger the reset. The mutation observer doesn't run in this scenario, so there is nothing in the Autocomplete controller that would trigger the reset.
Cool, will have a look at this |
Awesome :). Though, I'm still going back and forth on this - it's just a suggestion.
Ah yes, because the I'm writing this as my son just woke up - so not 100% thought-out yet. But this is a problem that has been on my mind a lot lately to get solved correctly. |
FYI - I have #1512 as a WIP to address more of the issues on a (hopefully) final & robust way. I'll be gone for several days. If you are eager & want to play with that code and keep going, please feel free :). I added several quick things (and a page to test them on in ux.symfony.com), but was only starting to test things and work out the bugs. |
Hi ! I don't know if the problem has been resolved since, but I'm here to explain the same type of problem and the solution put in place: I have a page in which I list items, and a button allowing me to open a modal containing an addition form for my entity. Everything is managed with LiveComponent. The form contains an EntityType field with #[LiveAction]
public function save(EntityManagerInterface $entityManager, Request $request): void
{
$this->submitForm();
/** @var MeetingPoint $meetingPoint */
$meetingPoint = $this->getForm()->getData();
if ($this->meeting) {
$meetingPoint->setMeeting($this->meeting);
}
$entityManager->persist($meetingPoint);
$entityManager->flush();
$this->resetForm();
$this->dispatchBrowserEvent('modal:close');
$this->emit('meeting-planning:refresh');
} Except that if I click again on the add button to display the creation form, the autocomplete field was not reset. Worse, even when selecting a new value, and submitting the form, it kept the old value. Capture.video.du.2024-03-25.09-58-15.webmAs you see in the video, the 1st time I select a user, but when I open the modal a second time, that same user is still selected, and if I take another one instead and submit the form, it is still the one that I had previously selected which is chosen. Even weirder, if I open the modal again, and click on the cross (to the right of the field) to clear the select, and I choose a new one, if I submit, it actually takes one other than the one I want. I was inspired by the method of the author of this issue in order to create a controller-stimulus that I add to my components using an ajax field. tomselect-reset-controller.js import { Controller } from '@hotwired/stimulus';
import TomSelect from 'tom-select';
import { getComponent } from '@symfony/ux-live-component';
/* stimulusFetch: 'lazy' */
export default class extends Controller {
async initialize() {
this.component = await getComponent(this.element);
window.addEventListener('select:clear', (event) => {
var elements = this.element.querySelectorAll('.tomselected');
elements.forEach(element => {
if (element.tomselect) {
var settings = element.tomselect.settings;
element.tomselect.destroy();
new TomSelect(element, settings);
}
});
});
}
} This controller will listen on the "select:clear" event, retrieve the autocomplete fields using the class added automatically by the "autocomplete => true" attribute, and reset the field. Now in my template : <div {{ attributes.add(stimulus_controller('tomselect-reset')) }}>
// form ...
</div> In my component : //...
$this->resetForm();
$this->dispatchBrowserEvent('select:clear'); // will reset the select
$this->dispatchBrowserEvent('modal:close');
$this->emit('meeting-planning:refresh'); And now : Capture.video.du.2024-03-25.10-09-55.webmHas this type of problem been resolved since then, @weaverryan ? |
@pierredup I'm not sure which approach (#1505 #1512) is better, but with a little guidance I can help you to test the best option and solve this 💪 |
@antoniovj1 As far as I can tell, both #1505 and #1512 are required, since it fixes different issues (although I haven't checked if #1512 fixes the same issue addressed in #1505, so maybe that is a first starting point) |
I've had a few days very busy 🥵 Your PR @pierredup seems perfect to me. I'm going to check the @weaverryan one to see if I can contribute something or not |
That's almost great, but unfortunatly it reset options in my case (with autocomplete fields). elements.forEach(element => {
if (element.tomselect) {
element.tomselect.clear(true); // True for "no change event will be fired on the original input." (default: false)
}
}); It works for me for autocomplete fields or not. |
When using the Autocomplete component in a form as part of a LiveComponent, the field is not reset when re-rendering the component (E.G when submitting the form). The previous selected values are still selected.
Here is an example using a multi-select dropdown, with a custom query builder that removes the selected items from the list:
Screen.Recording.2024-02-15.at.15.21.08.mov
When changing the form to an Autocomplete type, and selecting items, it doesn't get removed from the select
Screen.Recording.2024-02-15.at.15.24.12.mov
Currently in order to reset the autocomplete dropdown, I'm emitting a custom browser event with a custom controller on the select with the following which seems to work fine:
The text was updated successfully, but these errors were encountered: