Vous êtes nouveau sur Developpez.com ? Créez votre compte ou connectez-vous afin de pouvoir participer !

Vous devez avoir un compte Developpez.com et être connecté pour pouvoir participer aux discussions.

Vous n'avez pas encore de compte Developpez.com ? Créez-en un en quelques instants, c'est entièrement gratuit !

Si vous disposez déjà d'un compte et qu'il est bien activé, connectez-vous à l'aide du formulaire ci-dessous.

Identifiez-vous
Identifiant
Mot de passe
Mot de passe oublié ?
Créer un compte

L'inscription est gratuite et ne vous prendra que quelques instants !

Je m'inscris !

Apprendre à créer des listes déroulantes liées entre elles sans utiliser Ajax
Un article de NoSmoking

Le , par NoSmoking

52PARTAGES

7  0 
Bonjour,

Je vous propose un article : Créer des listes déroulantes liées entre elles sans utiliser Ajax.

Dans celui-ci, nous allons voir comment lier des listes déroulantes, <select>, entre elles sans faire appel à des requêtes serveur de type Ajax, tout se passe donc côté client.

L'approche que je vous propose est une approche s'appuyant sur une pseudobase de données facile à maintenir associée à une fonction de recherche.

N'hésitez pas à faire part de vos remarques ou commentaires concernant cet article.

Bonne lecture.

Créer des listes déroulantes liées entre elles sans utiliser Ajax.

Les meilleurs cours et tutoriels pour apprendre la programmation JavaScript
Les meilleurs cours et tutoriels pour apprendre la programmation Web

Une erreur dans cette actualité ? Signalez-le nous !

Avatar de NoSmoking
Modérateur https://www.developpez.com
Le 04/04/2016 à 19:06
Bonjour à tous et merci pour vos retour.
ce n'est pas la région "Haut de France" mais "Hauts de France"
je n’avais pas corrigé le bon fichier, par contre Daniel.
Il y a aussi le département du "Creuset" au lieu du département de la "Creuse".
celle là je ne me l'explique pas mais je te rassure cela ne provient pas de l'INSEE .

C'est corrigé dans la mise à jour.

Jérôme, pour en revenir à tes autres remarques
ne faudrait-il pas mettre en titre "...listes liées en cascade..." (ou un truc du genre)
Les listes liées sont toutes en « cascade » l'une entrainant l'autre c'est peut être juste la présentation qui donne un peu plus cette impression.
Un autre point est que souvent, lorsqu'il n'y a qu'un choix possible, on est quand même obligé de le sélectionner sur un bon nombre de site alors que dans mon exemple je le sélectionne par défaut ce qui fait que l'enchainement sur la liste suivante est réalisé.

tu ne traites pas d'une liste dépendant (par exemple) de DEUX ou PLUSIEURS autres listes.
le principe est le même et il suffit juste de faire abstraction du type de données pour voir que l'on est dans un schéma classique.

Imaginons que
  • nouvelle région soit modèle ;
  • ancienne région soit année ;
  • département soit couleur.
on retrouve bien le même schéma.

3/ il existe dans la FAQ JavaScript : Comment lier deux listes déroulantes entre elles ?
Je n'ai pas vu de lien dans l'article...
C'est prévu lorsque la mise à jour de la faq sera effective, car l’exemple actuel fourni ne me convient pas franchement, on en avait parlé ici Les formulaires (partie 2) Comment lier deux listes déroulantes entre elles ?

Quant au dernier lien que tu mets il ne m'a pas semblait opportun de le mettre car utilisant justement l'Ajax, donc difficile à introduire. De plus ce lien est épinglé ce qui en fait un incontournable.

Francis ton approche est pas mal non plus et tu fais bien de profiter de l'occasion pour nous en faire cadeau, cela fera une alternative de plus.
4  0 
Avatar de Francis Walter
Expert éminent sénior https://www.developpez.com
Le 04/04/2016 à 14:26
Bonjour,

