Symfony 4表单-Ajax选择人群

时间:2019-03-25 13:55:44

标签: php ajax forms symfony

是否有一种方法可以使用ajax异步填充Form ChoiceType(下拉列表)?

基本上是我要做什么:

简短说明:简单的预订系统。

详细说明:

当用户通过在“ preferredDate”中使用日期选择器(或其他方法)选择日期时, ajax调用将检查所选日期是否有可用的时隙,并用时间(例如:10:00、10:30、11:00、11:30等)填充“ availableTimes” ChoiceType(下拉列表)。

可用时间不在数据库中。

我的表单:

 public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('preferredDate', DateType::class, [
                'widget' => 'single_text',
                'input' => 'datetime',
                'format' => 'dd.MM.yyyy',
            ])
            ->add('availableTimes', ChoiceType::class, ['required' => false]);
    }

我的JS:

$(".reservation-date").change(function () {
        $.ajax({
            type: "GET",
            dataType: "json",
            url: "{{URL}}",
            data: {},
            success: function (data) {
                $(".reservation-times").empty();
                $.each(data, function (key, value) {
                    //populate availabletimes dropdown
                    let disabled = (value.disabled === true ? "disabled" : '');
                    $(".reservation-times").append('<option ' + disabled + ' value=' + value.time + '>' + value.time + '</option>');
                })
            }
            ,
            error: function (error) {
                console.log(error);
            }
        });
    })

当我发送选定的时间时,它会正常工作抛出错误“此值无效”

我做错了什么?

您会如何做?

编辑:没有验证集,但由于某些原因,它仍然想验证ChoiceType ... EDIT2:读取所有旧的SF2答案,但所有这些都是使用事件发送2次以上的表单。

EDIT3:_profiler中的错误:

enter image description here

enter image description here

2 个答案:

答案 0 :(得分:0)

我终于做到了。添加了EventListener,其他所有内容基本相同。

我的表单:

public function buildForm(FormBuilderInterface $builder, array $options)
    {

        $builder
            ->add('preferredDate', DateType::class, [
                'widget' => 'single_text',
                'input' => 'datetime',
                'format' => 'dd.MM.yyyy',
            ])
            ->add('availableTimes', ChoiceType::class)
            ->addEventListener(FormEvents::PRE_SUBMIT, function (FormEvent $event) {

                // get the form from the event
                $form = $event->getForm();
                $formOptions = $form->getConfig()->getOptions();

                //helpers
                $availableTimeHandler = $formOptions['availableTimeHelper'];

                // get the form data, that got submitted by the user with this request / event
                $data = $event->getData();

                //get date
                $preferredDate = $data['preferredDate'];

                // get the availableTimes element and its options
                $fieldConfig = $form->get('availableTimes')->getConfig();
                $fieldOptions = $fieldConfig->getOptions();


                /**
                 * Getting available times logic is here, 
                 * not showing because it's irrelevant to the issue.
                 *
                 * $times array example: 
                 * [
                 *      ['time' => '10:00', 'disabled' => false],
                 *      ['time' => '11:00', 'disabled' => true],
                 *      ['time' => '12:00', 'disabled' => true],
                 * ]
                 */

                $choices = [];
                foreach ($times as $time) {
                    $choices[] = [$time['time'] => $time['time']];
                }

                //update choices
                $form->add('availableTimes', ChoiceType::class,
                    array_replace(
                        $fieldOptions, [
                            'choices' => $choices
                        ]
                    )
                );
            });


    }

我的JS:

$(".reservation-date").change(function () {
        $.ajax({
            type: "GET",
            dataType: "json",
            url: "{{URL}}",
            data: {},
            success: function (data) {
                $(".reservation-times").empty();
                $.each(data, function (key, value) {
                    //populate availabletimes dropdown
                    let disabled = (value.disabled === true ? "disabled" : '');
                    $(".reservation-times").append('<option ' + disabled + ' value=' + value.time + '>' + value.time + '</option>');
                })
            }
            ,
            error: function (error) {
                console.log(error);
            }
        });
    })

建议或技巧将不胜感激。

答案 1 :(得分:0)

在这种情况下,如果还有其他开发人员被卡住,则对我有用的解决方案在这里说明:https://symfony.com/doc/current/form/dynamic_form_modification.html#dynamic-generation-for-submitted-forms

我做了类似的事情,并使用了两个事件PRE_SET_DATA和POST_SUBMIT,我没有使用原则,所以我的代码可能有些奇怪:

//The form
    $builder
        ->add('Pays', ChoiceType::class, [
            'choices' => $this->paysRepository,
            'attr' => ['class' => 'select2'],
            'mapped' => false,//Pays don't exist in Panneau Entity
            'constraints' => [
                new NotBlank([
                    'message' => 'Veuillez choisir un pays'
                ])
            ]
        ])
        ->add('NumVille', ChoiceType::class, [
            'attr' => ['class' => 'select2'],
            'placeholder' => 'Villes',
            'constraints' => [
                new NotBlank([
                    'message' => 'Veuillez choisir une ville'
                ])
            ]
        ]);

现在事件保存程序:

//The function that fill the dropdown
        $formModifier = function (FormInterface $form,String $pays) {
            //$choices = null === $ville ? [] : $ville->getAvailablePositions();

            if( !empty($pays) ){
                $choices = $this->villeRepository->findCities($pays);//findcities is a function that bring data , cuz i'm not using doctrine
            }else{
                $choices = [];
            }

            $form->add('NumVille', ChoiceType::class, [
                'choices' => $choices,
            ]);
        };

        //PRE SET DATA EVENT
        $builder->get('Pays')->addEventListener(
            FormEvents::PRE_SET_DATA,
            function (FormEvent $event) use ($formModifier) {

                //Get Form DATA
                $data = $event->getData();

                if ($data) {
                    $formModifier($event->getForm(), $data); 
                }

            }
        );

        //POST SUBMIT EVENT
        $builder->get('Pays')->addEventListener(
            FormEvents::POST_SUBMIT,
            function (FormEvent $event) use ($formModifier) {

                $data = $event->getForm()->getData();

                $formModifier($event->getForm()->getParent(), $data); 

            }
        );

NumVille下拉列表由前面的ajax填充。