I have a form which contains a collection. So I have:
/* my type */
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
As Bernhard indicated, listeners are the only way to do this because the data is not available in the sub form yet. I used the eventListener to solve a similar requirement. Below is a simplified version of my code that I hope will be helpful:
I have a parent form for my View
entity which has a lot of fields, as well as collection of other forms. One of the sub forms is for an associated entity ViewVersion
, which actually needs to load another form collection for a dynamic entity that is the content type associated with the View
. This content type could by one of many different types of entities, e.g Article, Profile, etc. So I need to find out what contentType is set in the View
data and then find the dynamic path to that bundle, and include that formType.
Once you know how to do it, it's actually easy!
class ViewType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
// Basic Fields Here
// ...
// ->add('foo', 'text')
// ...
// Load a sub form type for an associated entity
->add('version', new ViewVersionType())
;
}
}
class ViewVersionType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
// Basic Fields Here
// ...
// ->add('foo', 'text')
// ...
;
// In order to load the correct associated entity's formType,
// I need to get the form data. But it doesn't exist yet.
// So I need to use an Event Listener
$builder->addEventListener(FormEvents::PRE_SET_DATA, function (FormEvent $event) {
// Get the current form
$form = $event->getForm();
// Get the data for this form (in this case it's the sub form's entity)
// not the main form's entity
$viewVersion = $event->getData();
// Since the variables I need are in the parent entity, I have to fetch that
$view = $viewVersion->getView();
// Add the associated sub formType for the Content Type specified by this view
// create a dynamic path to the formType
$contentPath = $view->namespace_bundle.'\\Form\\Type\\'.$view->getContentType()->getBundle().'Type';
// Add this as a sub form type
$form->add('content', new $contentPath, array(
'label' => false
));
});
}
}
That's it. I'm new to Symfony, so the idea of doing everything in an EventListener is foreign to me (and seems unnecessarily complex). But I hope once I understand the framework better, it will seem more intuitive. As this example indicates, it's not that complicated to do it with an Event Listener, you just wrap your code in that closure (or put it in it's own separate function as described in the docs).
I hope that helps someone!