J'ai fait une lecture rapide et je trouve l'article bien.
Je vais profiter de cette discussion pour partager une méthode que j'ai l'habitude d'utiliser en manipulant les éléments optgroup du select :
(J'ai utilisé du JQuery)
Code HTML : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
  
<html> 
    <head>     
        <meta charset="UTF-8" /> 
        <title>Test</title> 
		<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.0/jquery.min.js"></script> 
    </head> 
    <body> 
        <div> 
            <label for="countries" class="required">Pays :</label> 
            <select id="countries" name="countries" content-type="choices" trigger="true" target="department"> 
                <option value="1" >France</option> 
                <option value="2" >Bénin</option> 
            </select> 
        </div> 
        <div> 
            <label for="department" class="required">Départements :</label> 
            <select id="department" name="department" > 
                <optgroup reference="1"> 
                    <option value="1" >Côtes d'amor</option> 
                    <option value="2" >Finistère</option> 
                    <option value="3" >Île-et-Vilaine</option> 
                    <option value="4" >Morbihan</option> 
                </optgroup> 
                <optgroup reference="2"> 
                    <option value="5" >Littoral</option> 
                    <option value="6" >Collines</option> 
                    <option value="7" >Atlantique</option> 
                    <option value="8" >Zou</option> 
                </optgroup> 
            </select> 
        </div> 
        <script> /* Insérer le code JavaScript ici */ </script> 
    </body> 
</html>
Code JavaScript : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
  
/* 
  * trigger="true" permet de dire que c'est l'élément le plus haut qui fait varier toutes les autres listes 
  * target=[id_cible] permet de spécifier la liste qui doit varier au changement de la sélection 
  * reference=[id_reference] est l'id de l'élément parent qui déclenche la mise à jour de la liste 
*/ 
  
//Fonction qui s'occupe de la mise à jour des listes 
function updateSelectBox(object){ 
    // Object correspond au input qui déclenche l'action (pays dans notre cas) 
    // On récupère le select (département) qui doit être mise à jour suite au changement du parent (pays) 
    var target = $("#"+object.attr('target')); 
  
    // On récupère tous les optgroup du select cible spécifié avec target (les optgroup du select département) 
    var listGroups = target.find("optgroup"); 
  
    // On récupère le optgroup qui correspond à la valeur courante du select parent (pays) 
    var validGroup = target.find("optgroup[reference='"+object.find(':selected').val()+"']"); 
  
    //On modifie la valeur courante du select cible (département) 
    target.val(validGroup.find("option").val()); 
  
    //On cache tous les optgroup de département 
    listGroups.hide(); 
  
    //On affiche uniquement le optgroup de département qui correspond à la valeur courante de pays 
    validGroup.show(); 
  
    //On vérifie si la cible (département) doit déclencher une mise à jour d'une autre liste 
    // Département peut par exemple déclencher la mise à jour des villes, et les villes déclenches celle des quartiers... 
    if(target.attr('content-type')=='choices') 
        target.change(); 
} 
  
//On associe la fonction updateSelectBox à l'événement onchange des listes qui doivent déclencher des mises à jour d'autres listes 
$("select[content-type='choices']").on('change',function(){ 
    updateSelectBox($(this)); 
}); 
  
//On fait la première mise à jour des 
$(document).ready(function(){ 
    updateSelectBox($("select[trigger='true']")); 
});

Si par exemple vous souhaitez ajouter les villes, il suffira d'ajouter un autre bloc select pour les villes, de renseigner son id à l'attribut target de département comme ceci :

Code HTML : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
  
<div> 
    <label for="town" class="required">Villes :</label> 
    <select id="town" name="town" content-type="choices"> 
        <optgroup reference="1"> <!-- 1 correspond à la valeur du département Côtes d'amor --> 
            <option value="1" >Ville machin</option> 
            <option value="2" >Ville consor</option> 
        </optgroup> 
        <optgroup reference="5"> <!-- 5 correspond à la valeur du département Littoral --> 
            <option value="4" >Cotonou</option> 
        </optgroup> 
    </select> 
</div>

Maintenant faut pas oublier de dire au select de département de faire varier les villes au changement en ajoutant content-type="choices" et target="town"Vous pouvez voir un petit démo ici : http://francis-walter.developpez.com...-without-ajax/
1  0 
Avatar de SylvainPV
Rédacteur/Modérateur https://www.developpez.com
Le 22/05/2016 à 15:24
Il se trouve que je bosse précisément en ce moment avec les administrations publiques et la gestion des voiries sur des référentiels des communes, donc désolé, je ne pense pas me tromper vu que c'est moi qui gère ces mises à jour des dits référentiels.... Voilà le dernier annuel de l'INSEE. Pour mon client la mise à jour est hebdomadaire et essentielle à son activité.

Vous vous plaignez de l'impact en performances, je vous donne un cas concret où l'on passe de 36000 items à télécharger à 400, et vous me dites que 36000 items c'est rien du tout à télécharger. Alors en récupérer par paquets de 300 ça devrait être encore moins que rien du tout, non ? Donc n'avoir aucune incidence sur la réactivité.

Je n'ai jamais parlé de fichier binaire, en AJAX c'est 99% du temps du JSON donc du texte qui pèse à peine plus lourd que faire son propre format texte. Je ne sais pas où vous êtes allé chercher votre facteur 1000, mais peu importe que vous stockiez cette liste dans un JSON, un script inline ou un script externe, il faut bien à un moment qu'elle passe du serveur au client, avec toujours les mêmes conditions réseau. C'est vrai qu'il faut essayer de limiter le nombre de requêtes pour éviter la latence et l'overhead HTTP. Mais on parle de 100ms et 1500 bytes à tout casser pour du TCP/IPv4 en 3G, donc c'est négligeable à partir de données de plus de 10 ko.

Enfin je trouve ça assez hautain de votre part d'affirmer que je me trompe alors que c'est quelque-chose qui est mis en pratique depuis des années. Prenez un site e-commerce au hasard et regardez s'il récupère les noms de communes sans passer par AJAX. On se tromperait donc tous d'après vous ? Un peu d'humilité svp...
2  1 
Avatar de jreaux62
Rédacteur/Modérateur https://www.developpez.com
Le 04/04/2016 à 9:15
Bonjour NoSmoking,

D'abord : très bon article !

1/ Grosse coquille !!
ce n'est pas la région "Haut de France" mais "Hauts de France" (on est plusieurs ! )

2/ (plus sérieux)
ne faudrait-il pas mettre en titre "...listes liées en cascade..." (ou un truc du genre)
UNE liste étant liée à UNE SEULE autre "parente" ?

Sauf erreur (car j'ai lu vite fait), tu ne traites pas d'une liste dépendant (par exemple) de DEUX ou PLUSIEURS autres listes.

Ex. : liste de véhicules dépendant de :
  • modèle
  • année
  • couleur
  • ...


A moins que ce soit le sujet d'un autre article ?

3/ il existe dans la FAQ JavaScript : Comment lier deux listes déroulantes entre elles ?
Je n'ai pas vu de lien dans l'article...

A voir aussi : http://www.developpez.net/forums/d59...s-liees-entre/
0  0 
Avatar de danielhagnoul
Rédacteur https://www.developpez.com
Le 04/04/2016 à 9:46
Il y a aussi le département du "Creuset" au lieu du département de la "Creuse".

Si les erreurs ont été commises par l'INSEE, c'est encore plus grave.
0  0 
Avatar de MichaelREMY
Membre confirmé https://www.developpez.com
Le 07/04/2016 à 10:40
j'approuve totalement cette démarche. ça devrait être un exercice de base pour tous ceux qui apprennent le javascript.
Avant de savoir le faire avec ajax, on doit savoir le faire sans (on doit même savoir le faire en algorithme même avant)

Pourquoi utiliser ajax quand on peut s'en passer!?

Le gain en terme de performance côté client est total, sans parler de l'expérience utilisateur qui est merveilleuse avec cette instantanéité alors qu'avec ajax on est sans arrêté en attente de délai de connexion,/serveur.
1  1 
Avatar de SylvainPV
Rédacteur/Modérateur https://www.developpez.com
Le 22/05/2016 à 2:21
@MichaelREMY: deux raisons principales pour utiliser AJAX: la quantité de données et leur dynamisation.

Si par exemple on fait une liste déroulante liée pour cette fois trouver une commune en France et non plus un département, on comprend facilement qu'il vaut mieux charger 100 départements, puis en AJAX 300 communes rattachées au département choisi, plutôt que de faire télécharger au client les 36000 communes françaises dès le début.

De plus, vu la fréquence à laquelle les communes évoluent (des centaines de fusions/divisions/créations/renommages chaque année), ce serait très pénible de stocker cette liste dans le code client: ça impliquerait de relivrer l'application à chaque mise à jour, avec les problèmes que ça pose pour la gestion du cache. Alors que si c'est dans une base de données, on peut mettre à jour n'importe quand et très facilement.

Donc dans les faits, on a encore souvent besoin d'AJAX dans les cas d'utilisation classiques des listes liées. Ceci dit on peut facilement adapter à AJAX la méthode d'update des select expliquée dans l'article.
1  1 
Avatar de SylvainPV
Rédacteur/Modérateur https://www.developpez.com
Le 22/05/2016 à 20:57
Si le serveur a une latence de plus de 100ms pour pondre une requête JSON aussi simple, ce n'est pas AJAX le problème, c'est le serveur. Mais lui faire cracher les 36000 communes pour chaque utilisateur quand la majorité ne sont intéressés que par celles de leur département, je doute que ce soit l'idéal question perfs.

Amazon n'a pas du tout besoin de la liste des villes, juste d'une adresse postale, donc ça va être difficile de démontrer quoi que ce soit avec ça... Prenons plutôt les sites immobiliers, où récupérer la ville est utile. Je n'ai regardé que seloger.com, logic-immo et Paru-Vendu: tous utilisent AJAX... De même, leboncoin utilise AJAX pour trouver les communes par filtrage de lettre.

Mais au fond, on est d'accord: AJAX n'est pas une nécessité absolue. Pour des données de moins de 5-10ko, qui ne changent pas trop souvent, on peut envisager de les précharger en totalité. Pour tout les autres cas, paginer ou filtrer les données est essentiel, et AJAX est le mécanisme le moins disruptif à cet effet.
1  1 
Avatar de MichaelREMY
Membre confirmé https://www.developpez.com
Le 22/05/2016 à 22:16
Citation Envoyé par SylvainPV Voir le message
Mais au fond, on est d'accord: AJAX n'est pas une nécessité absolue. Pour des données de moins de 5-10ko, qui ne changent pas trop souvent, on peut envisager de les précharger en totalité. Pour tout les autres cas, paginer ou filtrer les données est essentiel, et AJAX est le mécanisme le moins disruptif à cet effet.
mais votre script ajax, sa librairie, sa requête, ses composantes de sécurité, son accès réseau (ses multiples mêmes), ses passages en log, ...etc nécessitent plus de 10ko en ressources, en bande passante en charge...etc c'est là que vous ne me comprenez pas. Des données transmises en fichiers linéaires ne consomment pas tant que ça (vous êtes biaisais pas ces chiffres quantitatifs). n'avez-vous jamais remarquez que la vitesse de téléchargement d'un fichier 100% textuel (un dump sql non compressé par exemple, ou un export .csv ou txt) de plusieurs 100 de Mo va extrement plus vite qu'un même fichier en binaire. Une page HTM de 10Ko ira plus vite qu'une page de 1Ko + 5 requetes ajax et ça consommera moins !!

Ainsi si je suis votre raisonnement et le démontre (avec humour) :
vous préférez construire une ligne de chemin de fer avec 10 gares d'arrêts entre monaco et paris pour transporter 5 containers en 5 fois plutôt qu'une seule ligne directe d'un train express à 5 wagons d'une ligne point à point (sans arrêt)! vous croyez que minimiser la quantité transportée par wagon coutera moins cher à la société.... cher monsieur vous oubliez le coût et les temps aux gares, les vérifications des billets à chaque point....,etc.

Comme je le dis plus haut, le coût de traitement de votre méthode ajax coutent plus cher en charge et en octets au serveur et au client et en bande passante que la quantité totale de données à transporter.

Personnellement un script ajax est utile quand :
- il nécessite de brasser de multiples données croisés (un process métier) et non pas juste un filtrage/pagination.
- nécessite de garder une confidentialité (ne pas fournir tout au client)
- quand le client (l’utilisateur) peut avoir à effectuer plusieurs choix successifs des données dans la même session)
- nécessite absolue d’apporter une UX avantageuse et ergonomique (donc pas juste pour être à la mode et faire comme tout le monde).
1  1 
Avatar de SylvainPV
Rédacteur/Modérateur https://www.developpez.com
Le 23/05/2016 à 1:16
Récupérer un JSON en AJAX, c'est une broutille... ça se fait en une ligne de code en ES6:
Code : Sélectionner tout
fetch("/api/listeVilles/Nord").then(res => res.json()).then(function(villes){ ... })
Et pour les plus vieux navigateurs, ça peut se faire avec une petite fonction de dix lignes. Il faut m'expliquer d'où est-ce que vous sortez vos 10ko en bande passante suplémentaire.

Ensuite vous me refaites le coup du binaire, mais d'où est-ce que ça sort cette histoire de binaire ? L'AJAX c'est historiquement du XML et en pratique c'est 99% du temps du JSON, qui sont des formats textuels. Je ne sais pas non plus ce que vient faire Docker dans cette histoire.

Enfin, ce n'est pas une histoire de petits trains qui va occulter le fait que je vous ai trouvé 4 sites grands publics utilisant AJAX pour récupérer les noms des villes. Si vous continuez à prétendre que vous connaissez mieux votre sujet que toutes les équipes techniques réunies de ces sites, je pense qu'il vaut mieux arrêter cette discussion ici.
1  1