Bonjour à tous,

j'ai un formulaire que voici:

class ZonestechniqueType extends AbstractType
{
    /* @param FormBuilderInterface $builder
     * @param array $options
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('parcsimmobilier', 'entity', array(
                                    'mapped' => false,
                                    'class'    => 'MySpaceMyBundle:Parcsimmobilier',
                                    'property' => 'nom',
                                    'empty_value' => '-- sélectionner un parc --',
                                    'label'    => 'Choisir le parc immobilier : ',
                                    ))
            ->add('ensembles', 'entity', array(
                                    'mapped' => false,
                                    'class'    => 'MySpaceMyBundle:Ensembles',
                                    'query_builder' => function(EntityRepository $er) {
                                        return $er->createQueryBuilder('e')
                                                  ->join('e.parcsimmobilier','p');
                                    },
                                    'property' => 'nom',
                                    'empty_value' => '-- sélectionner un ensemble --',
                                    'label'    => 'Choisir l\'ensemble : ',
                                    ))
            ->add('batiments','entity', array(
                                    'class'    => 'MySpaceMyBundle:Batiments',
                                    'query_builder' => function(EntityRepository $er) {
                                        return $er->createQueryBuilder('b')
                                                  ->join('b.ensembles','e');
                                    },
                                    'property' => 'nom',
                                    'empty_value' => '-- sélectionner un batiment --',
                                    'label'    => 'Choisir un batiment : ',
                                    ))
            ->add('categorieszonestechnique')
            ->add('nom')
            ->add('localisation')
            ->add('commentaire')
            ;
    }

L'entité parcsimmobilier et ensembles sont liées par une relation ManyToOne ($parcsimmobilier dans Ensembles.php). L'entité Batiments.php est liée à Ensembles.php par une relation ManyToOne ($ensembles dans Batiments.php), et enfin ZonesTechnique.php est liée à Batiments.php par uen ManyToOne aussi ($batiments dans Zonestechnique.php).

Je dois faire un formulaire dynamique lors de la création d'une nouvelle ZonesTechnique, donc appel AJAX obligatoire. Tout cela doit se dérouler ainsi:
je sélectionne un parc, dans la liste déroulante suivante les ensembles liés à ce parc apparaissent, je sélectionne un ensemble, dans la liste déroulante suivante les bâtiments liés à l'ensemble préalablement sélectionné apparaissent.

Si vous voulez un apperçu, cela doit se faire comme ça(formulaire dynamique) mais aves les données présentent dans ma base bien entendu, et c'est là que je pêche...

Mon problème est liée au fait que ceci est ma première Ajax. Je ne sais pas vraiment si je m'y prend bien, voire même si je fais quoi que ce soit de bon.
Voci mon routing.yml pour l'appel de mes méthodes:

ajouterZonesConformites:
    path:     /gestionzonestechniquesconformites/ajouter
    defaults: { _controller: MySpaceMyBundle:GestionZonesTechniques:ajouterZonesConformites }
    requirements:
    methods: GET

# Ajax
formulaireZones:
    pattern:  /gestionzonestechniquesconformites/ajouterformulaire
    defaults: { _controller: MySpaceMyBundle:GestionZonesTechniques:formulaireZones }
    requirements:
      _method: POST

ajouterZonesConformites_process:
    path:     /gestionzonestechniquesconformites/ajouter/process
    defaults: { _controller: MySpaceMyBundle:GestionZonesTechniques:ajouterZonesConformites }
    requirements:
    methods: POST

Je me pose quand même certaines question: Dois-je créer une route différente pour afficher le formulaire et pour le remplir? comment cela fonctionne t-il réellement? Comme vous pouvez le voir, j'ai une méthode pour afficher et envoyer le formulaire correspondant à deux routes, et une autre méthode pour remplir le formulaire en Ajax et sa route respective? C'est comme cela qu'il faut faire?

Voici mon controller pour remplir le formulaire et l'ajout lors de la validation du formulaire:

    public function formulaireZonesAction() {

        $request = $this->getRequest();
        $em = $this->getDoctrine()->getEntityManager();

        if($request->isXmlHttpRequest()) { // pour vérifier la présence d'une requete Ajax

            $id = '';
            $id = $request->get('id');

                if ($id != '') {

                    $ensembles = $em->getRepository('MySpaceMyBundle:Ensembles')->getEnsembles($id);
                    echo $ensembles;

                    $tabEnsembles = array();
                    $i = 0;

                        foreach($ensembles as $ensemble) { // transformer la réponse à ta requete en tableau qui replira le select pour ensembles

                            $tabEnsembles[$i]['id'] = $ensemble->getId();
                            $tabEnsembles[$i]['nom'] = $ensemble->getNom();
                            $i++;
                        }

                    $response = new Response();

                    $data = json_encode($tabEnsembles); // formater le résultat de la requête en json

                    $response->headers->set('Content-Type', 'application/json');
                    $response->setContent($data);

                    return $response;
                }

        } else {

            return new Response('BIM ça plante');
        }
    }

//METHODE pour AJOUTER Zonestechniques
    /**
     * Select dynamique.
     *
     * @Route("/gestionzonestechniquesconformites/ajouterformulaire", name="formulaireZones")
     * @Method("POST")
     */
    public function ajouterZonesConformitesAction() {

        $em=$this->getDoctrine()->getManager();
        $zones = $em->getRepository('MySpaceMyBundle:Zonestechnique');

        $zones = new Zonestechnique;
        $form=$this->createForm(new ZonestechniqueType(), $zones);
        $request = $this->getRequest();

            if($request->isMethod('POST') | $form->isValid()) {

                $form->bind($request);
                $zoneConformite = $form->getData();

                $em->persist($zones);
                $em->flush();

                return $this->redirect($this->generateUrl('indexRechercheZones'));
            }

            //retourner le formulaire d'ajout si c'est invalide
            else {
                    return $this->render('MySpaceMyBundle:ZonesTechnique:ajouterZonesTechniqueConformites.html.twig', array('form' => $form->createView(), 'zone' => $zones ));
                }
    }

Quand j'affiche ma page, "aucune erreur" si ce n'est dans ma symfony ToolBar, j'ai bien un onglet Ajax qui est présent. Il m'affiche un numéro (1 au départ) entouré de vert. Pour me dire que tout est en ordre. Toutefois dès que je choisis un parc dans ma première liste déroulante, un autre numéro "2" entouré en rouge apparaît. Là il y a une erreur, je clique dessus et voici ce que cela me dit:

No route found for "POST /gestionzonestechniquesconformites/ajouter": Method Not Allowed (Allow: GET, HEAD)

voici ma twig avec le script:

<form action="{{ path('ajouterZonesConformites_process') }}" method="POST">
          <div class="row">
            <div class="col-md-6">
              <div>
                {{ form_errors(form) }}
              </div>
              <div>
                {{ form_label(form.parcsimmobilier, "Categorie(s) de la zone technique:", {'label_attr': {'class': 'control-label'}}) }}
                {{ form_errors(form.parcsimmobilier) }}
                {{ form_widget(form.parcsimmobilier, {'attr': {'class': 'form-control', 'id': 'parcsimmobilier',   'onChange':'remplirEnsembles();'}}) }}
              </div>
              <div>
                {{ form_label(form.ensembles, "Categorie(s) de la zone technique:", {'label_attr': {'class': 'control-label'}}) }}
                {{ form_errors(form.ensembles) }}
                {{ form_widget(form.ensembles, {'attr': {'class': 'form-control', 'id': 'ensembles'}}) }}
              </div>
              <div>
                {{ form_label(form.batiments, "Appartenant au bâtiment:", {'label_attr': {'class': 'control-label'}}) }}
                {{ form_errors(form.batiments) }}
                {{ form_widget(form.batiments, {'attr': {'class': 'form-control'}}) }}
              </div>
              <br>
              <div>
                {{ form_label(form.categorieszonestechnique, "Categorie(s) de la zone technique:", {'label_attr': {'class': 'control-label'}}) }}
                {{ form_errors(form.categorieszonestechnique) }}
                {{ form_widget(form.categorieszonestechnique, {'attr': {'class': 'selectpicker categories'}}) }}
              </div>
              <br>
              <div>
                {{ form_label(form.nom, "Nom de la zone technique:", {'label_attr': {'class': 'control-label'}}) }}
                {{ form_errors(form.nom) }}
                {{ form_widget(form.nom, {'attr': {'class': 'form-control'}}) }}
              </div>
              <br>
              <div>
                {{ form_label(form.localisation, "Localisation de la zone:", {'label_attr': {'class': 'control-label'}}) }}
                {{ form_errors(form.localisation) }}
                {{ form_widget(form.localisation, {'attr': {'class': 'form-control'}}) }}
              </div>
              <br>
              <div>
                {{ form_label(form.commentaire, "Ajouter un commentaire:", {'label_attr': {'class': 'control-label'}}) }}
                {{ form_errors(form.commentaire) }}
                {{ form_widget(form.commentaire, {'attr': {'class': 'form-control'}}) }}
              </div>
              <br>
            </div>
          </div>
          {# valiDation #}
          <br>
          <div class="row">
            <div class="clo-md-4"></div>
              <input onclick="clear_form_elements(this.form)" type="reset" value="Vider les champs" class="btn btn-xs btn-default"/>
            </div>
            <br>
            <div class="clo-md-4"></div>
              <input type="submit" value="Ajouter" class="btn btn-small btn-success"/>
            </div>
          </div>
        </form>
      </div>
    </div>
    <script type="text/javascript">function remplirEnsembles(){
        var id_select = $('#myspace_databasebundle_zonestechnique_parcsimmobilier').val();
          $.ajax({
            url: "{{ path('ajouterZonesConformites') }}",
            type: 'POST',
            data: {'id': id_select},
            dataType: 'json',
            success: function(json){ // quand la réponse de la requete arrive
              $('#myspace_databasebundle_zonestechnique_ensembles').html('');
              $.each(json, function(index, value) { // et  boucle sur la réponse contenu dans la variable passé à la function du success "json"
              $('#myspace_databasebundle_zonestechnique_ensembles').append('<option value="'+ value.id +'">'+ value.nom +'</option>');
              });
            }
          });
      }
    </script>

J'espère que vous pourrez m'éclairer sur comment réellement faire une requête Ajax, je pense que mon code doit avoir besoin de sérieuses modifications à ce niveau là.

Mais je me demande vraiment si je fais bien:
j'ai une méthode pour remplir le formulaire avec sa route correspondante (route Ajax). J'appelle le formulaire sur la méthode pour valider l'ajout d'une nouvelle zone technique. Ma méthode pour valider ce formulaire comprend 2 routes: une pour afficher en GET le formulaire, et une en POST pour soumettre et valider mes données.

11 réponses


dev_julien
Auteur
Réponse acceptée

@shadoo, j'ai trouvé ma solution hier, elle fonctionne. Je n'ai pas essayé les event listenner de Symfony, ça compliquait les choses vu que j'ai trois select dans mon formulaire avec au moins deux dépendances. Le deuxième dépend du premier, le troisième du deuxième. Tout fonctionne même à la validation.
Je vous explique la démarche:

  • tout d'abord le formulaire, que ce soit au niveau de ma vue Twig ou de mon formType (collection), le code reste inchangé, c'est le même.
  • j'ai ensuite créer ma méthode d'ajout qui fait appel au formulaire que vous pouvez aussi voir plus haut, c'est la même chose.
  • J'ai ensuite créer une méthode qui implémente Ajax en stipulant bel et bien que c'est uen route, voici le code:

    /**
     *
     * @Route("/gestionzonestechniquesconformites/ajouterEnsemblesformulaire", name="formulaireEnsemblesZones")
     * @Method("get")
     */
    public function formulaireEnsemblesZonesAction() {
    
        $request = $this->getRequest();
        $em = $this->getDoctrine()->getEntityManager();
    
        if($request->isXmlHttpRequest()) { // pour vérifier la présence d'une requete Ajax
    
            $id = '--selectionnez un parc--';
            $id = $request->get('id');
    
                if ($id != '--selectionnez un parc--') {
    
                    $ensembles = $em->getRepository('MySpaceDatabaseBundle:Ensembles')->getEnsembles($id);
    
                    $tabEnsembles = array();
                    $i = 0;
    
                        foreach($ensembles as $e) { // transformer la réponse de la requete en tableau qui remplira le select pour ensembles
                            $tabEnsembles[$i]['id'] = $e->getId();
                            $tabEnsembles[$i]['nom'] = $e->getNom();
                            $i++;
                        }
    
                    $response = new Response();
    
                    $data = json_encode($tabEnsembles); // formater le résultat de la requête en json
    
                    $response->headers->set('Content-Type', 'application/json');
                    $response->setContent($data);
    
                    return $response;
                }
    
        } else {
    
            return new Response('et BIM ça plante');
        }
    }

    Ce que vous pouvez noter ici, c'est la requête isXmlHttpRequest() ainsi que la méthode du repository getEnsembles($id) dont voici le code (attention de bien renseigné votre entité pour doctrine, afin qu'il comprenne bien que le repository est à votre entité):

