AJAX pour gérer des listes déroulantes imbriquées

Certains sites ont besoin de mettre en place une liste déroulante dont les options dépendent de la valeur sélectionnée dans une autre liste déroulante.

Par exemple, on pourrait avoir une liste déroulante proposant les départements d'une entreprise et une autre qui présente les personnes travaillant dans le département sélectionné. Autre exemple : une liste déroulante de pays et, selon le pays sélectionné, une liste déroulante de provinces (ou d'états, ou de communes, selon le terme convenant au pays).

Pour réaliser des listes déroulantes imbriquées, AJAX sera votre allié !

▼Publicité

Prenons l'exemple de la liste de pays qui influencera les options de la liste de provinces. La liste de pays pourrait être remplie de façon traditionnelle lors du chargement de la page. Elle pourrait également être remplie par AJAX sur le $(document).ready(), avec l'avantage que la requête à la base de données ne retardera pas le chargement initial de la page.

La liste de provinces, quant à elle, sera remplie par AJAX sur le .change() de la liste de pays.

Listes déroulantes imbriquées remplies avec AJAX

Voici le code PHP des fichiers qui généreront les options des listes déroulantes à partir de la base de données. Ce code sera placé dans deux fichiers que j'ai nommés generer-options-pays.php et generer-options-provinces.php :

PHP

// retourne les balises <option> pour remplir un <select> de pays à partir des données d'une table

// ce code est destiné à être appelé via AJAX

// si problème rencontré, retournera plutôt une des chaînes suivantes :

// REQUETE : la requête a planté

// AUCUNEDONNEE : la requête n'a retourné aucune donnée

// NONDETERMINE : le programme a rencontré une erreur non déterminée

// Le branchement à la base de données est réputé fait.

 

$retour = "";

$requete = "SELECT pays_id, pays_nom FROM pays ORDER BY pays_nom";

$resultat = $mysqli->query($requete);     // exécute la requête

 

if ($resultat) {    // si la requête a fonctionné

    if ($mysqli->affected_rows != 0) {    // si la requête a retourné au moins un enregistrement

 

        while ($enreg = $resultat->fetch_row()) {     // extrait chaque ligne une à une

            $retour .= "<option value='$enreg[0]'>$enreg[1]</option>";

        }

    }

    else {

        $retour = "AUCUNEDONNEE";

    }

}

else {

    $retour = "REQUETE";

}

 

// ne devrait jamais renter ici mais on conserve ce test au cas où

if ("" == $retour) {

    $retour = "NONDETERMINE";

}

 

echo $retour; // il faut faire un echo de code html puisque l'appel AJAX a été fait avec dataType: "html"

 

PHP

// retourne les balises <option> pour remplir un <select> de provinces selon le pays sélectionné

// ce code est destiné à être appelé via AJAX

// si problème rencontré, retournera plutôt une des chaînes suivantes :

// PARAMETRE : les données nécessaires n'ont pas été reçues en paramètre ou les paramètres n'étaient pas tous valides

// REQUETE : la requête a planté

// AUCUNEDONNEE : la requête n'a retourné aucune donnée

// NONDETERMINE : le programme a rencontré une erreur non déterminée

// Le branchement à la base de données est réputé fait.

 

$retour = "";

 

// retrouver le pays sélectionné, qui a été envoyé par AJAX

$pays = $_POST['pays'];

 

// valider les données côté serveur

$donneesValides = true;

if ('' == $pays) {

    $donneesValides = false;

}

else {

    // recherche si l'identifiant du pays existe dans la BD

    $requete = "SELECT pays_nom FROM pays WHERE pays_id = ?";

    $stmt = $mysqli->prepare($requete);

 

    if ($stmt) {

 

        $stmt->bind_param("i", $pays);

        $stmt->execute();

        // Sans cette ligne, il ne sera pas possible de connaître le nombre de lignes retournées par un SELECT.

        $stmt->store_result();

 

        if ($stmt->num_rows == 0) {

            $donneesValides = false;

        }

 

        $stmt->close();

    }

    else {

        $retour = "REQUETE";

    }

}

 

if ($donneesValides && '' == $retour) {

 

    $requete = "SELECT province_id, province_nom FROM province WHERE province_pays_id = ? ORDER BY province_nom";

    $stmt = $mysqli->prepare($requete);

 

    if ($stmt) {

 

        $stmt->bind_param("i", $pays);

 

        $stmt->execute();

        // Sans cette ligne, il ne sera pas possible de connaître le nombre de lignes retournées par un SELECT.

        $stmt->store_result();

 

        if ($stmt->num_rows > 0) {

 

            $stmt->bind_result($province_id, $province_nom);

 

            while ($stmt->fetch()) {

                $retour .= "<option value='$province_id'>$province_nom</option>";

            }

        }

        else {

            $retour = "AUCUNEDONNEE";

        }

    }

    else {

        $retour = "REQUETE

    }

 

    // ne devrait jamais renter ici mais on la laisse là au cas où

    if ("" == $retour) {

        $retour = "NONDETERMINE";

    }

}

