Dark Magic Dark Magic - 11 months ago 90
Ajax Question

How to fill the dropdown list dynamically in symfony? (select the cities of the region)

I explain my problem:

I have to create a form where the drop-down lists are filled according to our choices in the previous ones.

I have two entities:

A Region may have several Cities (ManyToOne) relationship.

I followed the documentation from here How to Dynamically Modify Forms Using Form Events (Dynamic Generation for Submitted Forms) .

Here is the code for the entities:

Region entity:

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

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


my problem:

I retrieve the list of regions with the query_builder option but how do I retrieve the list of cities according to the choice of 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', 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>

Answer Source

UPDATE

  1. I modified the entities.

  2. I modified the AnnonceType.

  3. I modified the new.html.twig.

Here is the code for the entities:

Region entity:

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

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>
Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download