如何在symfony中动态填充下拉列表? (选择该地区的城市)

时间:2017-09-28 11:05:24

标签: javascript php ajax symfony symfony-forms

我解释了我的问题:

我必须创建一个表单,根据我们之前的选择填充下拉列表。

我有两个实体:

一个地区可能有多个城市(ManyToOne)关系。

我按照此处的文档How to Dynamically Modify Forms Using Form Events (Dynamic Generation for Submitted Forms)

以下是实体的代码:

地区实体:

class Region
{
    /**
     * @var int
     *
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;

    /**
     * @var string
     *
     * @ORM\Column(name="nom", type="string", length=255)
     */
    private $nom;

    /**
     * @var int
     *
     * @ORM\Column(name="numero", type="smallint")
     */
    private $numero;
}

Ville实体:

class Ville
{
    /**
     * @var int
     *
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;

    /**
     * @var string
     *
     * @ORM\Column(name="nom", type="string", length=255)
     */
    private $nom;

    /**
     * @var int
     *
     * @ORM\Column(name="numero", type="smallint")
     */
    private $numero;

    /**
     * @var int
     *
     * @ORM\Column(name="codePostal", type="smallint")
     */
    private $codePostal;

    /**
     * @var Region
     *
     * @ORM\ManyToOne(targetEntity="GE\CandidatBundle\Entity\Region")
     */
    protected $region;
}

我的问题:

我使用query_builder选项检索区域列表,但如何根据区域选择检索城市列表。

AnnonceType:

 $builder
->add('region', EntityType::class, [
                'label' => 'Region *',
                'label_attr' => [
                    "class" => "smaller lighter blue",
                    "style" => "font-size: 21px;",
                ],
                'class'         => 'GECandidatBundle:Region',
                'choice_label'  => 'nom',
                'multiple'      => false,
                'query_builder' => function(RegionRepository $repository) {
                    return $repository->getListeRegion();
                }
            ])
            ->add('ville', TextType::class, [
                'label' => 'Ville *',
                'label_attr' => [
                    "class" => "smaller lighter blue",
                    "style" => "font-size: 21px;",
                ],
            ]);
$formModifier = function (FormInterface $form, Region $region = null) {
            $ville = null === $region ? array() : $region->getNom();

            $form->add('ville', EntityType::class, array(
                'class' => 'GECandidatBundle:Ville',
                'placeholder' => '',
                'choices' => $ville,

                'label' => 'Ville *',
                'label_attr' => [
                    "class" => "smaller lighter blue",
                    "style" => "font-size: 21px;",
                ],
                'choice_label'  => 'nom',
                'multiple'      => false,
                /*'query_builder' => function(VilleRepository $repository) {
                    return $repository->getVilleByRegion();
                }*/
            ));
        };

        $builder->addEventListener(
            FormEvents::PRE_SET_DATA,
            function (FormEvent $event) use ($formModifier) {
                $data = $event->getData();
                $formModifier($event->getForm(), $data->getVille());
            }
        );

        $builder->get('region')->addEventListener(
            FormEvents::POST_SUBMIT,
            function (FormEvent $event) use ($formModifier) {
                $region = $event->getForm()->getData();
                $formModifier($event->getForm()->getParent(), $region);
            }
        );