    public function getEnsembles($id)
    {
        $q = $this->_em->createQuery("SELECT e FROM MySpaceDatabaseBundle:Ensembles e JOIN MySpaceDatabaseBundle:Parcsimmobilier p WITH e.parcsimmobilier = :id");
        $q->setParameter('id',$id);
        return $q->getResult();
    }

    A ce niveau là, je fais juste un select sur ensembles afin de dire à doctrine de me renvoyer les résultats suite à mon premier select, cela reviendrait à faire un select basique en SQL pour afficher le nom des ensembles appartenant à un parc immobilier. Attention toutefois de ne pas mettre ON mais bien WITH dans votre DQL, en effet, je vous renvoit sur la doc de doctrine, mais Un ON et un WITH sont différents de ce que l'on peut avoir sur une reqûte SQL basique. De toutes manière, doctrine couinera si votre reqûete dans votre repository est mal renseigné ou mal faite.

  • Et pour finir, j'appel le script en ajax dans la vue correspondante du formulaire. Le scrip est le même que poster auparavant, juste n'oublier pas de préciser que l'url du script est celle la route de la méthode où l'on fait la requête isXmlHttpRequest(), sinon ajax fonctionnera pas et ne vous enverra pas d'erreur, tout comme moi.

Si vous avez des questions, hésitez pas à me contacter sur le site, ou même sur ce forum, je me ferai un plaisir de vous aidez. Ajax n'a pas d'implémentation type ou de procédure stricte pour le mettre en place, c'est pour ça que la première requête Ajax est la plus difficile.

@shadoo, FuelPHP c'est bien? J'ai bossé sur Laravel, je trouve ce framework assez cool d'ailleurs.

Merci en tout cas à toutes vos interventions.

Hey :)

