Accueil > PHP

Listes déroulantes dynamiques liées avec PHP et jQuery

-
Télécharger
Démo

Les listes déroulantes dynamiques liées permettent de rendre l’interface utilisateur encore plus ergonomique. Par exemple, si vous deviez demander à l’utilisateur de choisir son pays puis sa ville de résidence, il serait plus aisé pour lui si la liste des choix de ville s’actualisait en fonction du pays choisi: lui proposer de choisir parmi toutes les villes du monde serait pour lui un véritable casse-tête.

Description

La solution CS à ce problème relativement simple utilise jQuery (la fonction getJSON en particulier). Pour l’illustrer, nous considérerons un formulaire dans lequel l’utilisateur aura à choisir son pays puis sa ville.

Listes déroulantes dynamiques liées avec PHP et jQuery

Les étapes de notre solution sont les suivantes:

1- Créer deux listes select (combo box) listePays et listeVille dans le fichier principal (index.php). Lorsque l’utilisateur change la valeur de listePays, envoyer l’ID du pays sélectionné au processeur (processeur.php)
2- La liste des villes est ainsi extraite (de la base de données ou d’un simple tableau array comme dans notre exemple), encodée en JSON et renvoyée au fichier principal
3- Le résultat de la requête est alors insérée dans la liste listeVille.

Implémentation

Fichier principal: index.php

- Appel de la bibliothèque jQuery (disponible sur Google Code)


- Création des listes select listePays et listeVille




- Code jQuery pour envoyer l’ID du pays au processeur et insérer le résultat dans la liste listeVille lorsque l’utilisateur sélectionne un pays

$(document).ready(function(){
	$("select#listePaysId").change(function(){
		var idVal = $("select#listePaysId option:selected").attr('value');
		
		$.getJSON("processeur.php",{paysID: idVal, ajax: "true"}, function(data){				
			var options = "";
			if (data != null) 
			{					
				for (var i = 0; i < data.length; i++) {
					options += '';
				}
			}
			if (options != "") 
			{
				$("#resJson").attr("value", options);
				$("select#listeVilleId").html(options);
				$("select#listeVilleId").attr("disabled", false);
			}
			
		});
		
	});	
});

Détails
Si la valeur de listePays change, l’ID du pays sélectionné est sauvegardé dans la variable idVal. La fonction getJSON de jQuery est alors utilisée pour envoyer une requête au processeur processeur.php sous la forme ./processeur.php?paysID=[idVal]. Le résultat attendu étant un tableau d’éléments au format JSON, chaque élément est parsé en option de select

Processeur: processeur.php

Pour simplifier les choses, l’extraction des données dans cet exemple se fait à partir d’un tableau. Mais cette logique s’applique aussi bien à des données existantes dans une base de données. Néanmoins le risque d’injection SQL est grand et le développeur devra y prêter une attention particulière.

- Définition de la liste restreinte des pays et vérification de l’ID envoyé par le fichier principal
Note: l’ID du pays est envoyé comme paramètre $_GET.

$paysListe = array("fr", "us", "es", "en");
if (empty($_GET['paysID']) || !in_array($_GET['paysID'], $paysListe)) 
{
	exitProcesseur();
}
$paysID = $_GET['paysID'];

- Définition de la liste de villes pour chaque pays

$villes = $paysListe;

$villes["fr"][] = array("value"=>"paris", "label"=>"Paris");
$villes["fr"][] = array("value"=>"marseille", "label"=>"Marseille");
$villes["fr"][] = array("value"=>"toulouse", "label"=>"Toulouse");
$villes["fr"][] = array("value"=>"bordeaux", "label"=>"Bordeaux");
$villes["fr"][] = array("value"=>"lille", "label"=>"Lille");
$villes["fr"][] = array("value"=>"nancy", "label"=>"Nancy");

$villes["us"][] = array("value"=>"new-york", "label"=>"New-York");
$villes["us"][] = array("value"=>"washington", "label"=>"Washington");
$villes["us"][] = array("value"=>"los angeles", "label"=>"Los Angeles");

$villes["es"][] = array("value"=>"madrid", "label"=>"Madrid");
$villes["es"][] = array("value"=>"barcelone", "label"=>"Barcelone");
$villes["es"][] = array("value"=>"valence", "label"=>"Valence");

