Symfony2 Sonata admin dynamically change input data based on selected value

前端 未结 3 2091
借酒劲吻你
借酒劲吻你 2021-01-03 17:11

For one of my objects I need to create some dynamic form rendering... But I cant figure out how to do this in Sonata Admin. For example when I create an object I have a fiel

3条回答
  •  醉话见心
    2021-01-03 17:54

    After researching forever to find a way to use dynamic dropdowns using ajax and sonata with symfony4 i would like to share my solution how it actually works for me.

    In my case i have a district and this district has different cities. I have a company that first chooses a district and then depending of that it´s city.

    What i did:

    1. Create your entity for the districts

    2. Create your entity for the cities

    3. Go in your main class (in my case this is the company entity and add two entities for the districts and cities

        /**
         * @ORM\ManyToOne(targetEntity="App\Wdm\MainBundle\Entity\Model\Cities",   inversedBy="id")
         */
        private $city;
    
        /**
        * @ORM\ManyToOne(targetEntity="App\Wdm\MainBundle\Entity\Model\Districts", inversedBy="id")
        */
         private $district;
    
    
    1. Update your database schema and fill the cities and districts fields with some example data

    2. Go into your AdminClass in the configureFormFields Function and add the following (make sure to use the 'choice_label' option correctly with the corresponding field in your district or city entity.

        protected function configureFormFields(FormMapper $formMapper)
        {         $formMapper
                      // Some other added fields
    
                 ->add('district', EntityType::class, [
                     'choice_label' => 'name',
                     'class'       => Districts::class,
                     'placeholder' => '',
                 ])
    
                 ->add('city', EntityType::class, [
                     'choice_label' => 'name',
                     'class'       => Cities::class,
                     'placeholder' => '',
                 ])       
    
                 ;
    
    1. This should already work pretty well. You should now be able to have a dependent field. Let´s take a look to the AJAX magic now.

    2. Go into your AdminClass (same as the configureFields-Class) and add the following

     protected function configureRoutes(RouteCollection $collection)
        {    $collection->add('reloadCities', 'reload-cities');
    
        }
    
    1. Now you have a route that you can access from your ajax url. Now create a new Controller Class, wherever you want...
    request->get('id');
            $cities = $this->getDoctrine()->getRepository(Cities::class)->findBy(array("district" => $districtid));
            return $this->render("company/cities.html.twig", array("cities" => $cities));
        }
    }
    

    ... and don´t forget to register this controller in your services.yaml...

      admin.company:
            class: App\Wdm\MainBundle\Admin\CompanyAdmin
            arguments:
                - ~
                - App\Wdm\MainBundle\Entity\Model\Company
                - App\Wdm\MainBundle\Controller\CitiesController (THIS IS THE NEW ROW)
    

    ... and finally the little template that is being called in this function...

    // THIS IS THE cities.html.twig
    
    {% for city in cities %}
    
    {% endfor %}
    
    1. So far so good. We now got the logic that get´s the data from the ajax call and returns it to your sonata admin edit form. The only thing thats missing now is the jquery code that is needed in the edit template of sonata admin.

    Go into your AdminClass and insert the following code (e.g. before configureFormFields)

     public function getTemplate($name)
        {
            switch ($name) {
                case 'edit':
                    return 'company/cities_admin.html.twig';
                    break;
                default:
                    return parent::getTemplate($name);
                    break;
            }
        }
    

    Now we create this cities_admin.html.twig template that overrides the default template

    {% extends 'SonataAdminBundle:CRUD:edit.html.twig' %}
    
    {% block form %}
        {{ parent() }}
    
    
    {% endblock %}
    

    That´s it. Should work like a charm.

提交回复
热议问题