I simply struggled with this exact problem and thought that I would give up my own conclusions for those who accidentally stumble over it. I found a solution, but I would probably still recommend just using the ZenStruckFormBundle recommended by Doug, because it seems to be designed to work as a solution for the select2 field type that loads through ajax and binds to the object.
The real reason this doesn't work is because the genemu_jqueryselect2_* types for GenemuFormBundle do not implement a data transformer that will work with the entity when you need the select2 ajax-loading field. It seems he was never intended to work that way. When you use the genemu_jqueryselect2_hidden type and have the "multiple config" parameter set to true, it adds ArrayToStringTransformer This will not work with the entity.
To fix this, you need to create a new type of form field and determine that its parent is genemu_jqueryselect2_hidden , then make a few settings. It will look something like this ...
namespace Acme\DemoBundle\Form\Type; use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\FormBuilderInterface; use Acme\DemoBundle\Form\DataTransformer\EntityCollectionToIdTransformer; use Doctrine\Common\Persistence\ObjectManager; use Symfony\Component\OptionsResolver\OptionsResolverInterface; class EntityCollectionSelectorType extends AbstractType { protected $om; public function __construct(ObjectManager $om) { $this->om = $om; } public function buildForm(FormBuilderInterface $builder, array $options) { $transformer = new EntityCollectionToIdTransformer($this->om, $options['configs']['entity']); $builder->resetViewTransformers(); $builder->addModelTransformer($transformer); } public function setDefaultOptions(OptionsResolverInterface $resolver) { $resolver->setDefaults(array( 'invalid_message' => 'The selected entity does not exist', 'required' => true, 'auto_initialize' => false, 'configs' => array('multiple' => true), 'error_bubbling' => false, )); } public function getParent() { return 'genemu_jqueryselect2_hidden'; } public function getName() { return 'entity_collection_selector'; } }
Then you will also need to add a new data converter, used in the form field type indicated above, so that it can translate the values ββbetween the form fields and the entity ...
namespace Acme\DemoBundle\Form\DataTransformer; use Symfony\Component\Form\DataTransformerInterface; use Symfony\Component\Form\Exception\TransformationFailedException; use Doctrine\ORM\PersistentCollection; use Doctrine\Common\Persistence\ObjectManager; use Doctrine\Common\Collections\ArrayCollection; class EntityCollectionToIdTransformer implements DataTransformerInterface { private $om; private $entityType; public function __construct(ObjectManager $om, $entityType) { $this->om = $om; $this->entityType = $entityType; } public function transform($entities) { if (null == $entities || empty($entities)) { return ''; } $results = ''; foreach ($entities as $entity) { $results .= $entity->getId() . ','; } $results = trim($results, ' ,'); return $results; } public function reverseTransform($values) { if (!$values) { return new ArrayCollection(); } $values = explode(',', $values); $collection = array(); foreach ($values as $id) { $item = $this->om->getRepository($this->entityType)->findOneById($id); if (!is_null($item)) { $collection[] = $item; } else { throw new TransformationFailedException(sprintf( 'An entity with ID "%s" does not exist!', $value )); } } return new PersistentCollection($this->om, $this->entityType, new ArrayCollection($collection)); } }
Now make sure you define your new field type in your configuration for your services ...
<?xml version="1.0" ?> <container xmlns="http://symfony.com/schema/dic/services" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd"> <parameters> ... <parameter key="acme_demo.form.type.entity_collection_selector.class">Acme\DemoBundle\Form\Type\EntityCollectionSelectorType</parameter> ... </parameters> <services> ... <service id="acme_demo.form.type.entity_collection_selector" class="%acme_demo.form.type.entity_collection_selector.class%"> <argument type="service" id="doctrine.orm.default_entity_manager" /> <tag name="form.type" alias="entity_collection_selector" /> </service> ... </services> </container>
Now you can use it as such ...
$builder->add('customers', 'entity_collection_selector', array( 'configs' => array('entity' => 'AcmeDemoBundle:Customer') ));