Today i would like to share my recent experience on forms and data dependent fields. Playing with Symfony2 forms some time ago i was looking for best solutions of adding fields to forms that depend on the data / Doctrine object – there was nothing about it in the official Symfony documentation. I thought, as many other developers that the best / easiest way is to pass the current object in form constuctor. Today i know it was wrong but what is the recommended solution? Is there any easy way to add / remove form fields?
Imagine a scenario:
Implementing form in the old way i will write code:
<?php
namespace My\AdminBundle\Form;
use My\AdminBundle\Entity\User;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
class UserType extends AbstractType
{
protected $user = null;
public function __construct(User $user)
{
$this->user = $user;
}
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('firstName', 'text', array('label' => 'First name'))
->add('lastName', 'text', array('label' => 'Last name'))
->add('email', 'email', array('label' => 'Email address'))
;
// add permissions for none admin users
if (!$this->user->isAdmin()) {
$builder
->add('permissions', 'entity', array(
'label' => 'Access Permisson',
'class' => 'AdminBundle:Permission',
'multiple' => true,
'expanded' => true
))
}
}
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'My\AdminBundle\Entity\User'
));
}
public function getName()
{
return 'my_adminbundle_usertype';
}
}
But according to Bernhard Schussek the recommended way of playing with dependent fields in Symfony forms is to add / remove fields using EventListeneres on form events. Using FormEvent we can access our data object ($event->getData()), current form ($event->getForm()) and determine which fields add or remove accoridng to User object.
Yes, it may seem a bit complicated but i will try to show it in UserType example:
<?php
namespace My\AdminBundle\Form;
use My\AdminBundle\Entity\User;
use Symfony\Component\Form\FormEvent;
use Symfony\Component\Form\FormEvents;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
class UserType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('firstName', 'text', array('label' => 'First name'))
->add('lastName', 'text', array('label' => 'Last name'))
->add('email', 'email', array('label' => 'Email address'))
;
$formFactory = $builder->getFormFactory();
// add permissions for none admin users
$builder->addEventListener(FormEvents::PRE_SET_DATA,
function (FormEvent $event) use ($formFactory) {
if (!$event->getData()->isAdmin()) {
$event->getForm()->add($formFactory->createNamed(
'permissions', 'entity', null, array(
'label' => 'Access Permisson',
'class' => 'AdminBundle:Permission"',
'multiple' => true,
'expanded' => true
)));
}
}
);
}
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'My\AdminBundle\Entity\User'
));
}
public function getName()
{
return 'my_adminbundle_usertype';
}
}
Maybe it’s better, maybe it’s recommended way of adding dependent fields but in my opinion it also quite complicated. What about forms where we have many dependent fields? It’s a lot of code just for one filed. It really needs simplification. list of online casinos