ux icon indicating copy to clipboard operation
ux copied to clipboard

Feature request: dynamic forms

Open zmitic opened this issue 3 years ago • 0 comments

This issue is a feature request of rewriting my existing solution into symfony/ux. It is about removing the need for any JS for dynamic fields, but it does require one stimulus controller.

Sorry it is long, it is very hard to explain the problem itself so feel free to delete irrelevant things.


Problem

Symfony form events are great, but the problem is that users have to write both backend dynamics and lots of JS to dynamically change them.

The example on Symfony docs is just for one field; not only that POST_SUBMIT is complicated, but it also requires JS code per field which doesn't even allow dynamic add/remove or type change.

Avoiding the problem

If user switched to form.pre_submit, lots of the problems disappear. True, we have to work with scalar values but the trade-off is more than worth it. I have a case where collection is changed based on parent selection, and that is not even close to the worse-case scenario I have.

The problem it makes is that errors will still be rendered on individual fields, plus extra field found error if event removed some of them. I have tons of cases like this one, ask if it is not clear (trying to shorten this issue).


Workaround (click to expand)

To avoid custom JS and validation errors rendered during the change, I made (very badly written) bundle that expands forms with dynamic option. This solution works great, no problems here but the code is not something I am proud of.

Usage:

$builder->add('my_field', TextType::class, [
    'dynamic' => true,    //   <---- new option
]);

which would add my stimulus controller to that field. When that field changes, entire form will be submitted and thus, trigger all form events.

Backend would re-render it with new fields, or removed ones... and with no validation errors problem nor the need to manually replaceWith.

Controller code is as before, users does not have to write any extra PHP/JS code (the reason for my bundle and this issue):

public function __invoke(Request $request)
{
    $form = $this->createForm(MyFormType::class);
    // handle request, check for validation, redirect as before

    return $this->renderForm('my_template.html.twig, ['form' => $form]);
}

Or in other words: form does get submitted, all fields do get mapped as usual, form events work no matter how deeply nested it is... but validation errors are cleared.

Form itself is considered not valid which means controller would re-render it.


How it works (click to expand)

Stimulus controller adds hidden field _dynamic_field that will be used by form decorator. This way form events are triggered on backend, but form will be treated as not valid; that is why there is no need for extra PHP/JS.

If I haven't cleared the errors, the re-render process would put validation errors everywhere, including extra field found if event removed some of them.


Feature request

Rewrite this idea in symfony/ux. I think it is solid solution, I have been using it in multiple projects and so far, no problems.

But as I said: the code is bad and I might have missed some edge-case.

zmitic avatar Jun 25 '22 15:06 zmitic