[LiveComponent] `ComponentWithFormTrait` out-of-sync with browsers’ changes
While working with symfonycasts/dynamic-forms I observed two issues which seem to stem from the same cause:
- A not-
expandedChoiceTypewithout placeholder whose value isnullwill appear as a<select>with the first<option>selected. The state of the component is then out-of-sync. - When refreshing a page with a form, browsers will populate fields with the value the user previously changed. As this happens without any user interaction, the component won’t be aware of these changes and will keep its default state.
The first issue can be worked around by adding a placeholder, and the second by setting to the fields which must keep their value the autocomplete attribute to off.
Maybe the component could react to the load event to update its state?
Hey @MatTheCat could you move your issue to symfonycasts/dynamic-forms repo. I don't have any answer since I don't use this bundle sorry!
The problem here is more global (and almost concerns classic forms too)..
You can experience it on the demo https://ux.symfony.com/demos/live-component/dependent-form-fields
Select something in the first input.
Submit
Then refresh (just once) your browser.
The browser select the choice you did select the first time, but the inner value is not set... and from there starts a desync.
There is no easy way out of this... but in term of UX this is not good :/
So the questiion is not "do we have a bug", but .... "how can we think about something smart to improve DX/UX when browsers autofill fields"
cc this Slack conversation too : https://symfony-devs.slack.com/archives/C01FN4EQNLX/p1720614759376709
The solution seems to be some live changes on the form attributes (autocomplete / inert / etc..) executed during the component/form lifetime.
But this is something that must be done in userland i fear... as this could have negative impact on accessibility, or side effect on style, other scripts, etc...
- https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/autocomplete
- https://bugzilla.mozilla.org/show_bug.cgi?id=1688183
Took me time, but i check tested all this deeply, on Firefox at least.
TL;DR; "autocomplete=off" on the form tag itself solves almost everything.
{{ form_start(form, {
attr: {
autocomplete: 'off',
}
}) }}
You still can enjoy autocompletion if you specify it's type
->add('phone', TelType::class, [
'mapped' => false,
'label' => 'Phone',
'attr' => ['autocomplete' => 'phone'],
])
This field will benefic from autocompletion "on focus"... but thanks to the root "autcomplete=off" attribute, no problem at all during loading.
So i guess this is mainly a matter of ... docs ?
Thanks for testing!
Sadly, live components being incompatible with browsers keeping user-modified form values on reload seems like quite the deal-breaker 😅
In addition of being a workaround, autocomplete=off also wonʼt solve the non-nullable <select> null default value problem.
But if one has to live with it, this should indeed be documented!
I'm more and more thinking there is something not clear about the state in live component forms. In the end there must be "one source of truth", not two.
What would you suggest for the select?
Because i also checked some (dirty) js things and i think we can trigger some change évent when the browser fill data. Not sure for the select as it is indeterminate.
SO!
This is probably (partially at least) due to this code, that has not be updated since we allow "name" on inputs and not only data-model
https://github.com/symfony/ux/blob/89c7fa95d8d71af01fb604533755b2acbeb26ce5/src/LiveComponent/assets/src/Component/plugins/SetValueOntoModelFieldsPlugin.ts#L33