I would like to have 3 choice fields where the options available depend on the selected value of the previous field.
Following the example from the docs, I manage to make this work for two choice fields: https://symfony.com/doc/current/form/dynamic_form_modification.html#dynamic-generation-for-submitted-forms
But I can't wrap my head around adding a third choice field. For example: Company -> Department -> Location
The company field has a FormEvents::POST_SUBMIT
event listener via $builder->get('company')->addEventListener()
because you can't add children to a submitted form, the event listener is added to a subform that can still add children to the parent form. Without this the data is empty on submit.
Which is a problem because the same event listener can't be added to the department field because when adding via $builder->get('department')->addEventListener()
the field doesn't exists because it is added in the event listener.
// src/Form/Type/CompanyType.php
namespace App\Form\Type;
use App\Entity\Department;
use App\Entity\Company;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\Form\FormInterface;
// ...
class CompanyMeetupType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options): void
{
$builder
->add('company', EntityType::class, [
'class' => Company::class,
'placeholder' => '',
])
;
$formModifier = function (FormInterface $form, Company $company = null) {
$departments = null === $company ? [] : $company->getAvailableDepartments();
$form->add('department', EntityType::class, [
'class' => Department::class,
'placeholder' => '',
'choices' => $$departments,
]);
};
$builder->addEventListener(
FormEvents::PRE_SET_DATA,
function (FormEvent $event) use ($formModifier) {
$data = $event->getData();
$formModifier($event->getForm(), $data->getCompany());
}
);
$builder->get('company')->addEventListener(
FormEvents::POST_SUBMIT,
function (FormEvent $event) use ($formModifier) {
// It's important here to fetch $event->getForm()->getData(), as
// $event->getData() will get you the client data (that is, the ID)
$company = $event->getForm()->getData();
// since we've added the listener to the child, we'll have to pass on
// the parent to the callback functions!
$formModifier($event->getForm()->getParent(), $company);
}
);
}
// ...
}