扩展EntityType以允许通过AJAX调用设置额外的选择 [英] Extending EntityType to allow extra choices set with AJAX calls

查看:43
本文介绍了扩展EntityType以允许通过AJAX调用设置额外的选择的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我尝试创建一个Symfony自定义类型,扩展为核心"实体"类型.

I try to create a Symfony Custom type extending the core "entity" type.

但是我想将其与 Select2版本4.0.0 一起使用(ajax现在可以与"select" html元素一起使用,而不能像以前一样与隐藏的"input"一起使用).

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

  • 此类型应创建一个空选择,而不是扩展的实体"类型创建实体的完整列表.

这可以通过设置选项来工作(请参见configureOption):

This works by setting the option (see configureOption):

'choices'=>array()

  • 通过编辑附加到表单的对象,它应使用对象的当前数据填充选择.我解决了这个问题,但是仅使用以下buildView方法来查看...
  • Select2识别html"select"的内容,并使用ajax进行工作. 但是,当表单被发回时,Symfony无法识别所选的选项(因为不允许这样做?)

    Select2 recognize the content of the html "select", and does its work with ajax. But when the form is posted back, Symfony doesn't recognize the selected choices, (because there 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
    

    我尝试了使用EventListeners或Subscriber的几种方法,但是找不到有效的配置.

    I tried several methods using EventListeners or Subscribers but I can't find a working configuration.

    使用Select2 3.5.*,我解决了表单事件和覆盖隐藏的表单类型的问题,但是在这里扩展实体类型要困难得多.

    With Select2 3.5.* I solved the problem with form events and overriding the hidden formtype, but here extending the entitytype is much more difficult.

    如何构建我的类型以使其管理实体的反向转换?

    How can I build my type to let it manage the reverse transformation of my entites ?

    自定义类型:

    <?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';
        }
    }
    

    父母表格

    <?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';
        }
    }
    

    推荐答案

    问题已解决.

    解决方案是在PRE_SET_DATA和PRE_SUBMIT FormEvents中使用'choices'=> $ selectedChoices重新创建表单字段.

    The solution is to recreate the form field with 'choices'=>$selectedChoices in both PRE_SET_DATA and PRE_SUBMIT FormEvents.

    可以使用$ event-> getData()从事件中检索选择的选项

    Selected choices can be retrived from the event with $event->getData()

    看看我创建的包,它实现了此方法:

    Have a look on the bundle I created, it implements this method :

    Alsatian/FormBundle-ExtensibleSubscriber

    这篇关于扩展EntityType以允许通过AJAX调用设置额外的选择的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