[ajax] listes liées

J'ai utilisé la méthode exposée dans le tuto https://siddh.developpez.com/articles/ajax/#LIV-A
mais j'ai transposé à une table tb_pays et une table tb_ville....

j'ai beau cherché l'erreur, ma seconde liste est toujours vide quand je choisis un pays....
<?php include("haut.php") ; // contient la connexion avec la base ?>
<div id="corps">
		<script type='text/javascript'>
			var xhr = null; 
	 
			function getXhr(){
				if(window.XMLHttpRequest) // Firefox et autres
				   xhr = new XMLHttpRequest(); 
				else if(window.ActiveXObject){ // Internet Explorer 
				   try {
			                xhr = new ActiveXObject("Msxml2.XMLHTTP");
			            } catch (e) {
			                xhr = new ActiveXObject("Microsoft.XMLHTTP");
			            }
				}
				else { // XMLHttpRequest non supporté par le navigateur 
				   alert("Votre navigateur ne supporte pas les objets XMLHTTPRequest..."); 
				   xhr = false; 
				} 
			}
			
			/**
			* Méthode qui sera appelée sur le click du bouton
			*/
			function go(){
				getXhr();
				// On défini ce qu'on va faire quand on aura la réponse
				xhr.onreadystatechange = function(){
					// On ne fait quelque chose que si on a tout reçu et que le serveur est ok
					if(xhr.readyState == 4 && xhr.status == 200){
						leselect = xhr.responseText;
						// On se sert de innerHTML pour rajouter les options a la liste
						document.getElementById('ville').innerHTML = leselect;
					}
				}

				// Ici on va voir comment faire du post
				xhr.open("POST","ajaxville.php",true);
				// ne pas oublier ça pour le post
				xhr.setRequestHeader('Content-Type','application/x-www-form-urlencoded');
				// ne pas oublier de poster les arguments
				// ici, l'id du pays
				sel = document.getElementById('pays');
				idpays = sel.options[sel.selectedIndex].value;
				xhr.send("id_pays="+idpays);
			}
		</script>
		<form>
			<fieldset>
				<legend>lieux:</legend>
				<label>pays</label>
				<select name='pays' id='pays' onchange='go()'>
					<option value='-1'>Aucun</option>
					<?
						$res = mysql_query("SELECT * FROM tb_pays ORDER BY id_pays");
						while($row = mysql_fetch_assoc($res)){
							echo "<option value='".$row["id_pays"]."'>".$row["pays"]."</option>";
						}
					?>
				</select>
				<label>ville</label>
				<div id='ville' style='display:inline'>
				<select name='ville'>
					<option value='-1'>Choisir un pays</option>
				</select>
				</div>
			</fieldset>
		</form>
	</div>
	
<?php include("bas.php") ?>


et le fichier ajaxville.php
<?php
	echo "<select name='ville'>";
	if(isset($_POST["id_pays"])){
		$id_pays = $_POST["id_pays"];
		mysql_connect("localhost","root","");
		mysql_select_db("base_setlist");
		$res = mysql_query("SELECT * FROM tb_ville WHERE id_pays = $idpays ORDER BY ville");
		while($row = mysql_fetch_assoc($res))
		{
			echo "<option value='".$row["id_ville"]."'>".$row["ville"]."</option>";
		}
	}
	echo "</select>";
?>


merci:D

36 réponses

Résumé de la discussion

Problème central : la mise à jour d'une liste déroulante dépendante (ville) après le choix d'un pays via AJAX dans un exemple utilisant tb_pays et tb_ville. La cause fréquente est une incohérence de nom de variable dansajaxville.php, où la requête utilise idpays au lieu de id_pays, ce qui empêche la condition WHERE d'accéder aux lignes correspondantes. La correction consiste à utiliser le même nom de variable (id_pays) dans la requête et à s'assurer que la valeur envoyée via POST est id_pays, afin que la liste des villes se remplisse. En outre, vérifier que le script renvoie bien des options HTML et que la liste « ville » ne soit pas remontée à vide après remplacement par innerHTML.

