在另一个select's "change"上填充select字段事件,并使其可以提交


populate select field on another select's "change" event in symfony2 and make it OK for submission

使用Symfony2.3.4和PHP5.6.3

朋友们,我一直在寻找这个问题一段时间了,是的,我发现了一些类似的问题,甚至在烹饪书中找到了这个。

现在你会说,"这家伙相当慢",对了,我是。请帮助我,因为我似乎不能得到这个或任何其他例子,我遇到了帮助我自己的问题。

我需要的是当用户从另一个选择字段中选择项目时填充一个选择字段。所有这些都以标准的crudgenerated - symfony2形式发生。这两个选择分别代表一个实体集合(Zone和UEB),作为独立的Zone。

社区:别说话了,把代码给我!

我:好的,这是我目前为止的记录:

//ReferenceController.php
public function newAction() {
    $entity = new Reference();
    $form = $this->createCreateForm($entity);
    return $this->render('CCBundle:Reference:new.html.twig', array(
                'entity' => $entity,
                'form' => $form->createView(),
    ));
}
public function createAction(Request $request) {
    $entity = new Reference();
    $form = $this->createCreateForm($entity);
    $form->bind($request);
    /*
    var_dump($form->get('UEB')->getData());
    var_dump($form->get('UEB')->getNormData());
    var_dump($form->get('UEB')->getViewData());
    die();
    */
    if ($form->isValid()) {
        $em = $this->getDoctrine()->getManager();
        $em->persist($entity);
        $em->flush();
        return $this->redirect($this->generateUrl('reference_show', array('id' => $entity->getId())));
    }
    return $this->render('CCBundle:Reference:new.html.twig', array(
                'entity' => $entity,
                'form' => $form->createView(),
    ));
}

private function createCreateForm(Reference $entity) {
    $form = $this->createForm(new ReferenceType(), $entity, array(
        'action' => $this->generateUrl('reference_create'),
        'method' => 'POST',
    ));
    return $form;
}

//ReferenceType.php
public function buildForm(FormBuilderInterface $builder, array $options) {
    $builder
            ->add('suffix')
            ->add('zone', null, array(
                'required' => true,
            ))
    ;
    //What follows is for populating UEB field accordingly, 
    //whether it's a "createForm" or an "editForm"
    if ($options['data']->getId() !== null) {
        $formModifier = function (FormInterface $form, Zone $zone = null) {
            $UEBs = null === $zone ? array() : $zone->getUEBs();
            $form->add('UEB', 'entity', array(
                'required' => true,
                'label' => 'UEB',
                'class' => 'CCBundle:UEB',
                //                'empty_value' => '',
                'choices' => $UEBs,
            ));
        };
        $builder->addEventListener(
                FormEvents::PRE_SET_DATA, function (FormEvent $event) use ($formModifier) {
            $data = $event->getData();
            $formModifier($event->getForm(), $data->getZone());
        });
    } else {
        $formModifier = function (FormInterface $form) {
            $form->add('UEB', 'entity', array(
                'required' => true,
                'label' => 'UEB',
                'class' => 'CCBundle:UEB',
                'query_builder' =>
                function(EntityRepository $er) {
            return $er->createQueryBuilder('u')
                            ->where('u.zone = :zone')
                            ->setParameter('zone', $er->findFirstZone());
        }
                    )
            );
        };
        $builder->addEventListener(
                FormEvents::PRE_SET_DATA, function (FormEvent $event) use ($formModifier) {
            $formModifier($event->getForm());
        });
    }

//base.js
    var goalURL = "" + window.location;
        if (goalURL.slice(-13) === 'reference/new' || goalURL.match(/reference'/'d+'/edit$/))
    {
        //case new reference
        goalURL = goalURL.replace('reference/new', 'reference/update_uebs/');
        //case edit reference
        goalURL = goalURL.replace(/reference'/'d+'/edit/, 'reference/update_uebs/');
        //this is the function run every time the "new" or "edit" view is loaded
        //and every time the Zone select field is changed
        var runUpdateUEBs = function() {
            $.getJSON(goalURL, {id: $('#cc_ccbundle_reference_zone').val()}, function(response) {
            $('#cc_ccbundle_reference_UEB').children('option').remove();
            var non_selected_options = [];
            var index = 0;
            $.each(response, function(key, val) {
                var option = $('<option selected="selected"></option>');
                option.text(val);
                option.val(key);
                option.prop('selected', 'selected');
                option.appendTo($('#cc_ccbundle_reference_UEB'));
                non_selected_options[index++] = $(option);
            });
            var amount = non_selected_options.length;
            if (amount > 1)
                $.each(non_selected_options, function(key, val) {
                     if (amount - 1 === key)
                     val.attr('selected', false);
                });
            });
    };
    runUpdateUEBs();
    $('#cc_ccbundle_reference_zone').bind({
        change: runUpdateUEBs
    });
}

//ReferenceController.php
//this is where "goalURL" goes
function updateUEBsAction() {
    $id = $this->getRequest()->get('id');
    $em = $this->getDoctrine()->getManager();
    $uebs = $em->getRepository('CCBundle:UEB')->findBy(array('zone' => $id));
    $ids_and_names = array();
    foreach ($uebs as $u) {
        $ids_and_names[$u->getId()] = $u->getName();
    }
    return new 'Symfony'Component'HttpFoundation'Response(json_encode($ids_and_names));
}

有了这个,我可以加载对应于当前显示的区域的UEBs,每次选择一个新的区域,但只是在视觉上,而不是内部,因此:select填充得很好,但当我提交表单时它没有完成它并在UEB字段和

上输出"This value is not valid"
var_dump($form->get('UEB')->getData());
var_dump($form->get('UEB')->getNormData());
var_dump($form->get('UEB')->getViewData());
die();

从以上输出

null
null
string <the_value_of_the_option_tag> (length=1)

我需要知道如何填充的选择和内部数据提交。

谢谢你听我这么简单的解释。

我在听(读)。

这是我正在寻找的答案,它看起来很像在烹饪书中的一个,但不知何故我理解这一个更好,我能够将它应用到我自己的问题,它只需要在ajax调用和相应的动作的一些调整,但只关于我自己的问题。

感谢所有关心阅读我的问题的人,特别感谢Joshua Thijssen的帖子。