How to use related select boxes in Symfony ?
Let\'s say, I have a select list containing compagnies and another containing employees of the selected company. How do I d
I had the same problem. You must use form events. My code example with country, region, city relations.
namespace Orfos\UserBundle\Form\Type;
///import form events namespace
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\Form\FormEvents;
use Symfony\Component\Form\Event\DataEvent;
class RegistrationFormType extends BaseType
{
private $request;
public function __construct($class, $request, $doctrine)
{
parent::__construct($class);
$this->request = $request;
$this->doctrine = $doctrine;
}
public function buildForm(FormBuilder $builder, array $options)
{
parent::buildForm($builder, $options);
//other fields
$locale = $this->request->getLocale();
$builder->add('country', 'entity', array(
'class' => 'Orfos\CoreBundle\Entity\Country',
'property' => $locale . 'name',
'label' => 'register.country.label',
'query_builder' => function(EntityRepository $er) {
return $er->createQueryBuilder('c')
->select('c', 't')
->join('c.translations', 't');
},
));
$factory = $builder->getFormFactory();
$refreshRegion = function ($form, $country) use ($factory, $locale) {
$form->add($factory->createNamed('entity', 'region', null, array(
'class' => 'Orfos\CoreBundle\Entity\Region',
'property' => $locale . 'name',
'label' => 'register.region.label',
'query_builder' => function (EntityRepository $repository) use ($country) {
$qb = $repository->createQueryBuilder('region')
->select('region', 'translation')
->innerJoin('region.country', 'country')
->join('region.translations', 'translation');
if ($country instanceof Country) {
$qb = $qb->where('region.country = :country')
->setParameter('country', $country);
} elseif (is_numeric($country)) {
$qb = $qb->where('country.id = :country_id')
->setParameter('country_id', $country);
} else {
$qb = $qb->where('country.id = 1');
}
return $qb;
}
)));
};
$factory = $builder->getFormFactory();
$refreshCity = function($form, $region) use ($factory, $locale) {
$form->add($factory->createNamed('entity', 'city', null, array(
'class' => 'Orfos\CoreBundle\Entity\City',
'property' => $locale . 'name',
'label' => 'register.city.label',
'query_builder' => function (EntityRepository $repository) use ($region) {
$qb = $repository->createQueryBuilder('city')
->select('city', 'translation')
->innerJoin('city.region', 'region')
->innerJoin('city.translations', 'translation');
if ($region instanceof Region) {
$qb = $qb->where('city.region = :region')
->setParameter('region', $region);
} elseif (is_numeric($region)) {
$qb = $qb->where('region.id = :region_id')
->setParameter('region_id', $region);
} else {
$qb = $qb->where('region.id = 1');
}
return $qb;
}
)));
};
$builder->addEventListener(FormEvents::PRE_SET_DATA, function (DataEvent $event) use ($refreshRegion, $refreshCity) {
$form = $event->getForm();
$data = $event->getData();
if ($data == null){
$refreshRegion($form, null);
$refreshCity($form, null);
}
if ($data instanceof Country) {
$refreshRegion($form, $data->getCountry()->getRegions());
$refreshCity($form, $data->getRegion()->getCities());
}
});
$builder->addEventListener(FormEvents::PRE_BIND, function (DataEvent $event) use ($refreshRegion, $refreshCity) {
$form = $event->getForm();
$data = $event->getData();
if (array_key_exists('country', $data)) {
$refreshRegion($form, $data['country']);
}
if (array_key_exists('region', $data)) {
$refreshCity($form, $data['region']);
}
});
}
}