openclassrooms.com/courses/developpez-votre-site-web-avec-le-framework-symfony2/creer-des-formulaires-avec-symfony2#r-2087564
(j'ai mis l'id en encre pour que tu trouves de suite)

Sur ce tuto, il explique comment jouer avec ses données et avec ajax en même temps, donc une piste possible !
J'espère que tu peux en tirer une piste.

Merci pour ton intervention, j'avais déjà fouiller sur le tuto du SDZ avant de poster ce topic. Là il s'agit d'ajouter et supprimer des catégories à la pelle, c'est pas tout à fait ce que je veux, mais je m'en inspire ne t'inquiète pas.

J'y voyais plus une méthode d'intégration d'Ajax dans un formulaire. Je sais que tu ne veux ni supprimer ajouter ou faire un array grâce a l'Ajax:D

Ouais du coup, quand je debug (inspecter l'élément sur le navigateur) et que je vais dans l'onglet network, ma requête Ajax me renvoit bien l'id de mon parcsimmobilier, donc je pense qu'elle est bien incorporé, du moins qu'elle fait son job. J'avance là, dès que j'en sais plus, je viendrai poster ici. Me reste plus qu'à afficher mes données dynamiquement. Merci ;)

Salut julien,
je pense que tu as un problème au niveau de ta declaration de la méthode de la route : tu as déclaré la méthode ajouterZonesConformitesAction() de type @method('post') or que dans le fichier route elle est en _method: GET, c'est pour ça que tu as l'erreur, de plus tu n'as pas besoin de déclarer "route" ou la "method" dans les deux fichiers. J'espère que ça pourra au moins régler ce bug.

