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



我解释了我的问题:

我必须创建一个表格,其中下拉列表根据我们的选择填写。

我有两个实体:

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

我遵循了此处的文档,如何使用表单事件(提交表单的动态生成)动态修改表单。

这是实体的代码:

区域实体:

class Region
{
    /**
     * @var int
     *
     * @ORMColumn(name="id", type="integer")
     * @ORMId
     * @ORMGeneratedValue(strategy="AUTO")
     */
    private $id;
    /**
     * @var string
     *
     * @ORMColumn(name="nom", type="string", length=255)
     */
    private $nom;
    /**
     * @var int
     *
     * @ORMColumn(name="numero", type="smallint")
     */
    private $numero;
}

维尔实体:

class Ville
{
    /**
     * @var int
     *
     * @ORMColumn(name="id", type="integer")
     * @ORMId
     * @ORMGeneratedValue(strategy="AUTO")
     */
    private $id;
    /**
     * @var string
     *
     * @ORMColumn(name="nom", type="string", length=255)
     */
    private $nom;
    /**
     * @var int
     *
     * @ORMColumn(name="numero", type="smallint")
     */
    private $numero;
    /**
     * @var int
     *
     * @ORMColumn(name="codePostal", type="smallint")
     */
    private $codePostal;
    /**
     * @var Region
     *
     * @ORMManyToOne(targetEntity="GECandidatBundleEntityRegion")
     */
    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>

update

  1. 我修改了实体。

  2. 我修改了AnnonCetype。

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

这是实体的代码:

区域实体:

class Region
{
    /**
     * @var int
     *
     * @ORMColumn(name="id", type="integer")
     * @ORMId
     * @ORMGeneratedValue(strategy="AUTO")
     */
    private $id;
    /**
     * @var string
     *
     * @ORMColumn(name="nom", type="string", length=255)
     */
    private $nom;
    /**
     * @var int
     *
     * @ORMColumn(name="numero", type="smallint")
     */
    private $numero;
/**
 * @ORMOneToMany(targetEntity="GECandidatBundleEntityVille", mappedBy="region")
 **/
protected $villes;
/**
 * Get villes
 *
 * @return DoctrineCommonCollectionsCollection
 */
public function getVilles()
{
    return $this->villes;
}
}

维尔实体:

class Ville
{
    /**
     * @var int
     *
     * @ORMColumn(name="id", type="integer")
     * @ORMId
     * @ORMGeneratedValue(strategy="AUTO")
     */
    private $id;
    /**
     * @var string
     *
     * @ORMColumn(name="nom", type="string", length=255)
     */
    private $nom;
    /**
     * @var int
     *
     * @ORMColumn(name="numero", type="smallint")
     */
    private $numero;
    /**
     * @var int
     *
     * @ORMColumn(name="codePostal", type="smallint")
     */
    private $codePostal;
/**
 * @var Region
 * @ORMManyToOne(targetEntity="GECandidatBundleEntityRegion", 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>

许多解决方案:

更简单的是将villes添加到您的Region实体并做类似的事情:

class Region
{
    /**
     * @var int
     *
     * @ORMColumn(name="id", type="integer")
     * @ORMId
     * @ORMGeneratedValue(strategy="AUTO")
     */
    private $id;
    /**
     * @var string
     *
     * @ORMColumn(name="nom", type="string", length=255)
     */
    private $nom;
    /**
     * @var int
     *
     * @ORMColumn(name="numero", type="smallint")
     */
    private $numero;
    /** @ORMOneToMany(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);
            }
        );

第二个选项:

通过参数传递 region entity

,请查询构建器并在VilleRepository中实现您的CC_3

update

您使用非现有属性nom设置AJAX数据,替换您的JavaScript代码:

<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> 

最新更新