Bobot (l’IA à votre service)
  1. il n'y a rien a télécharger

    le principe d'AJAX:
    - sur un evenement (un onChange d'une liste par ex) on appelle une fonction Javascript/ajax

    qui va en arrière plan, sans recharger la page, appeler un script php sur le serveur en lui passant la valeur selectionnées ds la liste1

    - ce script va lire ds la BDD et genrer une liste2 et l'envoyer en réponse à Ajax

    - à la réception de la réponse, Ajax va écrire la liste par innerHTML dans un div de ta page

    <html>
    <head>
    <script type="text/javascript">
    //fonction AJAX
    //partie envoie de la requette, cette fct est appelée sur le onChange de la liste1
    function makeRequest(url,id_lire,id_ecrire){
     var http_request = false;
      //créer une instance (un objet) de la classe désirée fonctionnant sur plusieurs navigateurs
            if (window.XMLHttpRequest) { // Mozilla, Safari,...
                http_request = new XMLHttpRequest();
                if (http_request.overrideMimeType) {
                    http_request.overrideMimeType('text/xml');//un appel de fonction supplémentaire pour écraser l'en-tête envoyé par le serveur, juste au cas où il ne s'agit pas de text/xml, pour certaines versions de navigateurs Mozilla
                }
            } else if (window.ActiveXObject) { // IE
                try {
                    http_request = new ActiveXObject("Msxml2.XMLHTTP");
                } catch (e) {
                    try {
                        http_request = new ActiveXObject("Microsoft.XMLHTTP");
                    } catch (e) {}
                }
            }
    
            if (!http_request) {
                alert('Abandon :( Impossible de créer une instance XMLHTTP');
                return false;
            }
            http_request.onreadystatechange = function() { traitementReponse(http_request,id_ecrire); } //affectation fonction appelée qd on recevra la reponse
      // lancement de la requete
      http_request.open('POST', url, true);
      //changer le type MIME de la requête pour envoyer des données avec la méthode POST ,  !!!! cette ligne doit etre absolument apres http_request.open('POST'....
      http_request.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
      obj=document.getElementById(id_lire); //on vient lire la valeur selectionnée ds la liste1
      data="localisation="+obj.value; //on envoie la valeur au script php en POST
            http_request.send(data);
    }
    
    //partie traitement de la réponse
    function traitementReponse(http_request,id_ecrire) {
     //qd on recoit la reponse:
     if (http_request.readyState == 4) {
      if (http_request.status == 200) {
         // cas avec reponse de PHP en mode texte:
       var reponse=http_request.responseText;
       //alert(reponse); //TEST
       
       // on va ecrire la réponse, c a d la liste2 dans le div qui a pour id  id_ecrire
       var obj=document.getElementById(id_ecrire);
        obj.innerHTML=reponse;
      } 
      else {
                    alert('Un problème est survenu avec la requête.');
            }
        }
    }
    </script>
    </head>
    <body>
    <table>
    <td align="center" style="border:2px solid">
    <form action='result-affaire.php' method='POST'>
    <select name="localisation" id="id_liste1" onChange="makeRequest('reponsePhpAjax.php','id_liste1','id_div_liste2');">
    //on appelle la fct sur le onChange en lui passant l'url du script php appelé,l'id de la liste 1, l'id ou iol faut ecrire la réponse
    <?php
    
    $sql='SELECT Localisation FROM affaire';
    $list=mysql_query($sql) or die("Erreur de connexion au serveur SQL");
    echo'<option>Sélectionnez la localisation</option>';
    while ($data = mysql_fetch_array($list)){
     echo'<option value='.$data['*'].'>'.$data['Localisation'].'</option>';
    }
    ?>
    </select>
    <p></p>
    <input type="submit" name="affcicher" value="Afficher">
    </form>
    </td>
    </table>
    <div id="id_div_liste2"><!-- c'est la que par innerHTML AJAX va ecrire la liste2 --></div>
    
    //ce n'est pas le script result-affaire.php  qu'il faut appeler mais par exemple reponsePhpAjax.php
    
    </body>
    </html>
    


    le code de reponsePhpAjax.php:
    <?php
     //recup de la valeur passée par Ajax, valeur selectionnée dans la liste 1
     $localisation=$_POST['localisation'];
     //connexion bdd
     mysql_connect......
     mysql_select_db.....
     //requette
     $sql="SELECT * FROM affaire WHERE Localisation='$localisation';";
     $list=mysql_query($sql) or die("Erreur de connexion au serveur SQL");
     $reponse='<select name="nom_affaire">';
     $reponse.='<option>Sélectionnez le nom de l affaire</option>';
     while ($data = mysql_fetch_array($list)){
      $reponse.='<option value='.$data['idAffaire'].'>'.$data['NomAff'].'</option>';
    
     }
     $reponse.='</select>';
    
     //on envoie la reponse, c'est a dire la liste complete ainsi generée à AJAX
     echo $reponse;
    ?>
    
    1. Bonjour,

      Je viens de mettre en ligne un tuto pour résoudre le problème avec du XHR :
      http://www.denisbillo.com/fr/informatique/php-listes-liees-select.php
      1. Bonjour

        Je cherche désespérement à faire 3 listes liées à partir d'une base de donnée qui comporte les champs suivants :
        marque, type, contenu et au final si on envoi que cela affiche tous les vehicules de la marque , type et contenu séléctionné
        Voila si je pouvais avoir un peu d'aide et de votre temps
        vincent.roye super ton site avec les 3 menu c'est exactement le principe que je recherche avec au final l'affichage des articles qui correspondent
        Si une petite archive pouvait être mises à disposition ou transcrit :)
        Merci d'avance
        1. Salut,

          Vous pouvez lire mon post à ce sujet sur mon site, il y a un exemple de 3 listes liées et rafraichies avec Ajax.
          http://www.vincentroye.com/?p=339
          Continent -> Country -> City
          Simple et intuitif ;)

          Cordialement,

          Vincent Roye.
          1. Si tu est inscript sur le forum tu dois pouvoir m'envoyer un mail en MP avec ton adresse, comme ça on pourra envoyer les scripts en pièce jointe.

            Enfin si tu es ok pour ça
            1. Non je ne suis pas inscrit c'est pour ça ^^

              sinon mon adresse c'est celle qui suit : kuro point koara mailto hotmail point france

              ^^
          2. Non je ne pense pas qu'il y ait confusion seulement "Localisation" est non seulement une occurence de ma table AFFAIRE, mais aussi le nom de ma premiere liste c'est pour ça, je pensais que ça venait de la, et qu'il fallait aussi integrer ma deuxieme liste au script.

            Merci de m'avoir appris ce que ça signifiait ^^ et ça me dit toujours que ce n'est pas définit... en parlant de : la seconde liste que j'ai reprise en POST, et de l'occurence villeAffaire
            1. concernant Ajax:



              data="Localisation="+obj.value; //Envoi de la valeur au script PHP en 'POST'
              http_request.send(data);


              envoie la valeur selectionnée dans la liste2

              et dans le script php appelé tu récupères par $nom_affaire=$_POST['Localisation'];

              mais je n'y a -t-il pas de confusion entre nom affaire et localisation affaire ?
              1. quand php indique une erreur en fin de script c'est qu'il manque une }

                c'était bien le cas:

                <?php
                
                 $user="root";
                 $host="localhost";
                 $bdd="terawatt2";
                 mysql_connect($host,$user) or die("Erreur de connexion au serveur SQL");
                 mysql_select_db($bdd);
                
                 $NomAff=$_SESSION['Localiser'];
                //recherche de la ville en fct du choix liste 2
                 $sql_local="SELECT * FROM affaire WHERE nomAffaire='.$NomAff[nomAffaire].' AND villeAffaire='.$NomAff[villeAffaire].';"; 
                $list_local=mysql_query($sql_local) or die("Erreur de connexion au serveur SQL 4");
                //il doit y en avoir qu'une ?
                $donnee_loc=mysql_fetch_array($list_local);
                $localisation=$donnee_loc['Localisation']; //la ville
                //on genere la liste entière avec un select sur la ville ci dessus
                	$sql2="SELECT * FROM affaire";
                	$result2=mysql_query($sql2) or die("Erreur de connexion au serveur SQL 4");
                 $liste='<select>';
                 while ($donnees_liste = mysql_fetch_array($result2))
                 {
                 $liste.='<option value='.$donnees_liste['Localisation'].'';
                 if($donnees_liste['Localisation'] == $localisation){ $liste.=' selected';} //la ville est preselectionnée
                 $liste.= ' >'.$donnees_liste['Localisation'].'</option>';
                 } //il manquait cette accolade
                 $liste.='</select>';
                 echo $liste;
                 ?> 
                
                1. Désolé je n'arrive pas a trouver pour editer le post, mais cela ne viendrait pas de là (de ce morceau de script) ?
                  1. Oui en fait la ligne 18 etait inutile du coup je l'ai virée, et j'ai essayé les session, parce qu'avec post je n'avais pas de resultat non plus donc c'etait plus pour voir que par interet.

                    Par contre j'ai essayé de reprendre et modifier ton code à ma guise seulement il m'affiche tout le temps une "parse error" a la derniere ligne, alors que tout est niquel :/
                    Ou sinon si j'enleve le morceau de code du while a la fin, il me dit que la variable n'est pas définit, ainsi que les occurences demandées (undefined index "blabla").

                    Je vois aussi que dans le script que tu as fais il y a :
                    if (!http_request)
                    {
                    alert('Abandon :( Impossible de créer un objet XMLHTTP');
                    return false;
                    }
                    //Affectation de la fonction appelée quand on recevra la réponse
                    http_request.onreadystatechange = function()
                    {
                    traitementReponse(http_request,id_ecrire);
                    }
                    // Lancement de la requête
                    http_request.open('POST', url, true);
                    http_request.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
                    obj=document.getElementById(id_lire); //Lecture de la valeur selectionnée dans la liste "Localisation"
                    data="Localisation="+obj.value; //Envoi de la valeur au script PHP en 'POST'
                    http_request.send(data);
                    }
                    1. un petit oubli de ; ligne 18

                      sinon pourquoi utilises tu les sessions alors que tu peux très bien passer plusieurs valeurs par Ajax ?

                      <?php
                      session_start();
                      ?>
                      
                       <?php
                      
                       $user="root";
                       $host="localhost";
                       $bdd="terawatt2";
                       mysql_connect($host,$user) or die("Erreur de connexion au serveur SQL");
                       mysql_select_db($bdd);
                      
                       $NomAff=$_SESSION['Localiser'];
                      
                       $sql_local="SELECT * FROM affaire WHERE nomAffaire='.$NomAff[nomAffaire].' AND villeAffaire='.$NomAff[villeAffaire].';";
                      $list_local=mysql_query($sql_local) or die("Erreur de connexion au serveur SQL 4");
                       $Nom_local='<select>';
                       $Donnees_local = mysql_fetch_array($list_local); //il te manqait le ; 
                       while ($Donnees_local = mysql_fetch_array($list_local))
                       {
                       $Nom_local.='<option value='.$Donnees_local['Localisation'].'>'.$Donnees_local['Localisation'].'</option>';
                       $Nom_local.='</select>';
                       echo $Nom_local;
                       ?> 
                       
                       ou autre solution qui t'affichera toute la liste 1 mais avec la ville selected
                       
                       <?php
                      
                       $user="root";
                       $host="localhost";
                       $bdd="terawatt2";
                       mysql_connect($host,$user) or die("Erreur de connexion au serveur SQL");
                       mysql_select_db($bdd);
                      
                       $NomAff=$_SESSION['Localiser'];
                      //recherche de la ville en fct du choix liste 2
                       $sql_local="SELECT * FROM affaire WHERE nomAffaire='.$NomAff[nomAffaire].' AND villeAffaire='.$NomAff[villeAffaire].';"; 
                      $list_local=mysql_query($sql_local) or die("Erreur de connexion au serveur SQL 4");
                      //il doit y en avoir qu'une ?
                      $donnee_loc=mysql_fetch_array($list_local);
                      $localisation=$donnee_loc['Localisation']; //la ville
                      //on genere la liste entière avec un select sur la ville ci dessus
                      	$sql2="SELECT * FROM affaire";
                      	$result2=mysql_query($sql2) or die("Erreur de connexion au serveur SQL 4");
                       $liste='<select>';
                       while ($donnees_liste = mysql_fetch_array($result2))
                       {
                       $liste.='<option value='.$donnees_liste['Localisation'].'';
                       if($donnees_liste['Localisation'] == $localisation){ $liste.=' selected';} //la ville est preselectionnée
                       $liste.= ' >'.$donnees_liste['Localisation'].'</option>';
                       $liste.='</select>';
                       echo $liste;
                       ?> 
                      1. J'ai enlevé la ligne 18, que j'avais pas vu pour le coup, et du coup j'ai une liste de vide sans erreur ni rien... :/
                        Je comprends vraiment pas.. :/
                        1. J'avoue ne pas voir ce qui cloche, j'ai essayé de plusieurs maniere mais le mieux que j'ai pu avoir est une liste vide...
                          Et maintenant j'ai une parse error a la ligne 19.. :/

                          1 <?php
                          2 session_start();
                          3 ?>

                          5 <?php

                          7 $user="root";
                          8 $host="localhost";
                          9 $bdd="terawatt2";
                          10 mysql_connect($host,$user) or die("Erreur de connexion au serveur SQL");
                          11 mysql_select_db($bdd);

                          13 $NomAff=$_SESSION['Localiser'];

                          15 $sql_local="SELECT * FROM affaire WHERE nomAffaire='.$NomAff[nomAffaire].' AND villeAffaire='.$NomAff[villeAffaire].';";
                          16 $list_local=mysql_query($sql_local) or die("Erreur de connexion au serveur SQL 4");
                          17 $Nom_local='<select>';
                          18 $Donnees_local = mysql_fetch_array($list_local)
                          19 while ($Donnees_local = mysql_fetch_array($list_local))
                          20 {
                          21 $Nom_local.='<option value='.$Donnees_local['Localisation'].'>'.$Donnees_local['Localisation'].'</option>';
                          22 }
                          23 $Nom_local.='</select>';
                          24 echo $Nom_local;
                          25 ?>

                          Et a part la requête qui pourrait peut etre ne pas aller, je ne vois pas d'ou vient le probleme :/
                          A moins qu'il ne faille modifier le script ?
                          1. ha oui je pige

                            liste 1 les noms de ville

                            liste 2 toutes les affaires

                            si on choisi Toulouse dans la liste1 => la liste 2 par ajax n'a plus que les affaire de Toulouse

                            deuxième possibilité

                            si on choisit directement une affaire de Toulouse dans la liste2 Toulouse va apparaitre dans la liste1

                            Alors pour faire ça:

                            tu mets ta liste 1 dans un <div id="id_premiere_liste">

                            tu mets comme je t'ai dit ci dessus une liste 2 dans le div ou Ajax va ecrire plus tard construite avec une boucle while

                            tu lui mets un onChange qui appele la fonction ajax mais cette fois ci en inversant les id passés en arguments lors de l'appel fct

                            ii_lire=id_liste2 id_ecrire=id_premiere_liste

                            cette fonction Ajax va appeler une autre url, un script php qui va lire dans la bdd les villes et mettre selected celle qui correspond

                            c'est un peu compliqué a expliquer mais c'est jouable
                            1. Pour parler plus schématisé je vais dire,j'essaye en fait de faire en sorte que si je choisis directement dans la liste fille que la liste mère se définisse toute seule.

                              Par exemple si dans ma liste 2 j'ai toutes mes "affaires" sans les trier par "Localisation" et que j'en choisisse une de Toulouse, que ça m'affiche directement dans la liste 1 que c'est une affaire de Toulouse.

                              Je sais pas si je me suis bien expliqué ^^'
                              1. pour le premier cas

                                dans ta page tu mets dans le div qui va recevoir la réponse ajax une liste deroulante complete avec une boucle while qui va afficher tous les chargés d'affaire

                                ajax viendra ensuite suite a un choix dans la liste 1 venir écraser cette liste et la remplacer par une qui correspondra seulement au choix fait dans la 1
                                1. en gros ce que tu veux

                                  liste 1

                                  liste 2 tous les enregistrements

                                  qd choix dans liste 1 ça réaffiche la liste 2 mais avec seulement ceux concernés par la liste1

                                  par contre je ne comprend pas trop ce que tu veux faire dans l'autre sens choix liste 2 vers affich liste 1
                                  1. Par contre je n'arrive pas a faire en sorte que si je choisis directement dans ma seconde liste, le résultat de la premiere en soit définit automatiquement ??
                                    J'ai essayé de faire comme suit :
                                    - créer une autre page "reponseAjax" pour cette requête
                                    - j'ai bien mis l'espace <select> de la premiere liste dans un <div> afin que la liste soit remplacée par le résultat en fonction du choix dans la seconde liste

                                    et j'ai regardé le script, ne serait ce pas dans ce code la que je dois changer quelque chose ???
                                    1. Je pensais encore à autre chose, si jamais dans ma deuxieme liste au lieu qu'elle ne s'affiche qu'au moment d'avoir fait un choix dans la premiere. Si elle pouvait s'afficher directement en ayant le choix de tous les nom d'affaires et qu'apres choix, le résultat de la liste 1 s'applique, même si l'on en a pas plus vraiment besoin.
                                      Comment je dois procéder, parce qu'en remplaçant le div par select, cela m'affiche une liste vide donc et surtout qui ne prends pas la nouvelle liste qui est appelée (ce qui est normal ^^). Ou alors changer la forme sous laquelle se présente la requête appelée ???
                                      1. Bonjour,

                                        je suis entrain d'integrer liste liée comportants les champs suivants:

                                        region,departement et ville mon probleme c'est si je choisis n'importe quelle region le champ departement reste vide et meme bien sur champ ville. J'ai cette fonction qui ne retourne pas resultat ça ce que j'ai remarquer, je sais pas si sa rentre a la structure de la bd alors que j'ai fait les champs selon les requetes select, et j'ai pas bien compris le $id c quoi c'est en ajax
                                        je vais vous donner ma fonction qui ne retourne pas resultat

                                        public function getRegionById($id)
                                        {
                                        $prepare = $this->prepare('SELECT region_id, region_name
                                        FROM region
                                        WHERE region_id = "'.$id.'"');
                                        $prepare->execute();
                                        $region = $prepare->fetchAll();

                                        return $region;
                                        }

                                        merci d'avance
                                      2. Bonjour,

                                        je veux integrer un dossier contenant liste liee en ajax mais je sais comment l'integrer sachant que ma liste liee est contenue dans un dossier, lorsque je clique sur ce dossier la liste liee s'affiche mais je sais pas comment mettre cette liste dans dans une page php, c-à-d comment je peux appeler ce dossier, qui contient tout les fichiers pour faire liste liée, dans une page php

                                        prière m'aider
                                      3. Bonjour
                                        je veux savoir comment ajouter un quatrième niveau dans une liste liée comme l'exemple pubilée de region, departement, ville
                                        prière m'aider
                                    2. En effet ça marche beaucoup mieux :) J'avoue avoir quelques difficultés à comprendre l'ajax et tes conseils et explications m'aident beaucoup !

                                      Merci encore
                                      1. J'ai trouvé.... =D
                                      2. Moi j'ai script ajax telecharger pour liste liée, le dexieme niveau depend du premier niveau mon probleme c'est que lorsque je choisie valeur dans le premier champ le deuxieme niveau reste vide.

                                        Comment faire pour que je losrque je choisie valeur dans premier niveau j'aurais resultat?
                                    • 1
                                    • 2