@Julio; merci pour ta suggestion. En fait, en recopiant mon code j'ai fait une erreur. Dans mon projet, j'ai bien déclaré une seule fois la route sur la méthode qui affiche le formulaire pour le valider. J'ai essayé en post et en get (tout est déclaré de la même façon quand c'est en GET ou en POST), mais toujours pareil. Impossible d'afficher dynamiquement mes données. Je vais modifié mon premier post ainsi vous verrez mieux par vous même.

J'ai corrigé mon code, donc maintenant je suis en POST partout concernant la route Ajax. Toutefois, dans la SymfonyToolBar, je vois bien que je n'ai pas d'erreur (tout est vert) et quand je fais inspecter l'élément, dans l'onglet network, j'ai bien ma reqête lancé. Par contre côté client, rien ne se passe (pas d'affichage dynamique).

Dois-je créer une route différente pour afficher le formulaire et pour le remplir ?
Pour afficher un ensemble de champs de formulaire en Ajax selon l'élément que l'on selectionne, OUI c'est mieux en terme d'organisation.
On peut créer un service mais cela dépend concrètement du nombre de formulaire de de template de champs que tu intègres. J'avais bossé sur un gros site avec que des formulaires dynamiques, la plus part étaient un affichage conditionnel de groupes de champs en javascript, mais pour les autres il vallait mieux utiliser une insertion via les requêtes ajax, tout en sachant que certain groupe de champs intégré en ajax pouvais aussi s'ajouter en groupe de champs multiples.

Tu sélectionnes l'élément, via cet élément tu l'envoies en requête GET (ou post selon le choix mais pas obligatoire) en Ajax à une route de controller qui s'occupera d'afficher le template Twig en adéquation. (voir d'autres paramètres envoyé en url si besoin).

comment cela fonctionne t-il réellement<un espace avant le point d'interrogation>?
<Formulaire page HTML avec collection de champs appelé via l'url> => <On selectionne un item en fonction d'un évènement sur un input ou selection qui envoie une requête get à la méthode d'un controller> => <La methode de ce controller se chargera de renvoyer le template de champs que l'on souhaite renvoyer On ne renvoie pas le retour en JSON mais bien du contenu HTML>

Tu renvois le retour du contenu en json seulement si tu as plusieurs variables et inerractions nombreuses que tu devras manipuler, dans ces cas là tu stockers ta view Twig dans une variable que tu renverras en json par exemple, de ce fait tout ton template de view de collection de champs se trouver dans une variable json, ce qui te laisse l'avantage de pouvoir attribuer d'autres variables json en retour que tu pourras exploiter.

C'est comme cela qu'il faut faire<espace avant le point d'interrogation>?
Oui tu peux le faire comme ça.
Exemple:

  • Une route pour afficher la page avec son formulaire, donc une requête HTTP de type GET
  • Une route différente (donc méthode) pour traiter le formulaire en POST (on peut très bien traiter dans la même méthode, mais si tu as beaucoup de traitement il vaut mieux utiliser une autre route et méthode pour la validation car si non tu auras une méthode avec bien trop de code dedans)
  • Et une route en GET (si tu le souhaites) qui s'occupera de populer le contenu de ton formulaire avec de nouveaux champs ou autres. Dans ce cas là la validation de ces nouveaux champs devra être instancier afin de prendre en compte leur validation yaml ou php.

Pour l'erreur que cela t'affichait No route found for "POST /gestionzonestechniquesconformites/ajouter": Method Not Allowed (Allow: GET, HEAD)
C'est que tu appelais une requête en post alors que ta route attends une requête de type GET dans les entêtes.

@shadoo, merci pour ton intervention. Comme tu as pu le constater, j'ai modifié mon code suivant les suggestions que l'on a pu me faire sur mon post.

j'ai donc créer un formulaire dont voici le code:

// FormType Components
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
use Doctrine\ORM\EnsemblesRepository;
use Doctrine\ORM\ParcsimmobilierRepository;
use Doctrine\ORM\BatimentsRepository;

class ZonestechniqueType extends AbstractType
{
    /* @param FormBuilderInterface $builder
     * @param array $options
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('parcsimmobilier', 'entity', array(
                                    'mapped' => false,
                                    'class'    => 'MyspaceDatabaseBundle:Parcsimmobilier',
                                    'property' => 'nom',
                                    'empty_value' => '-- sélectionner un parc --',
                                    'label'    => 'Choisir le parc immobilier : ',
                                    'multiple' => false,
                                    ))
            ->add('ensembles', 'entity', array(
                                    'mapped' => false,
                                    'multiple' => false,
                                    'class'    => 'MyspaceDatabaseBundle:Ensembles',
                                    /*'query_builder' => function(EntityRepository $er) {
                                        return $er->createQueryBuilder('e')
                                                  ->join('e.parcsimmobilier','p');
                                    },*/
                                    'property' => 'nom',
                                    'empty_value' => '-- sélectionner un ensemble --',
                                    'label'    => 'Choisir l\'ensemble : ',
                                    ))
            ->add('batiments','entity', array(
                                    'class'    => 'MyspaceDatabaseBundle:Batiments',
                                    /*'query_builder' => function(EntityRepository $er) {
                                        return $er->createQueryBuilder('b')
                                                  ->join('b.ensembles','e');
                                    },*/
                                    'property' => 'nom',
                                    'empty_value' => '-- sélectionner un batiment --',
                                    'label'    => 'Choisir un batiment : ',
                                    ))
            ->add('categorieszonestechnique')
            ->add('nom')
            ->add('localisation')
            ->add('commentaire')
            ;
    }

    /**
     * @param OptionsResolverInterface $resolver
     */
    public function setDefaultOptions(OptionsResolverInterface $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => 'Myspace\DatabaseBundle\Entity\Zonestechnique'
        ));
    }

    /**
     * @return string
     */
    public function getName()
    {
        return 'mySpace_databasebundle_zonestechnique';
    }
}

