Symfony具有实体类型和表单事件的多选问题

时间:2018-01-29 15:13:11

标签: ajax forms symfony events

我有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 %} 

2 个答案:

答案 0 :(得分:1)

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

我使用这种方法,用于在分层字段中生成Country,City和District实体。如果有帮助或者您需要更多信息,请告诉我。

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

创建doc中定义的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>

我希望这会有所帮助。

答案 1 :(得分:0)

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

的元素的new_address_form_City事件上调用该函数