Symfony 2 GenemuFormBundle how to create jQuery Select2 with Ajax

I am trying to add Select2 input using a GenemuFormBundle as described in "Use jQuery Select2 with Ajax". Adding a jQuery Select2 field to a field jQuery Select2 field documentation works fine.

But the documentation on how to implement Select2 Ajax loading is very unconvincing. If I pull out the document correctly, it should create the same thing that is indicated in the Select2 documentation. This is exactly what I would like to create. I added a hidden field as well as the required JavaScript, but the only thing I get is Variable "id" does not exist in xBundle:x:new.html.twig at line x .

Shaper of forms (taken directly from the mentioned document):

 ... ->add('field_name', 'genemu_jqueryselect2_hidden', array( 'configs' => array( 'multiple' => true // Wether or not multiple values are allowed (default to false) ) )) ->add('field_name', 'genemu_jqueryselect2_entity', array( 'class' => 'xBundle:Entity', 'property' => 'foo', )) 

View (also taken directly from the document):

 {% block stylesheets %} {{ form_stylesheet(form) }} {% endblock %} {% block javascript %} {{ form_javascript(form) }} {% endblock %} {% block genemu_jqueryselect2_javascript %} <script type="text/javascript"> $field = $('#{{ id }}'); var $configs = {{ configs|json_encode|raw }}; // custom configs $configs = $.extend($configs, { query: function (query) { var data = {results: []}, i, j, s; for (i = 1; i < 5; i++) { s = ""; for (j = 0; j < i; j++) {s = s + query.term;} data.results.push({id: query.term + i, text: s}); } query.callback(data); } }); // end of custom configs $field.select2($configs); </script> {% endblock %} 
+7
forms symfony
source share
1 answer

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 { /** * @var ObjectManager */ protected $om; /** * @param ObjectManager $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 { /** * @var ObjectManager */ private $om; /** * @var string The Doctrine entity type to use */ private $entityType; /** * @param ObjectManager $om */ public function __construct(ObjectManager $om, $entityType) { $this->om = $om; $this->entityType = $entityType; } /** * Transforms a collection of entities to a comma separated string * * @param ArrayCollection $entities * @return string */ public function transform($entities) { if (null == $entities || empty($entities)) { return ''; } $results = ''; foreach ($entities as $entity) { $results .= $entity->getId() . ','; } $results = trim($results, ' ,'); return $results; } /** * Transforms a string of comma separated IDs to a PersistentCollection for Doctrine * * @param string $values * @return PersistentCollection|ArrayCollection * @throws TransformationFailedException if entity is not found. */ 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') )); 
+4
source share

All Articles