EntityType extension to provide advanced settings with AJAX calls

I am trying to create a Symfony Custom type that extends the main entity type.

But I want to use it with Select2 version 4.0.0 (now ajax works with the "select" html element, and not with the hidden "input", as before).

  • This type should create an empty selection instead of a complete list of objects with the extended "entity" type.

This works by setting a parameter (see configureOption):

'choices'=>array() 
  • When editing an object attached to a form, it must fill the selection with the current data of the object. I solved this problem, but only for presentation with the following buildView method ...

Select2 recognizes the contents of the html "select" and does its work with ajax. But when the form is submitted back, Symfony does not recognize the selected options (because they were not allowed?)

 Symfony\Component\Form\Exception\TransformationFailedException Unable to reverse value for property path "user": The choice "28" does not exist or is not unique 

I tried several methods using EventListeners or subscribers, but I can not find a working configuration.

With Select2 3.5. * I solved the problem with form events and overriding the hidden form type, but here the entitytype extension is much more complicated.

How can I create my type so that it can control the inverse transformation of my entites?

Custom type:

 <?php namespace AppBundle\Form\Type; use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\Form\FormView; use Symfony\Component\Form\FormInterface; use Symfony\Component\OptionsResolver\OptionsResolver; use Symfony\Component\Form\ChoiceList\View\ChoiceView; class AjaxEntityType extends AbstractType { protected $router; public function __construct($router) { $this->router = $router; } /** * {@inheritdoc} */ public function buildForm(FormBuilderInterface $builder, array $options) { $builder->setAttribute('attr',array_merge($options['attr'],array('class'=>'select2','data-ajax--url'=>$this->router->generate($options['route'])))); } /** * {@inheritdoc} */ public function buildView(FormView $view, FormInterface $form, array $options) { $view->vars['attr'] = $form->getConfig()->getAttribute('attr'); $choices = array(); $data=$form->getData(); if($data instanceOf \Doctrine\ORM\PersistentCollection){$data = $data->toArray();} $values=''; if($data != null){ if(is_array($data)){ foreach($data as $entity){ $choices[] = new ChoiceView($entity->getAjaxName(),$entity->getId(),$entity,array('selected'=>true)); } } else{ $choices[] = new ChoiceView($data->getAjaxName(),$data->getId(),$data,array('selected'=>true)); } } $view->vars['choices']=$choices; } /** * {@inheritdoc} */ public function configureOptions(OptionsResolver $resolver) { $resolver->setRequired(array('route')); $resolver->setDefaults(array('choices'=>array(),'choices_as_value'=>true)); } public function getParent() { return 'entity'; } public function getName() { return 'ajax_entity'; } } 

Parent form

 <?php namespace AppBundle\Form; use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\OptionsResolver\OptionsResolver; class AlarmsType extends AbstractType { /** * @param FormBuilderInterface $builder * @param array $options */ public function buildForm(FormBuilderInterface $builder, array $options) { $builder ->add('name','text',array('required'=>false)) ->add('user','ajax_entity',array("class"=>"AppBundle:Users","route"=>"ajax_users")) ->add('submit','submit'); } /** * @param OptionsResolver $resolver */ public function configureOptions(OptionsResolver $resolver) { $resolver->setDefaults(array('data_class' => 'AppBundle\Entity\Alarms','validation_groups'=>array('Default','form_user'))); } /** * @return string */ public function getName() { return 'alarms'; } } 
+4
source share
1 answer

The problem is resolved.

The solution is to recreate the form field using "choice" => $ selectedChoices in both PRE_SET_DATA and PRE_SUBMIT FormEvents.

Selected options can be retrieved from the event using $ event-> getData ()

Look at the created bunch, it implements this method:

Alsatian / FormBundle - Extensible Subscriber

+5
source

All Articles