完成Symfony2动态表单修改

时间:2013-11-29 05:08:50

标签: jquery forms symfony doctrine-orm

经过多天试图找出Symfony到Cookbook的条目...... http://symfony.com/doc/current/cookbook/form/dynamic_form_modification.html

我终于得到了第三个例子来处理我的ProductType.php文件中的以下代码(见下文)。

当我添加游戏时,当我点击提交按钮时会出现相应的服务器和类别列表。如果我通过在其中一个字段中输入无效输入来强制显示错误,则仅显示新字段。

我有两个问题。如果$ formModifier变量中没有的所有数据都有效,则它会提交数据,但我没有看到“服务器”和“类别”选项。即使在选择游戏之前我不需要显示“服务器”和“类别”,我如何确保“服务器”和“类别”。

第二个问题是在食谱中输入它说“可能仍然缺少的一件事是在选择运动后你的表格的客户端更新。这应该通过向你的应用程序发回AJAX来处理。在该控制器中,您可以提交表单,但只需使用提交的表单呈现更新的字段,而不是处理它。“

由于我的事件修饰符处于“提交”状态,我如何提交具有所选游戏(id)的控制器条目,并仅渲染仅在选择游戏后才需要的字段?

先谢谢。

斯科特

<?php

namespace Acme\MainBundle\Form;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
use Symfony\Component\Form\FormEvent;
use Symfony\Component\Form\FormEvents;
use Doctrine\ORM\EntityRepository;
use Symfony\Component\Form\FormInterface;
use Acme\MainBundle\Entity\Game;

class ProductsType extends AbstractType {

    /**
     * @param FormBuilderInterface $builder
     * @param array $options
     */
    public function buildForm(FormBuilderInterface $builder, array $options) {
        $builder
                ->add('name')
                ->add('price')
                ->add('description')
                ->add('game')

        ;

        // ** Build Form Interface Based On Selected Game **//

        $formModifier = function(FormInterface $form, Game $game, $game_id) {

                    // ** Add Servers Based On Game Id ** // 
                    $form->add('server', 'entity', array(
                        'class' => 'Acme\MainBundle\Entity\GameServers',
                        'query_builder' => function(EntityRepository $er) use ($game_id) {
                            $query = $er->createQueryBuilder('i')
                                    ->select(array('i'))
                                    ->where('i.game_id = :game_id')
                                    ->setParameter('game_id', $game_id)
                                    ->orderBy('i.name', 'ASC');
                            return $query;
                        },
                            )
                    );
                    // ** Build Category List Based on Game Id Submitted ** //
                    // Refactor this so that is nothing is selected that it Doesn't Build Category List **/        
                    $form->add('category', 'entity', array(
                        'class' => 'Acme\MainBundle\Entity\GameCategories',
                        'query_builder' => function(EntityRepository $er) use ($game_id) {
                            $query = $er->createQueryBuilder('i')
                                    ->select(array('i'))
                                    ->where('i.game_id = :game_id')
                                    ->setParameter('game_id', $game_id)
                                    ->orderBy('i.name', 'ASC');

                            return $query;
                        },
                            )
                    );
                };

        //** Checks for Games That Are Submitted and Adds Servers and Categories Based on Game Selection **//
        $builder->get('game')->addEventListener(
                FormEvents::POST_SUBMIT, function(FormEvent $event) use ($formModifier) {
                    // Get Form Data to Pass Back to Modifier
                    $game = $event->getForm()->getData();
                    // Get Game Id to pass back to Form Modifier
                    $game_id = $event->getForm()->getData()->getId();
                    $formModifier($event->getForm()->getParent(), $game, $game_id);
                }
        );
    }

    /**
     * @param OptionsResolverInterface $resolver
     */
    public function setDefaultOptions(OptionsResolverInterface $resolver) {
        $resolver->setDefaults(array(
            'data_class' => 'Acme\MainBundle\Entity\Products'
        ));
    }

    /**
     * @return string
     */
    public function getName() {
        return 'acme_mainbundle_products';
    }

}

2 个答案:

答案 0 :(得分:1)

我找到了这个SO条目How to handle Ajax forms with collections in Symfony2.3

的ajax部分的答案

这是我的实现

的javascript

$(document).ready(function () {
    $('#acme_mainbundle_products_game').change(function(){
       if($(this).val()){
           $.ajax({
        type: "POST",
        url: "{{ url('productsCreateSubmit') }}",
        data: $(this).serialize(),
        success: function(data) {
            $('#dynamic_fields').html(data);
        }
    });

    return false; 
        }
    });
});

/new.html.twig中的twig

{%extends':: base.html.twig'%}

{%block body - %}

    <h1>Products creation</h1>
    {{ form_start(form) }}
    <hr />
        {{ form_label(form.name) }}
        {{ form_errors(form.name) }}
        {{ form_widget(form.name) }}
    <hr />
        {{ form_label(form.price) }}
        {{ form_errors(form.price) }}
        {{ form_widget(form.price) }}
    <hr />
        {{ form_label(form.description) }}
        {{ form_errors(form.description) }}
        {{ form_widget(form.description) }}
    <hr />
        {{ form_label(form.game) }}
        {{ form_errors(form.game) }}
        {{ form_widget(form.game) }}
    <hr />
    <div id="dynamic_fields">Stuff Will Go Here</div>
{{ form_end(form) }}

serverslist.twig.html

<hr />
 {{ form_label(form.server) }}
 {{ form_errors(form.server) }}
 {{ form_widget(form.server) }}
<hr />
<hr />
 {{ form_label(form.category) }}
 {{ form_errors(form.category) }}
 {{ form_widget(form.category) }}
<hr />

最后是控制器条目

/**
 * @Route("/products/create/submit", name="productsCreateSubmit")
 */
public function productsCreateSubmitAction(Request $request) {
    $products = new Products();

    $form = $this->createForm(new ProductsType(), $products);
    $form->handleRequest($request);

    return $this->render('AcmeMainBundle:Products:serverslist.html.twig', array(
                'form' => $form->createView(),
    ));
}

我仍然需要完成验证,但这就是我如何使用ajax来渲染必需的字段。它似乎是正确的,它的工作原理,但如果有人有任何反馈,如何做得更好,我很乐意听到反馈。

答案 1 :(得分:0)

我认为获得$ game对象时会出现问题:

 //** Checks for Games That Are Submitted and Adds Servers and Categories Based on Game Selection **//
    $builder->get('game')->addEventListener(
            FormEvents::POST_SUBMIT, function(FormEvent $event) use ($formModifier) {
                // Get Form Data to Pass Back to Modifier
                $game = $event->getForm()->getData()->getGame();
                // Get Game Id to pass back to Form Modifier
                $game_id = $game->getId();
                $formModifier($event->getForm()->getParent(), $game, $game_id);
            }
    );

并且您不使用$ game对象,在$ formModifier中仅使用$ game_id。所以你可以改变你的功能:

 $formModifier = function(FormInterface $form, $game_id) {
    //Adding other widgets here
 }