- Sauvegarde de la liste de villes dans la $result

$result = array();
foreach ($villes[$paysID] as $ville)
{
	$result[] = $ville;
}

- Encodage JSON et affichage du résultat

echo json_encode($result);

Fichier complet

function exitProcesseur()
{
	echo '';
	exit();
}

$paysListe = array("fr", "us", "es", "en");
if (empty($_GET['paysID']) || !in_array($_GET['paysID'], $paysListe)) 
{
	exitProcesseur();
}
$paysID = $_GET['paysID'];

$villes = $paysListe;

$villes["fr"][] = array("value"=>"paris", "label"=>"Paris");
$villes["fr"][] = array("value"=>"marseille", "label"=>"Marseille");
$villes["fr"][] = array("value"=>"toulouse", "label"=>"Toulouse");
$villes["fr"][] = array("value"=>"bordeaux", "label"=>"Bordeaux");
$villes["fr"][] = array("value"=>"lille", "label"=>"Lille");
$villes["fr"][] = array("value"=>"nancy", "label"=>"Nancy");

$villes["us"][] = array("value"=>"new-york", "label"=>"New-York");
$villes["us"][] = array("value"=>"washington", "label"=>"Washington");
$villes["us"][] = array("value"=>"los angeles", "label"=>"Los Angeles");

$villes["es"][] = array("value"=>"madrid", "label"=>"Madrid");
$villes["es"][] = array("value"=>"barcelone", "label"=>"Barcelone");
$villes["es"][] = array("value"=>"valence", "label"=>"Valence");

$result = array();
foreach ($villes[$paysID] as $ville)
{
	$result[] = $ville;
}
echo json_encode($result);
exit();

N’hésitez pas à envoyer vos suggestions / critiques en commentant ci-dessous

