Home > Mobile >  Symfony dynamic dropdown
Symfony dynamic dropdown

Time:02-04

Hi I want to get dynamic dropdown lists with cities depending on region. I try to follow official symfony documentation and add dynamic forms but I'm newbie in symfony and my coding skills didn't let me get what am I doing wrong, so I need some advise

City.php

namespace App\Entity;

use App\Repository\CityRepository;
use Doctrine\ORM\Mapping as ORM;

/**
 * @ORM\Entity(repositoryClass=CityRepository::class)
 */
class City
{
/**
 * @ORM\Id
 * @ORM\GeneratedValue
 * @ORM\Column(type="integer")
 */
private $id;

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

/**
 * @ORM\ManyToOne(targetEntity=Region::class, inversedBy="cities")
 * @ORM\JoinColumn(name="parent_id", referencedColumnName="id", nullable=false)
 */
private $parent;

public function getId(): ?int
{
    return $this->id;
}

public function getName(): ?string
{
    return $this->name;
}

public function setName(string $name): self
{
    $this->name = $name;

    return $this;
}

public function getParent(): ?Region
{
    return $this->parent;
}

public function setParent(?Region $parent): self
{
    $this->parent[] = $parent;

    return $this;
}

public function __toString()
{
    return $this->name;
}

Region.php

namespace App\Entity;

use App\Repository\RegionRepository;
use Doctrine\ORM\Mapping as ORM;

/**
 * @ORM\Entity(repositoryClass=RegionRepository::class)
 */
class Region
{
/**
 * @ORM\Id
 * @ORM\GeneratedValue
 * @ORM\Column(type="integer")
 */
private $id;

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

/**
 * @ORM\OneToMany(targetEntity="App\Entity\City", mappedBy="parent")
 **/
protected $cities;

public function getId(): ?int
{
    return $this->id;
}

public function getName(): ?string
{
    return $this->name;
}

public function setName(string $name): self
{
    $this->name = $name;

    return $this;
}

/**
 * Get cities
 *
 * @return \Doctrine\Common\Collections\Collection
 */
public function getAvailableCities()
{
    return $this->cities;
}

public function __toString()
{
    return $this->name;
}

and Form.type.php

 public function buildForm(FormBuilderInterface $builder, array $options): void
{
    $builder
        ->add('title', TextType::class)
        ->add('description', TextareaType::class)
        ->add('region',  EntityType::class, [
            'class' => Region::class,
            'choice_label' => 'name',
            'placeholder' => '')
;
 $formModifier = function (FormInterface $form, Region $region = null) {
        $cities = null === $region ? [] : $region->getAvailableCities();

        $form->add('city', EntityType::class, [
            'class' => City::class,
            'placeholder' => '',
            'choices' => $cities,
        ]);
    };

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

            $formModifier($event->getForm(), $data->getRegion());
        }
    );

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

            $formModifier($event->getForm()->getParent(), $region);
        }
    );

And in twig I have:

var $region = $('#offer_region');
    $region.change(function() {
        var $form = $(this).closest('form');
        var data = {};
        data[$region.attr('id')] = $region.val();
        $.ajax({
            url : $form.attr('action'),
            type: $form.attr('method'),
            data : data,
            success: function(html) {
                $('#offer_city').replaceWith(
                    $(html).find('#offer_city')
                );
            }
        });

Ajax in POST return correct region value but still there is somthing I missed that city dropdown is always empty, maybe you could point me what am I missing in this code?

CodePudding user response:

So I believe the failure comes, [at least], from the point that you try to fetch the html element from the entire HTTP response object, while you should rather fetch it from the body/content.

From the jQuery Documentation:

The jqXHR Object The jQuery XMLHttpRequest (jqXHR) object returned by $.ajax() as of jQuery 1.5 is a superset of the browser's native XMLHttpRequest object. For example, it contains responseText and responseXML properties, as well as a getResponseHeader() method. When the transport mechanism is something other than XMLHttpRequest (for example, a script tag for a JSONP request) the jqXHR object simulates native XHR functionality where possible.

(...)

Data Types

(...)

The available data types are text, html, xml, json, jsonp, and script.

If text or html is specified, no pre-processing occurs. The data is simply passed on to the success handler, and made available through the responseText property of the jqXHR object.

This means you have to change this line in your AJAX code:

$('#offer_city').replaceWith(
    $(html).find('#offer_city')
);

by this line:

$('#offer_city').replaceWith(
    $(html.responseText).find('#offer_city')
);
  •  Tags:  
  • Related