【问题标题】:Symfony multiple choice issue with entity type and form eventsSymfony 实体类型和表单事件的多项选择问题
【发布时间】:2018-01-29 15:13:11
【问题描述】:

我有 3 个实体工作正常,但创建 symfony 表单时出现问题

// My FormType

public function buildForm(FormBuilderInterface $builder, array $options)
{
    $translator = $this->translator;

    $builder
        ->add('Country', EntityType::class, array(
            'class'       => 'App\Entity\Countries',
            'placeholder' => '',
        ))
        ->add('City', EntityType::class,array(
            'class' =>'App\Entity\Cities'
        ))
    ;

    $formModifier = function (FormInterface $form, Countries $sport = null) {
        $positions = null === $sport ? array() : $sport->getCities();

        $form->add('City', EntityType::class, array(
            'class' => 'App\Entity\Cities',
            'placeholder' => '',
            'choices' => $positions,
        ));
    };

    $formModifier2 = function (FormInterface $form, Cities $sport = null) {
        $positions = null === $sport ? array() : $sport->getCountryId();

        $form->add('District', EntityType::class, array(
            'class' => 'App\Entity\Districts',
            'placeholder' => '',
            'choices' => $positions,
        ));
    };

    $builder->addEventListener(
        FormEvents::PRE_SET_DATA,
        function (FormEvent $event) use ($formModifier) {
            // this would be your entity, i.e. SportMeetup
            $data = $event->getData();

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

    $builder->addEventListener(
        FormEvents::PRE_SET_DATA,
        function (FormEvent $event) use ($formModifier2) {
            // this would be your entity, i.e. SportMeetup
            $data = $event->getData();

            $formModifier2($event->getForm(), $data->getCity());
        }
    );

    $builder->get('Country')->addEventListener(
        FormEvents::POST_SUBMIT,
        function (FormEvent $event) use ($formModifier) {
            // It's important here to fetch $event->getForm()->getData(), as
            // $event->getData() will get you the client data (that is, the ID)
            $sport = $event->getForm()->getData();

            // since we've added the listener to the child, we'll have to pass on
            // the parent to the callback functions!
            $formModifier($event->getForm()->getParent(), $sport);
        }
    );
    $builder->get('City')->addEventListener(
        FormEvents::POST_SUBMIT,
        function (FormEvent $event) use ($formModifier2) {
            // It's important here to fetch $event->getForm()->getData(), as
            // $event->getData() will get you the client data (that is, the ID)
            $sport = $event->getForm()->getData();

            // since we've added the listener to the child, we'll have to pass on
            // since we've added the listener to the child, we'll have to pass on
            // the parent to the callback functions!
            $formModifier2($event->getForm()->getParent()->getParent(), $sport);
        }
    );
}

// this my controller

       public function userAddress(UserInterface $user,Request $request,HelperService $helper, MailGenerator $mail,TranslatorInterface $translator) 
       {                                                                                                                                            
           $user_address = new UserAddresses();                                                                                                     

           $form = $this->createForm(NewAddressFormType::class,$user_address,array('csrf_protection' => false));                                    
           $form->handleRequest($request);                                                                                                          

           if($form->isSubmitted()) {                                                                                                               
               $data =  $form->getData();                                                                                                           
           }                                                                                                                                        

           return $this->output('checkout/checkout_address',array('form'=>$form->createView()));                                                    
       }    

Form rendering ok i change my first select box and working ajax post but second one first but third one is not working not send ajax data


    {% block script%}

         <script>
           var $sport = $('#new_address_form_Country');
           // When sport gets selected ...
           $sport.change(function() {
              // ... retrieve the corresponding form.
               var $form = $('#new_address_form').closest('form');
               // Simulate form data, but only include the selected sport value.
              var data = {};
              data[$sport.attr('name')] = $sport.val();
              // Submit data via AJAX to the form's action path.
               $.ajax({
                   url : $form.attr('action'),
                   type: $form.attr('method'),
                   data : data,
                   success: function(html) {
                       // Replace current position field ...
                     $('#new_address_form_City').replaceWith(
                        // ... with the returned one from the AJAX response.
                        $(html).find('#new_address_form_City')
                      );
                  }
              });
         });

           var $sport2 = $('#new_address_form_City');
           // When sport gets selected ...
           $sport2.change(function() {
               // ... retrieve the corresponding form.
               var $form = $('#new_address_form').closest('form');
               // Simulate form data, but only include the selected sport value.
               var data = {};
               data[$sport2.attr('name')] = $sport2.val();
               // Submit data via AJAX to the form's action path.
               $.ajax({
                   url : $form.attr('action'),
                   type: $form.attr('method'),
                   data : data,
                   success: function(html) {
                       // Replace current position field ...
                       $('#new_address_form_District').replaceWith(
                           // ... with the returned one from the AJAX response.
                           $(html).find('#new_address_form_District')
                       );
                   }
               });
           });
       </script>
    {% endblock %} 

【问题讨论】:

    标签: ajax forms symfony events


    【解决方案1】:

    你应该使用 $builder->addEventListener。对于多个字段,您需要做的就是在 FormEvents::PRE_SET_DATA 事件处理程序中拥有动态字段。此外,使用父字段数据,如文档中所述获取子字段选择。

    我使用这种方法在分层字段中生成国家、城市和地区实体。让我知道它是否有帮助或您需要更多信息。

    $builder->add(); // all other fields..
    $builder->addEventSubscriber(new DynamicFieldsSubscriber());
    

    按照文档中的定义创建一个eventSubscriber,这里文件名为DynamicFieldsSubscriber

    public static function getSubscribedEvents()
    {
            return array(
                FormEvents::PRE_SET_DATA => 'preSetData', 
                FormEvents::PRE_SUBMIT => 'preSubmitData', 
            );
    }
    /**
     * Handling form fields before form renders.
     * @param FormEvent $event
     */
    public function preSetData(FormEvent $event)
    {
        $translator = $this->translator;
    
        $location = $event->getData();
        // Location is the main entity which is obviously form's (data_class)
        $form = $event->getForm();
    
        $country = "";
        $city = "";
        $district = "";
    
        if ($location) {
            // collect preliminary values for 3 fields.
            $country = $location->getCountry();
            $city = $location->getCity();
            $district = $location->getDistrict();
        }
        // Add country field as its static.
        $form->add('country', EntityType::class, array(
            'class' => 'App\Entity\Countries',
            'label' => $translator->trans('country'),
            'placeholder' => $translator->trans('select'),
            'required' => true,
            'query_builder' => function (EntityRepository $er) {
                return $er->createQueryBuilder('c');
            }
        ));
        // Now add all child fields.
        $this->addCityField($form, $country);
        $this->addDistrictField($form, $city);
    }
    
    /**
     * Handling Form fields before form submits.
     * @param FormEvent $event
     */
    public function preSubmitData(FormEvent $event)
    {
        $form = $event->getForm();
        $data = $event->getData();
    
        // Here $data will be in array format.
    
        // Add property field if parent entity data is available.
        $country = isset($data['country']) ? $data['country'] : null;
        $city = isset($data['city']) ? $data['city'] : null;
        $district = isset($data['district']) ? $data['district'] : null;
    
        // Call methods to add child fields.
        $this->addCityField($form, $country);
        $this->addDistrictField($form, $city);
    }
    
    /**
     * Method to Add City Field. (first dynamic field.)
     * @param FormInterface $form
     * @param type $country
     */
    private function addCityField(FormInterface $form, $country = null)
    {
        $translator = $this->translator;
        $countryCode = (is_object($country)) ? $country->getId() : $country;
        // $countryCode is dynamic here, collected from the event based data flow.
        $form->add('city', EntityType::class, array(
            'class' => 'App\Entity\Cities',
            'label' => $translator->trans('city'),
            'placeholder' => $translator->trans('select'),
            'required' => true,
            'attr' => array(
                'class' => 'col-md-12 validate-required',
                'placeholder' => 'City *'
            ),
            'query_builder' => function (EntityRepository $er) use($countryCode) {
                return $er->createQueryBuilder('p')
                    ->where('p.country_id = :country')
                    ->setParameter('country', $countryCode);
            }
        ));
    }
    
    /**
     * Method to Add District Field, (second dynamic field)
     * @param FormInterface $form
     * @param type $city
     */
    private function addDistrictField(FormInterface $form, $city = null)
    {
        $translator = $this->translator;
        $cityCode = (is_object($city)) ? $city->getId() : $city;
        // $cityCode is dynamic in here collected from event based data flow.
        $form->add('district', EntityType::class, array(
            'class' => 'App\Entity\Districts',
            'label' => $translator->trans('district'),
            'placeholder' => $translator->trans('select'),
            'required' => true,
            'attr' => array('class' => 'district'),
            'query_builder' => function (EntityRepository $er) use($cityCode) {
                return $er->createQueryBuilder('s')
                    ->where('s.city = :city')
                    ->setParameter('city', $cityCode);
            }
        ));
    }
    

    你的项目 JQuery 应该是这样的

     <script>
               var $sport = $('#new_address_form_country');
           // When sport gets selected ...
           $sport.change(function() {
              // ... retrieve the corresponding form.
               var $form = $('#new_address_form').closest('form');
               // Simulate form data, but only include the selected sport value.
              var data = {};
              data[$sport.attr('name')] = $sport.val();
              // Submit data via AJAX to the form's action path.
               $.ajax({
                   url : $form.attr('action'),
                   type: $form.attr('method'),
                   data : data,
                   success: function(html) {
                       // Replace current position field ...
                     $('#new_address_form_city').replaceWith(
                        // ... with the returned one from the AJAX response.
                        $(html).find('#new_address_form_city')
                      );
                  }
              });
         });
    
               $(document).on('change','#new_address_form_city',function () {
                   // ... retrieve the corresponding form.
                   var $form2 = $('#new_address_form').closest('form');
                   // Simulate form data, but only include the selected sport value.
                   var data2 = {};
                   data2[$('#new_address_form_city').attr('name')] = $('#new_address_form_city').val();
                   // Submit data via AJAX to the form's action path.
                   $.ajax({
                       url : $form2.attr('action'),
                       type: $form2.attr('method'),
                       data : data2,
                       success: function(html) {
                           console.log($(html).find('#new_address_form_district'));
                           // Replace current position field ...
                           $('#new_address_form_district').replaceWith(
                               // ... with the returned one from the AJAX response.
                               $(html).find('#new_address_form_district')
                           );
                       }
                   });
               });
    
       </script>
    

    我希望这会有所帮助。

    【讨论】:

      【解决方案2】:

      我相信有时 ajax 调用后的 ajax 调用不起作用,因为它失去了与 jquery 事件侦听器的联系。 为$sport2.change 事件侦听器创建一个函数并将其命名为例如sport2Change。并尝试在具有 id 的元素的 onchange 事件上调用该函数 - new_address_form_City

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2022-01-20
        • 2021-11-08
        • 2014-04-15
        • 2016-06-26
        • 2017-05-07
        • 2016-03-21
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多