如何构建Symfony来检查`onChange`下拉字段?

时间:2015-11-25 12:52:40

标签: forms symfony doctrine-orm entity

在我的示例中,我有四个实体要用于博客平台:所有者 发布 用户 位置< / KBD>

  • 所有者可以有多个帖子
  • 帖子可以有多个用户地点

我正在尝试创建一个管理表单,我可以从下拉菜单中选择所有者,这将刷新表单onChange以填充帖子的下拉菜单< / KBD>。

当选择 Post 时,表格将再次刷新,并附上与该帖子相关联的表单字段 Users Locations 。然后我可以:

  1. 使用更多信息更新现有实体(例如,用户的出生日期或位置的GPS坐标)
  2. 创建要附加到帖子的实体的新实例
  3. 我没有包含 Location 实体,并且没有包含命名空间/ include语句,因为它们会影响我在控制器/ Formtypes中如何编写此类管理页面的主要问题(我的尝试如下):

    控制器:

    /**
    * @Route("/adminposts", name="admin_posts")
    */
    public function updatePostsAction(Request $request)
    {
      $user = new User();
      $form = $this->createForm(new UserType(), $user);
      $form->handleRequest($request);
    
      if ($form->isSubmitted() && $form->isValid()) {
            $em = $this->getDoctrine()->getManager();
            $em->persist($owner);
            $em->persist($post);
            $em->persist($user);
            $em->persist($location);
            $em->flush();
            return $this->redirectToRoute('homepage');
      }
      return $this->render('AppBundle:Default:adminupdate.post.html.twig', array(
            'form' => $form->createView(),
      ));
    }
    

    用户表单类型:

    class UserType extends AbstractType
    {
      public function buildForm(FormBuilderInterface $builder, array $options)
      {
            $builder
                 ->add('owner','entity',array(
                      'class'=>'AppBundle:Owner',
                      'choice_label'=>'username',
                      'query_builder'=>function(EntityRepository $er) {
                            return $er->createQueryBuilder('d')
                                 ->orderBy('d.username','ASC');
                      }))
    
                 ->add('post','entity',array(
                      'class'=>'AppBundle:Post',
                      'choice_label'=>'posttext',
                      'query_builder'=>function(EntityRepository $er) {
                            return $er->createQueryBuilder('d')
                                 ->orderBy('d.postdate','ASC');
                      }))
    
                 ->add('Firstname')
                 ->add('Surname')
                 ->add('DOB')
                 ->getForm();
      }
    
      public function configureOptions(OptionsResolver $resolver)
      {
            $resolver->setDefaults(array(
                 'data_class' => 'AppBundle\Entity\Users',
            ));
      }
    
      public function getName()
      {
            return 'user';
      }
    }
    

1 个答案:

答案 0 :(得分:0)

好的,也许您可​​以在这里查看:Symfony2: Change choices with ajax and validation或按照我的方法:

在您的UserType中:

pytest.yield_fixture

我假设您知道如何在jQuery(我用它来使用它)和ajax调用中创建onChange事件。

仅提醒,在您看来:

class UserType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('owner','entity',array(
                'class'=>'AppBundle:Owner',
                'choice_label'=>'username',
                'query_builder'=>function(EntityRepository $er) {
                    return $er->createQueryBuilder('o')
                        ->orderBy('o.username','ASC');
                }))

            ->add('Firstname')
            ->add('Surname')
            ->add('DOB');

        // Add listeners for Post field
        $builder->addEventListener(FormEvents::PRE_SET_DATA, array($this, 'onPreSetData'));
        $builder->addEventListener(FormEvents::PRE_SUBMIT, array($this, 'onPreSubmit'));
    }


    protected function addElements(FormInterface $form, $owner = null)
    {
        if($owner){
            $form->add('post','entity',array(
                'class'=>'AppBundle:Post',
                'choice_label'=>'posttext',
                'query_builder'=>function(EntityRepository $er, $owner) {
                    return $er->createQueryBuilder('p')
                        ->join('p.owner', 'o')
                        ->where('o.id = :ownerID')
                        ->setParameter('ownerID', $owner->getID() )
                        ->orderBy('d.postdate','ASC');
                }));
        }
        else{
            $form->add('post','choice',array(
                'choice_label'=>'posttext',
                'empty_value' => '-- Choose --',
                'choices' => array())
            );
        }
    }

    public function onPreSubmit(FormEvent $event)
    {
        $form = $event->getForm();
        $data = $event->getData();

        $this->addElements($form, $data->getOwner());
    }

    public function onPreSetData(FormEvent $event)
    {
        /** @var User user */
        $user = $event->getData();
        $form = $event->getForm();

        $this->addElements($form, $user->getOwner());
    }

    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => 'AppBundle\Entity\Users',
        ));
    }

    public function getName()
    {
        return 'user';
    }
}

你的Ajax脚本:

 {{ form_row(
        form.owner,
        {
            'attr': {               
                'data-owner-id': ""~form.owner.vars.id,
                'class': "change-posts-per-owner",
            }
        }
    ) }}
    {{ form_row(form.post) }}
    {{ form_row(form.firstname) }}
    {{ form_row(form.surname) }}
    {{ form_row(form.DOB) }}

您还可以使用 $(document).on('change', 'select .change-posts-per-owner', function(){ var ownerID = $(this).data("owner-id"); $.ajax({ url: your_url, type: "GET", //or POST data: 'ownerID='+ownerID, dataType: 'JSON', //or html or whatever you want success:function(data) { //Replace <option element in your select element for post list considering your dataType (type of response) } }); } $.post()代替显式方法$.get() 我建议您使用FOSJSRoutingBundle以$.ajax();方法指示您的网址。