Quand je l'affiche, bien entendu aucune erreur de ce côté tout fonctionne parfaitement.
J'ai ensuite deux méthodes dans mon controller. La première pour la requête Ajax que voici:

nction formulaireZonesAction() {

        $request = $this->getRequest();
        $em = $this->getDoctrine()->getEntityManager();

        if($request->isXmlHttpRequest()) { // pour vérifier la présence d'une requete Ajax

            $id = '';
            $id = $request->get('id');

                if ($id != '') {

                    $ensembles = $em->getRepository(MySpaceDatabaseBundle:Ensembles')
                                    ->getEnsemblesByParcsimmobilierQueryBuilder($id);

                    $tabEnsembles = array();
                    $i = 0;

                        foreach($ensembles as $ensemble) { // transformer la réponse à ta requete en tableau qui replira le select pour ensembles

                            $tabEnsembles[$i]['id'] = $ensemble->getId();
                            $tabEnsembles[$i]['nom'] = $ensemble->getNom();
                            $i++;
                        }

                    $response = new Response();

                    $data = json_encode($tabEnsembles); // formater le résultat de la requête en json

                    $response->headers->set('Content-Type', 'application/json');
                    $response->setContent($data);

                    return $response;
                }

        } else {

            return new Response('et BIM ça plante');
        }
    }

et la deuxième pour afficher le formulaire et gérer l'ajout d'une zone technique:

//METHODE pour AJOUTER Zonestechniques et ses conformités
    public function ajouterZonesConformitesAction() {

        $em=$this->getDoctrine()->getManager();
        $zones = $em->getRepository('MySpaceDatabaseBundle:Zonestechnique');

        $zones = new Zonestechnique;
        $form=$this->createForm(new ZonestechniqueType(), $zones);
        $request = $this->getRequest();

            if($request->isMethod('POST') | $form->isValid()) {

                $form->bind($request);
                $zoneConformite = $form->getData();

                $em->persist($zones);
                $em->flush();

                return $this->redirect($this->generateUrl('indexRechercheZones'));
            }

            //retourner le formulaire d'ajout si c'est invalide
            else {
                    return $this->render('MySpaceGestionEquipementsTechniquesBundle:ZonesTechnique:ajouterZonesTechniqueConformites.html.twig', array('form' => $form->createView(), 'zone' => $zones ));
                }
    }

donc pour l'instant de cecôté je n'ai aucune erreur côté client, et même sans parler de la requête Ajax, mon formulaire ajoute bien mes données dans mon entité quand je le valide.
J'ai donc 3 route dans mon routing file, une pour afficher le formulaire en GET, une autre pour la méthode Ajax en GET, et la dernière pour gérer l'ajout des données (validation du formulaire):

ajouterZonesConformites:
    path:     /gestionzonestechniquesconformites/ajouter
    defaults: { _controller: MySpaceGestionEquipementsTechniquesBundle:GestionZonesTechniques:ajouterZonesConformites }
    requirements:
    methods: GET

#Ajax
formulaireZones:
    pattern:  /gestionzonestechniquesconformites/ajouterformulaire
    defaults: { _controller: MySpaceGestionEquipementsTechniquesBundle:GestionZonesTechniques:formulaireZones }
    requirements:
    methods: GET

ajouterZonesConformites_process:
    path:     /gestionzonestechniquesconformites/ajouter/process
    defaults: { _controller: MySpaceGestionEquipementsTechniquesBundle:GestionZonesTechniques:ajouterZonesConformites }
    requirements:
    methods: POST

Pour le routing pareil, tout fonctionne, je ne pense pas me tromper, je veux dire par là que quand je debug avec la symfony toolbar ou même en ligne de commande, toutes mes routes sont bonnes (elles matchent bien avec ce que j'attends d'elle).
J'appelle bien ma méthode en GET pour ce qui est d'Ajax et l'affichage du formulaire.
Toutefois, lorsque je suis sur la page du formulaire et que je selectionne un parc dans mon premier select, dans la symfony toolbar ou même l'onglet network tout se passe bien, aucunes erreur. Rien ne se produit. Peut être que l'erreur vient du côté php. Je ne sais vraiment pas là.
Voici mon repository pour EnsemblesRepository.php:

class EnsemblesRepository extends EntityRepository
{
    public function getEnsemblesByParcsimmobilierQueryBuilder($id)
    {
        return $this
          ->createQueryBuilder('e')
          ->where('e.parcsimmobilier = :parcsimmobilier')
        ->setParameter('id', $id);
        ;
    }
}

C'est la requ^te que j'appelle dans ma méthode Ajax de mon controller.
Ensuite voici ma vue:

 <form action="{{ path('ajouterZonesConformites_process') }}" method="POST">
          <div class="row">
            <div class="col-md-6">
              <div>
                {{ form_errors(form) }}
              </div>
              <div>
                {{ form_label(form.parcsimmobilier, "choisir un parc", {'label_attr': {'class': 'control-label'}}) }}
                {{ form_errors(form.parcsimmobilier) }}
                {{ form_widget(form.parcsimmobilier, {'attr': {'class': 'form-control', 'id': 'parcsimmobilier',   'onChange':'remplirEnsembles();'}}) }}
              </div>
              <div>
                {{ form_label(form.ensembles, "choisir un ensemble:", {'label_attr': {'class': 'control-label'}}) }}
                {{ form_errors(form.ensembles) }}
                {{ form_widget(form.ensembles, {'attr': {'class': 'form-control', 'id': 'ensembles'}}) }}
              </div>
              <div>
                {{ form_label(form.batiments, "Appartenant au bâtiment:", {'label_attr': {'class': 'control-label'}}) }}
                {{ form_errors(form.batiments) }}
                {{ form_widget(form.batiments, {'attr': {'class': 'form-control'}}) }}
              </div>
              <br>
              <div>
                {{ form_label(form.categorieszonestechnique, "Categorie(s) de la zone technique:", {'label_attr': {'class': 'control-label'}}) }}
                {{ form_errors(form.categorieszonestechnique) }}
                {{ form_widget(form.categorieszonestechnique, {'attr': {'class': 'selectpicker categories'}}) }}
              </div>
              <br>
              <div>
                {{ form_label(form.nom, "Nom de la zone technique:", {'label_attr': {'class': 'control-label'}}) }}
                {{ form_errors(form.nom) }}
                {{ form_widget(form.nom, {'attr': {'class': 'form-control'}}) }}
              </div>
              <br>
              <div>
                {{ form_label(form.localisation, "Localisation de la zone:", {'label_attr': {'class': 'control-label'}}) }}
                {{ form_errors(form.localisation) }}
                {{ form_widget(form.localisation, {'attr': {'class': 'form-control'}}) }}
              </div>
              <br>
              <div>
                {{ form_label(form.commentaire, "Ajouter un commentaire:", {'label_attr': {'class': 'control-label'}}) }}
                {{ form_errors(form.commentaire) }}
                {{ form_widget(form.commentaire, {'attr': {'class': 'form-control'}}) }}
              </div>
              <br>
            </div>
          </div>
          {# valiDation #}
          <br>
          <div class="row">
            <div class="clo-md-4"></div>
              <input onclick="clear_form_elements(this.form)" type="reset" value="Vider les champs" class="btn btn-xs btn-default"/>
            </div>
            <br>
            <div class="clo-md-4"></div>
              <input type="submit" value="Ajouter" class="btn btn-small btn-success"/>
            </div>
          </div>
        </form>

et le script pour ajax qui l'accompagne:

<script type="text/javascript">
      function remplirEnsembles(){
        var id_select = $('#mySpace_databasebundle_zonestechnique_parcsimmobilier').val();
        alert(id_select)
          $.ajax({
            url: "{{ path('ajouterZonesConformites') }}",
            type: 'GET',
            data: {'id': id_select},
            dataType: 'json',
            success: function(json){ // quand la réponse de la requete arrive
              $('#mySpace_databasebundle_zonestechnique_ensembles').html('');
              $.each(json, function(index, value) { // et  boucle sur la réponse contenu dans la variable passé à la function du success "json"
              $('#mySpacer_databasebundle_zonestechnique_ensembles').append('<option value="'+ value.id +'">'+ value.nom +'</option>');
              });
            }
          });
      }
    </script>

Donc au final, je ne sais vraiment comment debugger tout ça, puisque de mon côté tout paraît fonctionner, sauf que je n'ai pas ce que je souhaite, c'est à dire peuplé mon deuxième select par rapport au premier. L'id de parcsimmobilier m'est bien renvoyé. Ma méthode de mon repository est peut être fausse. J'en sais rien, donc je test d'autres choses, j'essaie de corriger, mais pour l'instant rien de nouveau.

Tu n'as aucune erreur qui apparait en retour dans ton firebug ou autre ?
Je n'ai plus mes développements de symfony2 sous la main depuis le crash de mon pc (il faudra que je les retrouves) vue que je bosse surtout sous FuelPHP et Laravel depuis un an mon souvenir d'imbrication et de repopulation des formulaires multiples remonte un peu...
Avant de vouloir repeupler des champs selects en ajax plutôt que javascript il faut se demande deux choses :

  • Est ce que mes collections de type input seront variable et injecter dans d'autres formulaire selon d'autres valeurs sélectionnés ?
  • Est ce que mes selects multiples contiennent beaucoup d'éléments à afficher ?

Si cela ne rempli pas ces deux clauses on peut tout à fait passer par du javascript et champs cachés.
Concernant le repeuplement en ajax j'étais passé pour cette procédure sous symfony2 : [http://symfony.com/fr/doc/current/cookbook/form/dynamic_form_modification.html#generation-dynamique-pour-formulaire-soumis]()
Sur certain formulaire, au départ cela ne figurait pas dans la doc.
Là comme ça sans visuel et sans retour d'erreur c'est un peu compliqué de dépister le problème.