Как я могу изменить это jQuery, чтобы динамически отображать и скрывать зависимые параметры выбора в раскрывающемся списке? - PullRequest
4 голосов
/ 05 августа 2020

В этом примере у меня есть серия из 3 раскрывающихся списков выбора. К каждому из них применяется один и тот же класс («группа-1»), чтобы указать, что они связаны (и позволить несколько групп выбора на одной странице). Атрибут «данные-родитель» применяется к элементу select для установления sh отношения родитель / потомок 1: 1. Атрибут "data-parent" применяется к опции для установления sh отношения "многие: многие".

Моя цель - создать фрагмент динамического c jQuery кода, чтобы я не Я должен явно определять поведение по идентификатору или классу, а скорее по значению параметра и значению родительских данных.

Мои проблемы:

  1. Третье раскрывающееся меню не обновляется в все. Я думал, что у некоторых из них может быть более одного родительского значения данных (разделенных пробелом), но даже если я изменю их так, чтобы у всех было только одно, оно все равно не обновляется с изменениями во втором раскрывающемся списке .
  2. Я не уверен, как реализовать "многие" родительские значения данных в параметрах для третьего раскрывающегося списка. Разделите строку, создайте массив и проверьте, есть ли значение в массиве?
  3. Как мне сбросить второй и третий раскрывающиеся списки до значения «по умолчанию» с изменением родительского раскрывающегося списка -вниз? Например, если я выберу «Cookies» из первого, «1 дюжина» и «2 дюжины» появятся во втором. Но если я выберу «1 дюжина», а затем изменю первое поле на «Пироги», «1 дюжина» останется выбранной, хотя «Лист» и «Круглый» - единственные доступные варианты в раскрывающемся списке. Я бы хотел, чтобы он сбросил настройки по умолчанию («Десерты ...»).

Код ниже, а вот мой рабочий jsfiddle: 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();
        });
    });
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<select class="group-1" name="categories">
    <option value="" selected="selected">Please select...</option>
    <option value="cookie">Cookies</option>
    <option value="cake">Cakes</option>
    <option value="icecream">Ice Cream</option>
</select>

<select class="group-1 hide" name="desserts" data-parent="categories">
    <option value="" selected="selected">Desserts...</option>
    <option value="1-dozen" data-parent="cookie">1 dozen</option>
    <option value="2-dozen" data-parent="cookie">2 dozen</option>
    <option value="sheet" data-parent="cake">Sheet</option>
    <option value="round" data-parent="cake">Round</option>
    <option value="pint" data-parent="icecream">Pint</option>
</select>

<select class="group-1 hide" name="flavors" data-parent="desserts">
    <option value="" selected="selected">Flavors...</option>
    <option value="choc-chip" data-parent="1-dozen 2-dozen">Chocolate Chip</option>
    <option value="oatmeal" data-parent="1-dozen 2-dozen">Oatmeal</option>
    <option value="yellow" data-parent="sheet round">Yellow</option>
    <option value="red-velvet" data-parent="sheet">Red Velvet</option>
</select>

Заранее благодарим за любую помощь! Также приветствуются предложения по улучшению.

Ответы [ 2 ]

1 голос
/ 05 августа 2020

Я не знаю контекста этого кода, поэтому я понятия не имею, является ли этот шаблон «вложенных» параметров и выборок лучшим решением. Но вот моя версия javascript, которая, кажется, достигает того, что было задано в вопросе. Я прокомментирую соответствующие изменения, чтобы мой мыслительный процесс был ясен. Я также добавил css для класса hide, так как его не было в 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();

        //Call the update function with the data of the changed Select
        updateRecursivly(selClass, selName, selVal);

        //Recursive function to update all selects, this allows for multiple "child" selects per select and an in theory infinite "tree" of selects
        function updateRecursivly(selClass, selName, selVal) {
            //Search "children" of the parent select
            var children = $("select." + selClass + "[data-parent='" + selName + "']");
            if (children.length) {
                children.each(function () {
                    //Hide all options in the "child" select
                    $(this).children("option[data-parent]").hide();
                    //if selVal is an empty string, the default option is selected and we should just hide the "child" select
                    if (selVal !== "") {
                        //Get all options that contain (*=) selVal in "data-parent"
                        var options = $(this).children("option[data-parent*='" + selVal + "']");
                        //If there are possible options show the select and the possible options. Else hide select
                        if (options.length) {
                            $(this).removeClass('hide');
                            options.show();
                        } else {
                            $(this).addClass('hide');
                        }
                    } else {
                        $(this).addClass('hide');
                    }
                    //If the select is updated, the options should be reset. Any selected is reset and the first is selected
                    //From here https://stackoverflow.com/a/16598989/14040328 this is apparently safer against reset events than other solutions
                    $(this).children("option:selected").prop("selected", false);
                    $(this).children("option:first").prop("selected", "selected");

                    //Get the name of the select
                    var childName = $(this).attr("name");

                    //Update the Child select
                    updateRecursivly(selClass, childName, "");
                });
            }
        }
    });
});
.hide {
  display: none;
}

Я не уверен, переборщил ли я с комментариями или нет, если что-то неясно не стесняйтесь комментировать.

0 голосов
/ 05 августа 2020

Вы можете использовать attributeContainsWord (~) для сопоставления нескольких значений со словом. Итак, в приведенном ниже коде я использовал $(this).children("option[data-parent~='" + selVal + "']").show();, чтобы показать параметры, которые соответствуют selVal. Кроме того, я использую prop('selectedIndex', 0); для сброса выбора по умолчанию.

Демо-код :

$(document).ready(function() {
  $(".hide").children("option").hide();
  $("select").on('change', function() {
    //checking if dropdown is categories
    if ($(this).attr("name") == "categories") {
      //reset other to default
      $('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();
    //check if name != desserts
    if ($(this).attr("name") != "desserts") {
      //hide option of flavour
      $("select[name=flavors]").children("option").hide();
      //loop and show desire values
      $("select." + selClass + "[data-parent='" + selName + "']").each(function() {
        $(this).children("option[data-parent='" + selVal + "']").show();
        $(this).children("option[data-parent!='" + selVal + "']").hide();
      });

    } else {
      //hide options
      $("select[name=flavors]").children("option").hide();
      //loop through flavours
      $("select[name=flavors]").each(function() {
        //use " ~ " to see if the selval matches with values 
        $(this).children("option[data-parent~='" + selVal + "']").show();

      });

    }
  });
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<select class="group-1" name="categories">
  <option value="" selected="selected">Please select...</option>
  <option value="cookie">Cookies</option>
  <option value="cake">Cakes</option>
  <option value="icecream">Ice Cream</option>
</select>

<select class="group-1 hide" name="desserts" data-parent="categories">
  <option value="" selected="selected">Desserts...</option>
  <option value="1-dozen" data-parent="cookie">1 dozen</option>
  <option value="2-dozen" data-parent="cookie">2 dozen</option>
  <option value="sheet" data-parent="cake">Sheet</option>
  <option value="round" data-parent="cake">Round</option>
  <option value="pint" data-parent="icecream">Pint</option>
</select>

<select class="group-1 hide" name="flavors" data-parent="desserts">
  <option value="" selected="selected">Flavors...</option>
  <option value="choc-chip" data-parent="1-dozen 2-dozen">Chocolate Chip</option>
  <option value="oatmeal" data-parent="1-dozen 2-dozen">Oatmeal</option>
  <option value="yellow" data-parent="sheet round">Yellow</option>
  <option value="red-velvet" data-parent="sheet">Red Velvet</option>
</select>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...