Я объясняю свою проблему:
Я должен создать форму, в которой раскрывающиеся списки заполняются в соответствии с нашими выборами в предыдущих.
У меня есть два объекта:
Регион может иметь несколько связей (ManyToOne).
Я следил за документацией здесь. Как динамически изменять формы с помощью событий формы (динамическое поколение для отправленных форм) .
Вот код для объектов:
Регион:
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; }
моя проблема:
Я извлекаю список регионов с параметром 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>
Многие решения:
Более простым должно быть добавление villes
в ваш объект 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
в свой VilleRepository
ваш getVilleByRegion
, передав аргумент субъекту region
ОБНОВИТЬ
Вы устанавливаете свои данные ajax с помощью несуществующего атрибута nom
вместо кода 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>
ОБНОВИТЬ
Я изменил объекты.
Я модифицировал AnnonceType.
Я изменил new.html.twig.
Вот код для объектов:
Регион:
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>