new.html.twig:

    {{ form_start(form) }}
        {{ form_row(form.region) }}    {# <select id="ge_candidatbundle_annonce_region" ... #}
        {{ form_row(form.ville) }} {# <select id="ge_candidatbundle_annonce_ville" ... #}
        {# ... #}
    {{ form_end(form) }}
<script>
        var $region = $('#ge_candidatbundle_annonce_region');
        $region.change(function() {
            var $form = $(this).closest('form');
            var data = {};
            data[$region.attr('nom')] = $region.val();
            $.ajax({
                url : $form.attr('action'),
                type: $form.attr('method'),
                data : data,
                success: function(html) {
                    $('#ge_candidatbundle_annonce_ville').replaceWith(
                        $(html).find('#ge_candidatbundle_annonce_ville')
                    );
                }
            });
        });
    </script>

2 个答案:

答案 0 :(得分:0)

许多解决方案:

更简单的方法是将Region添加到class Region { /** * @var int * * @ORM\Column(name="id", type="integer") * @ORM\Id * @ORM\GeneratedValue(strategy="AUTO") */ private $id; /** * @var string * * @ORM\Column(name="nom", type="string", length=255) */ private $nom; /** * @var int * * @ORM\Column(name="numero", type="smallint") */ private $numero; /** @ORM\OneToMany(targetEntity="Ville", inversedBy="region") **/ protected $villes; public function getVilles() { return $this->villes; } public function setVilles($villes) { $this->villes = $villes; return $this; } // [... + get/setVilles functions ...] } 实体并执行类似的操作:

$formModifier = function (FormInterface $form, Region $region = null) {
            $villes = null === $region ? array() : $region->getVilles();

            $form->add('ville', EntityType::class, array(
                'class' => 'GECandidatBundle:Ville',
                'placeholder' => '',
                'choices' => $villes,

                'label' => 'Ville *',
                'label_attr' => [
                    "class" => "smaller lighter blue",
                    "style" => "font-size: 21px;",
                ],
                'choice_label'  => 'nom',
                'multiple'      => false,
                /*'query_builder' => function(VilleRepository $repository) {
                    return $repository->getVilleByRegion();
                }*/
            ));
        };

        $builder->addEventListener(
            FormEvents::PRE_SET_DATA,
            function (FormEvent $event) use ($formModifier) {
                $data = $event->getData();
                $formModifier($event->getForm(), $data->getVille());
            }
        );

        $builder->get('region')->addEventListener(
            FormEvents::POST_SUBMIT,
            function (FormEvent $event) use ($formModifier) {
                $region = $event->getForm()->getData();
                $formModifier($event->getForm()->getParent(), $region);
            }
        );

在你的类型中:

VilleRepository

第二个选项:

取消注释您的查询构建器,并通过传递getVilleByRegion实体

参数,在您的region nom中实施

<强>更新

您使用非现有属性设置ajax数据<script> var $region = $('#ge_candidatbundle_annonce_region'); $region.change(function() { var $form = $(this).closest('form'); var data = {}; data[$region.attr('name')] = $region.val(); $.ajax({ url : $form.attr('action'), type: $form.attr('method'), data : data, success: function(html) { $('#ge_candidatbundle_annonce_ville').replaceWith( $(html).find('#ge_candidatbundle_annonce_ville') ); } }); }); </script> 将您的javascript代码替换为:

{{1}}

答案 1 :(得分:0)

<强>更新

  1. 我修改了实体。

  2. 我修改了AnnonceType。

  3. 我修改了new.html.twig。

  4. 以下是实体的代码:

    地区实体:

    class Region
    {
        /**
         * @var int
         *
         * @ORM\Column(name="id", type="integer")
         * @ORM\Id
         * @ORM\GeneratedValue(strategy="AUTO")
         */
        private $id;
    
        /**
         * @var string
         *
         * @ORM\Column(name="nom", type="string", length=255)
         */
        private $nom;
    
        /**
         * @var int
         *
         * @ORM\Column(name="numero", type="smallint")
         */
        private $numero;
    /**
     * @ORM\OneToMany(targetEntity="GE\CandidatBundle\Entity\Ville", mappedBy="region")
     **/
    protected $villes;
    
    /**
     * Get villes
     *
     * @return \Doctrine\Common\Collections\Collection
     */
    public function getVilles()
    {
        return $this->villes;
    }
    }
    

    Ville实体:

    class Ville
    {
        /**
         * @var int
         *
         * @ORM\Column(name="id", type="integer")
         * @ORM\Id
         * @ORM\GeneratedValue(strategy="AUTO")
         */
        private $id;
    
        /**
         * @var string
         *
         * @ORM\Column(name="nom", type="string", length=255)
         */
        private $nom;
    
        /**
         * @var int
         *
         * @ORM\Column(name="numero", type="smallint")
         */
        private $numero;
    
        /**
         * @var int
         *
         * @ORM\Column(name="codePostal", type="smallint")
         */
        private $codePostal;
    
    /**
     * @var Region
     * @ORM\ManyToOne(targetEntity="GE\CandidatBundle\Entity\Region", inversedBy="villes")
     */
    protected $region;
    }
    

    AnnonceType:

         $builder
        ->add('region', EntityType::class, [
                        'label' => 'Region *',
                        'label_attr' => [
                            "class" => "smaller lighter blue",
                            "style" => "font-size: 21px;",
                        ],
                        'class'         => 'GECandidatBundle:Region',
                        'choice_label'  => 'nom',
                        'multiple'      => false,
                        'query_builder' => function(RegionRepository $repository) {
                            return $repository->getListeRegion();
                        }
                    ])
                    ->add('ville');
    $formModifier = function (FormInterface $form, Region $region = null) {
                $villes = null === $region ? array() : $region->getVilles();
    
                $form->add('ville', EntityType::class, array(
                    'class' => 'GECandidatBundle:Ville',
                    'placeholder' => '',
                    'choices' => $villes,
    
                    'label' => 'Ville *',
                    'label_attr' => [
                        "class" => "smaller lighter blue",
                        "style" => "font-size: 21px;",
                    ],
                    'choice_label'  => 'nom',
                    'multiple'      => false,
    
                ));
            };
    
            $builder->addEventListener(
                FormEvents::PRE_SET_DATA,
                function (FormEvent $event) use ($formModifier) {
                    $data = $event->getData();
                    $formModifier($event->getForm(), $data->getVille());
                }
            );
    
            $builder->get('region')->addEventListener(
                FormEvents::POST_SUBMIT,
                function (FormEvent $event) use ($formModifier) {
                    $region = $event->getForm()->getData();
                    $formModifier($event->getForm()->getParent(), $region);
                }
            );
    

    new.html.twig:

        {{ form_start(form) }}
                {{ form_row(form.region) }}    {# <select id="ge_candidatbundle_annonce_region" ... #}
                {{ form_row(form.ville) }} {# <select id="ge_candidatbundle_annonce_ville" ... #}
                {# ... #}
            {{ form_end(form) }}
    <script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
        <script>
                var $region = $('#ge_candidatbundle_annonce_region');
                $region.change(function() {
                    var $form = $(this).closest('form');
                    var data = {};
                    data[$region.attr('name')] = $region.val();
                    $.ajax({
                        url : $form.attr('action'),
                        type: $form.attr('method'),
                        data : data,
                        success: function(html) {
                            $('#ge_candidatbundle_annonce_ville').replaceWith(
                                $(html).find('#ge_candidatbundle_annonce_ville')
                            );
                        }
                    });
                });
            </script>