4 votes

Comment puis-je modifier ce jQuery pour montrer et cacher dynamiquement les options de sélection dépendantes dans un menu déroulant?

Dans cet exemple, j'ai une série de 3 listes déroulantes select. La même classe ("group-1") est appliquée à chacune pour indiquer qu'elles sont liées (et permettre plusieurs groupes de sélection sur la même page). L'attribut "data-parent" est appliqué au select pour établir une relation parent/enfant 1:1. L'attribut "data-parent" est appliqué à l'option pour établir une relation de type beaucoup:beaucoup.

Mon objectif est de créer un morceau de code jQuery dynamique afin de ne pas avoir à identifier explicitement le comportement par id ou classe, mais plutôt par la valeur de l'option et la valeur de data-parent.

Mes problèmes :

  1. La troisième liste déroulante ne se met pas à jour du tout. Je pensais que cela pourrait être dû au fait que certaines d'entre elles ont plus d'une valeur data-parent (séparées par un espace), mais même si je les modifie pour qu'elles aient toutes une seule valeur, elle ne se met toujours pas à jour avec les changements de la deuxième liste déroulante.
  2. Je ne sais pas comment implémenter les valeurs data-parent "beaucoup" dans les options pour la troisième liste déroulante. Diviser la chaîne, créer un tableau et vérifier si la valeur s'y trouve?
  3. Comment réinitialiser les deuxième et troisième listes déroulantes à la valeur "par défaut" avec un changement de la liste déroulante parent ? Par exemple, si je choisis "Cookies" du premier, "1 douzaine" et "2 douzaines" apparaissent dans le deuxième. Mais si je sélectionne "1 douzaine" puis change la première boîte par "Gâteaux", "1 douzaine" reste sélectionné même si "Feuille" et "Rond" sont les seules options disponibles dans la liste déroulante. J'aimerais qu'elle se réinitialise à la valeur par défaut ("Desserts...").

Le code est ci-dessous, et voici mon jsfiddle fonctionnel : https://jsfiddle.net/rwh4z623/20/

$(document).ready(function(){
    $(".hide").children("option").hide();
    $("select").on('change', function(){
        var selClass = $(this).attr("class");
        var selName = $(this).attr("name");
        var selVal = $(this).children("option:selected").val();
        $("select."+selClass+"[data-parent='"+selName+"']").each(function(){
            $(this).children("option[data-parent='"+selVal+"']").show();
            $(this).children("option[data-parent!='"+selVal+"']").hide();
        });
    });
});

    Veuillez sélectionner...
    Cookies
    Gâteaux
    Crème glacée

    Desserts...
    1 douzaine
    2 douzaines
    Feuille
    Rond
    Pinte

    Saveurs...
    Pépite de chocolat
    Avoine
    Jaune
    Velours rouge

Merci d'avance pour toute aide ! De plus, les suggestions d'améliorations sont appréciées.

1voto

user14040328 Points 26

Je ne connais pas le contexte de ce code, donc je n'ai aucune idée si ce modèle d'options et de sélections "imbriquées" est la meilleure solution. Mais voici ma version du javascript qui semble réaliser ce qui était demandé dans la question. Je vais commenter les modifications pertinentes pour expliquer ma démarche. J'ai également ajouté le css pour une classe hide, car cela n'était pas dans le jsfiddle.

$(document).ready(function () {
    $("select").on('change', function () {
        var selClass = $(this).attr("class");
        var selName = $(this).attr("name");
        var selVal = $(this).children("option:selected").val();

        //Appeler la fonction update avec les données de la Sélection modifiée
        updateRecursivly(selClass, selName, selVal);

        //Fonction récursive pour mettre à jour toutes les sélections, cela permet d'avoir plusieurs sélections "enfants" par sélection et une "arborescence" infinie en théorie de sélections
        function updateRecursivly(selClass, selName, selVal) {
            //Rechercher les "enfants" de la sélection parent
            var children = $("select." + selClass + "[data-parent='" + selName + "']");
            if (children.length) {
                children.each(function () {
                    //Cacher toutes les options dans la sélection "enfant"
                    $(this).children("option[data-parent]").hide();
                    //si selVal est une chaîne vide, l'option par défaut est sélectionnée et nous devrions simplement cacher la sélection "enfant"
                    if (selVal !== "") {
                        //Obtenir toutes les options contenant (*=) selVal dans "data-parent"
                        var options = $(this).children("option[data-parent*='" + selVal + "']");
                        //s'il y a des options possibles, afficher la sélection et les options possibles. Sinon, cacher la sélection
                        if (options.length) {
                            $(this).removeClass('hide');
                            options.show();
                        } else {
                            $(this).addClass('hide');
                        }
                    } else {
                        $(this).addClass('hide');
                    }
                    //Si la sélection est mise à jour, les options doivent être réinitialisées. Toute sélection est réinitialisée et la première est sélectionnée
                    //D'ici https://stackoverflow.com/a/16598989/14040328 c'est apparemment plus sûr contre les événements de réinitialisation que d'autres solutions
                    $(this).children("option:selected").prop("selected", false);
                    $(this).children("option:first").prop("selected", "selected");

                    //Obtenir le nom de la sélection
                    var childName = $(this).attr("name");

                    //Mettre à jour la sélection enfant
                    updateRecursivly(selClass, childName, "");
                });
            }
        }
    });
});

.hide {
  display: none;
}

Je ne suis pas sûr si j'ai trop commenté ou non, si quelque chose n'est pas clair, n'hésitez pas à commenter.

0voto

Swati Points 22914

Vous pouvez utiliser attributeContainsWord (~) pour faire correspondre plusieurs valeurs à un mot. Ainsi, dans le code ci-dessous, j'ai utilisé $(this).children("option[data-parent~='" + selVal + "']").show(); pour afficher les options qui correspondent à selVal. De plus, j'ai utilisé prop('selectedIndex', 0); pour réinitialiser la sélection par défaut.

Code de démonstration :

$(document).ready(function() {
  $(".hide").children("option").hide();
  $("select").on('change', function() {
    //vérification si la liste déroulante est des catégories
    if ($(this).attr("name") == "categories") {
      //réinitialiser les autres par défaut
      $('select[name=desserts]').prop('selectedIndex', 0);
      $('select[name=flavors]').prop('selectedIndex', 0);
    }

    var selClass = $(this).attr("class");
    var selName = $(this).attr("name");
    var selVal = $(this).children("option:selected").val();
    //vérifier si le nom n'est pas desserts
    if ($(this).attr("name") != "desserts") {
      //cacher l'option de saveur
      $("select[name=flavors]").children("option").hide();
      //boucler et afficher les valeurs désirées
      $("select." + selClass + "[data-parent='" + selName + "']").each(function() {
        $(this).children("option[data-parent='" + selVal + "']").show();
        $(this).children("option[data-parent!='" + selVal + "']").hide();
      });

    } else {
      //cacher les options
      $("select[name=flavors]").children("option").hide();
      //boucler à travers les saveurs
      $("select[name=flavors]").each(function() {
        //utiliser " ~ " pour voir si le selval correspond aux valeurs
        $(this).children("option[data-parent~='" + selVal + "']").show();

      });

    }
  });
});

  Veuillez choisir...
  Cookies
  Gâteaux
  Crème glacée

  Desserts...
  1 douzaine
  2 douzaines
  Feuille
  Rond
  Pinte

  Saveurs...
  Pépites de chocolat
  Avoine
  Jaune
  Velours rouge

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X