The problem is that nothing is loaded in the municipality field, it goes undefined. In AJAX code, I understand the meaning of the province well. But in the addMunicipioField.php class does not take the value of $ province, it is always nul

I am trying to make a registration form where part of the usual fields ( name, nick, password, ... ) I also add two dependent fields Municipality and Province .
Codec Controller:
class UserController extends Controller { private $session; public function __construct() { $this->session = new Session(); } public function registerAction(Request $request) { if (is_object($this->getUser())) { return $this->redirect('home'); } $user = new DbUsuario(); $form = $this->createForm(RegistreUserType::class, $user); $form->handleRequest($request); if ($form->isSubmitted()) { if ($form->isValid()) { $em = $this->getDoctrine()->getManager(); $query = $em->createQuery('SELECT u FROM BackendBundle:DbUsuario u WHERE u.email = :email OR u.nick = :nick') ->setParameter('email', $form->get("email")->getData()) ->setParameter('nick', $form->get("nick")->getData()); $user_isset = $query->getResult(); if (count($user_isset) == 0) { $factory = $this->get("security.encoder_factory"); $encoder = $factory->getEncoder($user); $password = $encoder->encodePassword($form->get("password")->getData(), $user->getSalt()); $user->setPassword($password); $user->setRole("ROLE_USER"); $user->setImagen(null); $em->persist($user); $flush = $em->flush(); if ($flush == null) { $status = "Te has registrado correctamente"; $this->session->getFlashBag()->add("status", $status); return $this->redirect("login"); } else { $status = "No te has registrado correctamente"; } } else { $status = "Usuario ya esta registrado."; } } else { $status = "No te has registrado correctamente."; } $this->session->getFlashBag()->add("status", $status); } return $this->render('AppBundle:User:register.html.twig', array( "form" => $form->createView()
The entity that creates the form is DbUsuario , which has an idMunicipio field.
private $idMunicipio; public function setIdMunicipio(\BackendBundle\Entity\DbMunicipio $idMunicipio = null) { $this->idMunicipio = $idMunicipio; return $this; } public function getIdMunicipio() { return $this->idMunicipio; }
Then the Entity Of DbMunicipio , which connects to the 'province' with
private $provincia; public function setProvincia(\BackendBundle\Entity\DbProvincia $provincia = null){ $this->provincia = $provincia; return $this; }
And the DbProvincia Entity , which has only fields ( id (integer), slug (String) and province (String) ).
I define the form as follows:
namespace AppBundle\Form; use .... class RegistreUserType extends AbstractType { public function buildForm(FormBuilderInterface $builder, array $options) { $factory = $builder->getFormFactory(); $builder->add('nombre', TextType::class, array('label' => 'Nombre', 'required' => 'required', 'attr' => array('class' => 'form-nombre form-control') )); $builder->add('apellido', TextType::class, array('label' => 'Apellido', 'required' => 'required', 'attr' => array('class' => 'form-apellido form-control') )); $builder->add('nick', TextType::class, array('label' => 'Nick', 'required' => 'required', 'attr' => array('class' => 'form-nick form-control nick-input') )); $provinSubscriber = new AddProvinciaField($factory); $builder->addEventSubscriber($provinSubscriber); $muniSubscriber = new AddMunicipioField($factory); $builder->addEventSubscriber($muniSubscriber); $builder->add('email', EmailType::class, array('label' => 'Correo electrónico', 'required' => 'required', 'attr' => array('class' => 'form-email form-control') )); $builder->add('password', PasswordType::class, array('label' => 'Password', 'required' => 'required', 'attr' => array('class' => 'form-password form-control') )); $builder->add('Registrarse', SubmitType::class, array("attr" => array("class" => "form-submit btn btn-success"))); } public function configureOptions(OptionsResolver $resolver) { $resolver->setDefaults(array( 'data_class' => 'BackendBundle\Entity\DbUsuario' )); } public function getBlockPrefix() { return 'backendbundle_dbusuario'; } }
I define in AppBundle \ Form \ eventListener \ AddProvinciaField the classes called on the form:
namespace AppBundle\Form\EventListener; use .... use BackendBundle\Entity\DbProvincia; class AddProvinciaField implements EventSubscriberInterface { private $factory; public function __construct(FormFactoryInterface $factory) { $this->factory = $factory; } public static function getSubscribedEvents() { return array( FormEvents::PRE_SET_DATA => 'preSetData', FormEvents::PRE_SUBMIT => 'preSubmit' ); } private function addProvinciaForm($form, $provincia) { $form -> add('provincia', EntityType::class, array( 'class' => 'BackendBundle:DbProvincia', 'label' => 'Provincia', 'placeholder' => '_ Elegir _', 'auto_initialize' => false, 'mapped' => false, 'attr'=> array('class' => 'form-provincia form-control provincia-input'), 'query_builder' => function (EntityRepository $repository) { $qb = $repository->createQueryBuilder('provincia'); return $qb; } )); } public function preSetData(FormEvent $event){ $data = $event->getData(); $form = $event->getForm(); if (null === $data) {return;} $provincia = ($data->getIdMunicipio()) ? $data->getIdMunicipio()->getProvincia() : null ; $this->addProvinciaForm($form, $provincia); } public function preSubmit(FormEvent $event) { $data = $event->getData(); $form = $event->getForm(); if (null === $data) { return;} $provincia = array_key_exists('provincia-input', $data) ? $data['provincia-input'] : null; $this->addProvinciaForm($form, $provincia); } }
And later I define AddMunicipioField .php:
namespace AppBundle\Form\EventListener; use .... use BackendBundle\Entity\DbProvincia; class AddMunicipioField implements EventSubscriberInterface { private $factory; public function _construct(FormFactoryInterface $factory) { $this->factory = $factory; } public static function getSubscribedEvents() { return array( FormEvents::PRE_SET_DATA => 'preSetData', FormEvents::PRE_SUBMIT => 'preSubmit' ); } private function addMunicipioForm($form, $provincia) { $form->add('idMunicipio', EntityType::class, array( 'class' => 'BackendBundle:DbMunicipio', 'label' => 'Municipio', 'placeholder' => '_ Elegir _', 'auto_initialize' => false, 'attr'=> array('class' => 'form-municipio form-control municipio-input'), 'query_builder' => function (EntityRepository $repository) use ($provincia) { $qb = $repository->createQueryBuilder('idMunicipio') ->innerJoin('idMunicipio.provincia', 'provincia'); if ($provincia instanceof DbProvincia) { $qb->where('idMunicipio.provincia = :provincia') ->setParameter('provincia', $provincia); } elseif (is_numeric($provincia)) { $qb->where('provincia.id = :provincia') ->setParameter('provincia', $provincia); } else { $qb->where('provincia.provincia = :provincia') ->setParameter('provincia', null); } return $qb; } )); } public function preSetData(FormEvent $event){ $data = $event->getData(); $form = $event->getForm(); if (null === $data) { return; } $provincia = ($data->getIdMunicipio()) ? $data->getIdMunicipio()->getProvincia() : null ; $this->addMunicipioForm($form, $provincia); } public function preSubmit(FormEvent $event){ $data = $event->getData(); $form = $event->getForm(); if (null === $data) { return; } $provincia = array_key_exists('provincia_input', $data) ? $data['provincia_input'] : null; $this->addMunicipioForm($form, $provincia); }
}
And finally, the AJAX request:
$(document).ready(function(){ var $form = $(this).closest('form'); $(".provincia-input").change(function(){ var data = { idMunicipio: $(this).val() }; $.ajax({ type: 'POST', url: $form.attr('action'), data: data, success: function(data) { for (var i=0, total = data.length; i < total; i++) { $('.municipio-input').append('<option value="' + data[i].id + '">' + data[i].municipio + '</option>'); } } }); }); });
I added var_dump and alert () to the code. This is the output method.
In this case, the value of the region is always null .
addMunicipioField.php public function preSetData(FormEvent $event){ $data = $event->getData(); $form = $event->getForm(); if (null === $data) { return; } $provincia = ($data->getIdMunicipio()) ? $data->getIdMunicipio()->getProvincia() : null ; var_dump('presetdata'); var_dump($provincia); $this->addMunicipioForm($form, $provincia); }
AJAX:
$(document).ready(function(){ var $form = $(this).closest('form'); $(".provincia-input").change(function(){ alert($('.provincia-input').val()); // THIS IS CORRECT VALUE, INTEGER. var data = { idMunicipio: $(this).val() }; $.ajax({ type: 'POST', url: $form.attr('action'), data: data, success: function(data) { alert(data); alert(data.length); // THIS IS INCORRECT. for (var i=0, total = data.length; i < total; i++) { $('.municipio-input').append('<option value="' + data[i].id + '">' + data[i].municipio + '</option>'); } } }); }); });

Another point of view Objects are the same. In this case, it works, but I have to click the submit button. How could I do this without pressing a button, that it was an automatic change?
The RegistreUserType class extends AbstractType. I am adding the following lines.
$builder -> add('provincia', EntityType::class, array( 'class' => 'BackendBundle:DbProvincia', 'label' => 'Provincia', 'placeholder' => '_ Elegir _', 'auto_initialize' => false, 'mapped' => false, 'attr'=> array('class' => 'form-provincia form-control provincia-input'), 'query_builder' => function (EntityRepository $repository) { $qb = $repository->createQueryBuilder('provincia'); return $qb; } )); $builder->add('idMunicipio', EntityType::class, array( 'class' => 'BackendBundle:DbMunicipio', 'label' => 'Municipio', 'placeholder' => '_ Elegir _', 'auto_initialize' => false, 'mapped' => false, 'attr'=> array('class' => 'form-municipio form-control municipio-input') )); $builder->addEventSubscriber(new AddMunicipioField());
New AddMunicpioField () class:
class AddMunicipioField implements EventSubscriberInterface { public static function getSubscribedEvents() { return array( FormEvents::PRE_SUBMIT => 'preSubmit', FormEvents::PRE_SET_DATA => 'preSetData', ); } public function preSubmit(FormEvent $event){ $data = $event->getData(); $this->addField($event->getForm(), $data['provincia']); } protected function addField(Form $form, $provincia){ $form->add('idMunicipio', EntityType::class, array( 'class' => 'BackendBundle:DbMunicipio', 'label' => 'Municipio', 'placeholder' => '_ Elegir _', 'auto_initialize' => false, 'mapped' => false, 'attr'=> array('class' => 'form-municipio form-control municipio-input'), 'query_builder' => function(EntityRepository $er) use ($provincia){ $qb = $er->createQueryBuilder('idMunicipio') ->where('idMunicipio.provincia = :provincia') ->setParameter('provincia', $provincia); return $qb; } )); }
Ajax Codec:
$(document).ready(function () { $('.provincia-input').change(function () { var $form = $(this).closest('form'); var data = $('.provincia-input').serialize(); $.ajax({ url: $form.attr('action'), type: 'POST', data: data, success: function (data) { $('.municipio-input').replaceWith($(html).find('.municipio-input')); } }); });
});