else {

    $retour = "PARAMETRE";

}

 

echo $retour;

La page Web se chargera de remplir la liste déroulante de pays dès que le DOM est chargé. La liste déroulante de provinces sera chargée lors d'un changement de pays.

HTML

<form method="post">

    <label for="pays">Pays :</label><select name="pays" id="pays" required></select>

    <label for="province">Province :</label><select name="province" id="province" required></select>

    <input type="submit" value="Envoyer" />

</form>

 

<script>

    $(function () {

        // dès le chargement de la page, on remplit la liste des pays

        remplirPays();

 

        // lorsque le pays sera changé dans la liste, on charge la liste des provinces ou états correspondants

        $("#pays").change(function (event) {

            remplirProvinces();

        });

    });

 

    function remplirPays() {

    var jqxhr = $.ajax({

            type: 'get', // on n'a pas de paramètres à envoyer alors GET est sécuritaire

            url: 'generer-options-pays.php',

            dataType: "html", // le fichier php fait un echo de code HTML

            contentType: "application/x-www-form-urlencoded; charset=UTF-8",

            data: ""

        })

        .done(function (response, textStatus, jqXHR) {

            // Appel réussi : on affiche le code HTML généré par le code serveur

            if ("REQUETE" == response) {

                $("#pays").html("<option value=''>Un problème technique nous empêche de retrouver les pays (code R).</option>");

            }

            else if ("AUCUNEDONNEE" == response) {

                $("#pays").html("<option value=''>Il n'y a actuellement aucun pays dans le système.</option>");

            }

            else if ("NONDETERMINE" == response) {

                $("#pays").html("<option value=''>Un problème technique nous empêche de retrouver les pays (code I).</option>");

            }

            else if (response.indexOf('<option') != 0) {

                // la chaîne ne débute pas par <option donc c'est probablement un message d'erreur PHP retourné par AJAX

                $("#pays").html("<option value=''>Un problème technique nous empêche de retrouver les pays (code E).</option>");

            }

            else {

                $("#pays").html("<option value=''>Veuillez choisir...</option>" + response);

            }

        })

        .fail(function (jqXHR, textStatus, errorThrown) {

            // Réagit si le code serveur n'a pas pu être appelé par AJAX, s'il a planté ou s'il n'a pas retourné le bon type de données

            $("#pays").html("<option value=''>Un problème technique nous empêche de retrouver les pays (code A).</option>");

        });

    }

 

    function remplirProvinces() {

        var pays = $('#pays').val();

        var dataString = 'pays=' + pays;

 

        var jqxhr = $.ajax({

            type: 'post',

            url: 'generer-options-provinces.php',

            dataType: "html", // le fichier php fait un echo de code HTML

            contentType: "application/x-www-form-urlencoded; charset=UTF-8",

            data: dataString

        })

        .done(function (response, textStatus, jqXHR) {

            // Appel réussi : on affiche le code HTML généré par le code serveur

            if ("PARAMETRE" == response) {

                $("#province").html("<option value=''>Le pays sélectionné n'est pas valide.</option>");

            }

            else if ("REQUETE" == response) {

                $("#province").html("<option value=''>Un problème technique nous empêche de retrouver les provinces (code R).</option>");

            }

            else if ("AUCUNEDONNEE" == response) {

                $("#province").html("<option value=''>Il n'y a actuellement aucune province dans le système.</option>");

            }

            else if ("NONDETERMINE" == response) {

                $("#province").html("<option value=''>Un problème technique nous empêche de retrouver les provinces (code I).</option>");

            }

            else if (response.indexOf('<option') != 0) {

                // la chaîne ne débute pas par <option donc c'est probablement un message d'erreur PHP retourné par AJAX

                $("#province").html("<option value=''>Un problème technique nous empêche de retrouver les provinces (code E).</option>");

            }

            else {

                $("#province").html("<option value=''>Veuillez choisir...</option>" + response);

            }

        })

        .fail(function (jqXHR, textStatus, errorThrown) {

            // Réagit si le code serveur n'a pas pu être appelé par AJAX, s'il a planté ou s'il n'a pas retourné le bon type de données

            $("#province").html("<option value=''>Un problème technique nous empêche de retrouver les provinces (code A).</option>");

        });

    }

 

</script>

Merci de partager ! Share on FacebookTweet about this on TwitterShare on Google+Share on LinkedInPin on PinterestShare on StumbleUponEmail this to someone
Catégories