Set FormType's option dynamically, based on the data of a sibling FormType?

Viewed 453

I have a Symfony Form with a custom ChoiceType that needs to filter the available choices, based on the value of another field (a sibling form-type inside the same form).

I am using EasyAdmin CMS that doesn't allow its fields to pass down additional dynamic type_options to their form-types, because of it YAML configuration. And I'd like the the custom ChoiceFormType to have encapsulate the logic on how to resolve its own options.

But modifying the options based on other form data seems impossible.

  • form data is NULL inside buildForm(); I can access it just from FormEvents.
  • inside FormEvents::PRE_SET_DATA I cannot replace the current type with one having the modified options.
public function buildForm(FormBuilderInterface $builder, array $options)
{
    $builder->addEventListener(FormEvents::PRE_SET_DATA, function (FormEvent $event) use ($builder, $options) {
        $parent = $event->getForm()->getParent();
        $parent_data = $parent-getData();
        $other_field_value = $parent_data->getOtherFieldValue();
        $filtered_choices = array_filter(fn($choice) => $choice !== $other_field_value);
        $options['choices'] = $filtered_choices;

        $parent->add($form, get_class($this), $options);   // THIS FAILS
    }

Trying to set the options, resolved dynamically based on the form data, fails with:

A cycle was detected. Listeners to the PRE_SET_DATA event must not call setData(). You should call setData() on the FormEvent object instead.

But the $event->setData() works just on the current FormType, not on the the whole form.

What's the pattern to make a FormType set its own options dynamically, based on the value of a sibling form type?

0 Answers
Related