Multiple Symfony2 Forms in One Template

My application consists of zones that can have many devices.

When viewing a zone, you must display a control for each device in the zone.

Each device is completely independent, so enclosing device forms in the form of a zone seems unnecessary - I only want to deal with changes on one device at a time.

Currently, I create a form for each device and pass them to the zone view template:

public function viewAction($zone_id) { $zone = $this->getZoneById($zone_id); $forms = array(); foreach ($zone->getDevices() as $device) { $forms[] = $this->createForm(new DeviceType(), $device)->createView(); } return $this->render('AcmeBundle:Zones:view.html.twig', array('zone' => $zone, 'deviceForms' => $forms)); } 

And then in the view template, I iterate over the forms:

 {% for form in deviceForms %} {% include 'AcmeBundle:Devices:control.html.twig' with {'zone':zone, 'form':form} %} {% endfor %} 

It seems that everything is working fine, but I really need to change the template, which is created based on the "type" of the device. What is the cleanest way to do this? I can do something like:

 {% if form.vars.data.type == 'foo' %} {% include 'AcmeBundle:Devices:control-foo.html.twig' with {'zone':zone, 'form':form} %} {% elseif form.vars.data.type == 'bar' %} {% include 'AcmeBundle:Devices:control-bar.html.twig' with {'zone':zone, 'form':form} %} {% endif %} 

but does it look like there is too much logic in the template? It would be better to assign a template to display the form object in some way, but I don't know if this is possible?

+4
source share
1 answer

You must add a template parameter or something else to FormType through the controller. In FormType you must declare a default template parameter and pass it the form view.

 public function viewAction($zone_id) { $zone = $this->getZoneById($zone_id); $forms = array(); //You define a config for each type of device (you should use parameters) $templates = array( 'foo' => 'AcmeBundle:Devices:control-foo.html.twig', 'bar' => 'AcmeBundle:Devices:control-bar.html.twig', ); foreach ($zone->getDevices() as $device) { //define your template here. $type = $device->getType(); //add a template option in the form. $options['template'] == $templates[$type]; $forms[] = $this->createForm(new DeviceType(), $device, $options)->createView(); } return $this->render('AcmeBundle:Zones:view.html.twig', array('zone' => $zone, 'deviceForms' => $forms)); } 

Now in DeviceType you have to set the default parameters in the form, they will be combined with the parameters that we create in the controller.

 public function getDefaultOptions(array $options) { return array( //...other options... //this is the default template of this form 'template' => 'AcmeBundle:Devices:control.html.twig' ); } 

Then set the attribute on the form in Builder

 public function buildForm(FormBuilder $builder, array $options) { $builder->setAttribute('template', $options['template']); //...your fields here... } 

Finally, set the var template in the view.

 public function buildView(FormView $view, FormInterface $form) { $view->set('template', $form->getAttribute('template')); } 

Now you can read the "template" option in the branch and enable the corresponding template

 {% for form in deviceForms %} {% include form.get('template') with {'zone':zone, 'form':form} %} {% endfor %} 

Remember to add lines at the beginning of FormType

 use Symfony\Component\Form\FormInterface; use Symfony\Component\Form\FormView; use Symfony\Component\Form\FormBuilder; 
+3
source

All Articles