Télécharger
Démo
  • Saadou

     Merci.

  • Y-ss-n

    Est-ce que vous pouvez nous expliquer comment peut-on modifier ce script si on veut récupérer les données depuis une base de données MySQL ??

    • Anonyme

      Quelle est la structure de tes tables?

  • tomtom

    J’ai fais un test avec pays/région tiré de la base, ca passe pas vraiment, quelqu’un a un exemple?

    Merci!

    • Anonyme

      Pourrais-tu donner plus de details sur le code que tu as utilise?

      • tomtom

        oui je vous le met :

        index.php

        Liste chaînée avec PHP/JSON [Demo]

            td {
                vertical-align: top;
            }
            th {
                text-align: left;
            }
            #resJson {
                padding:5px; 
                border: 1px solid #DCDCDC; 
                width: 400px; 
                height: 180px;
            }
            #libelle {
                width: 100px;
            }

        Liste chaînée avec PHP/JSON

        Choisissez le pays puis la ville

        Pays

        <option value='’>

        Ville

        Résultat

        $(document).ready(function(){
        $(« select#listePaysId »).change(function(){
        var idVal = $(« select#listePaysId option:selected »).attr(‘value’);
        $(« select#listeVilleId »).attr(« disabled », true);

        $.getJSON(« processeur.php »,{paysID: idVal, ajax: « true »}, function(data){
        var options = «  »;
        if (data != null) 
        {
        for (var i = 0; i < data.length; i++) {
        options += '’ + data[i].label +  »;
        }
        }
        //envoyer le resultat dans le select
        $(« select#listeVilleId »).html(options);
                        $(« #resJson »).attr(« value », options);
                        
                        //si le resultat n’est pas vide
                        //activer le select
        if (options != «  ») 
        {
        $(« select#listeVilleId »).attr(« disabled », false);
        }

        });

        });
        });

        processus.php

        $res1['id'], « label »=>$res1['nom_region']);
        }
        }

        $result = array();
        foreach ($villes[$paysID] as $ville)

        $result[] = $ville;
        }
        echo json_encode($result);
        exit();
        ?>

        • tomtom

          Oui Je vous le met: 

          index.php:

          Liste chaînée avec PHP/JSON [Demo]

              td {
                  vertical-align: top;
              }
              th {
                  text-align: left;
              }
              #resJson {
                  padding:5px; 
                  border: 1px solid #DCDCDC; 
                  width: 400px; 
                  height: 180px;
              }
              #libelle {
                  width: 100px;
              }

          Liste chaînée avec PHP/JSON

          Choisissez le pays puis la ville

          Pays

          <option value='’>

          Ville

          Résultat

          $(document).ready(function(){
          $(« select#listePaysId »).change(function(){
          var idVal = $(« select#listePaysId option:selected »).attr(‘value’);
          $(« select#listeVilleId »).attr(« disabled », true);

          $.getJSON(« processeur.php »,{paysID: idVal, ajax: « true »}, function(data){
          var options = «  »;
          if (data != null) 
          {
          for (var i = 0; i < data.length; i++) {
          options += '’ + data[i].label +  »;
          }
          }
          //envoyer le resultat dans le select
          $(« select#listeVilleId »).html(options);
                          $(« #resJson »).attr(« value », options);
                          
                          //si le resultat n’est pas vide
                          //activer le select
          if (options != «  ») 
          {
          $(« select#listeVilleId »).attr(« disabled », false);
          }

          });

          });
          });

          • tomtom

            (le tout premier message du code est à effacer )
            Processeur.php$res1['id'], « label »=>$res1['nom_region']);
            }
            }

            $result = array();
            foreach ($villes[$paysID] as $ville)

            $result[] = $ville;
            }
            echo json_encode($result);
            exit();
            ?>

          • Anonyme

            Dans le script Javascript tu fais appel au fichier nomme « processus.php » au lieu de « processeur.php »

          • tomtom

            non j’ai juste changé les valeur des option tiré de la base, mais j’ai travaillé sur les fichiers que vous avez mis.
            J’ai l’impression que le code que je vous ai mis en commentaire est tronqué, je vous envoi les fichiers par mail si vous voulez.
            Merci

  • http://twitter.com/Planteparadise Le Paradis du Jardin

    c’est bien mais si on veut créer plusieurs listes qui s’affichent en cascade en fonction du résultat précédent comment fait-t-on avec 3 listes par exemple faut-il créer un fichier supplémentaire ?

  • laloune

    billet très instructif, merci beaucoup !

    et le fait d’avoir mis « Nancy » dans les villes, ca c’est le gros + :-) 5-4 4-ever

  • Sylvain

    Est il possible de paramétrer ce script afin que lorsque on arrive sur la page avec un lien qui indique un choix de pays ($_GET) on ait déjà la selction des villes qui s’affiche ?

    • Anonyme

      Tout a fait possible, meme si ca necessite assez de changement au code ci-dessus. Tu pourrais par exemple ajouter une condition PHP afin que la fonction Javascript AJAX, qui permet de remplir les select soit appelee manuellement tout a fait en bas de ton code.

      Quelque chose dans le genre:

      /*appel de la fonction AJAX*/

  • asrahzarh

    très bon code, mais de gros problème quand à la mise en place via ma base de données. Je cite l’erreur : Fatal error: Cannot use string offset as an array

    Et le bout de code où il y a l’erreur :

    while( $ligne4 = $listeProjets2->fetch() )
    {
    $nom2 = $ligne4[0];

    //Liste procédures
    $listeProcedures = listeProcedures($nom2);

    // Pour chaque procédure
    while( $ligne2 = $listeProcedures->fetch() )
    {
    $libelle = $ligne2[0];
    $procedures[$nom2][] = array(« value2″=>$libelle, « label2″=>$libelle);
    }
    $listeProcedures->closeCursor();

    }
    $listeProjets2->closeCursor();

    $result = array();

    HELP ME :)

  • Soufiane Benyahya

    Bonjour ,
    baah c’est une bonne méthode mais si on veut remplir ces deux liste avec le contenu de la base de données est ce qu’il y a un code qui pourra implémenter ça

    NB : j’ai fais pas mal de tentatives mais sans résultats aidez-moi SVP et merci d’avance.

  • Nightmare

    Salut ton code et vraiment au top mais malheureusement je rencontre un problème j’ai vraiment du mal a intégré d’autre champs aurait tu une solution merci d’avance !

Ressources pour PHP, JavaScript, HTML/CSS - CodeurSolitaire 2012