【问题标题】:Cascade dropdown using JS not working使用JS的级联下拉菜单不起作用
【发布时间】:2016-12-24 20:40:21
【问题描述】:

我有 3 个下拉列表,这些值是用 mysql 动态填充的。现在,我正在尝试级联 3 下拉菜单,但 JS 脚本不起作用。

我想做的是:

案例 1:如果用户从下拉列表 #1 中选择一个值,下拉列表 #2 的值取决于下拉列表 #1,下拉列表 #3 的值取决于下拉列表 #2。例如。州-市-大道

案例 2:用户可以从 3 个下拉菜单中进行选择。

案例 3 和 4:如果用户从下拉列表 #2 中选择,下拉列表 #3 的值取决于下拉列表 #2(但如果下拉列表 #2 已经存在,则在下拉列表 #3 中选择一个值是可选的)

表格:

<form action='' method='post' id='loc'>
<select name="state" id="filter_region" class="state">
    <option name="default" class="default" value="State" readonly>State</option>
    <?php
    foreach($result_state as $option){
        if(isset($_POST['state']) && $_POST['state'] == $option->state)
            echo '<option name="state" class="filter_by" selected value="'. $option->state .'">'. $option->state .'</option>';
        else    
         echo '<option name="state" class="filter_by" value="'. $option->state .'">'. $option->state .'</option>';
     };
    ?>
</select>

<select name="city" id="filter_city" class="city">
    <option name="default" class="default" value="City" readonly>City</option>
    <?php
    foreach($result_city as $option){
        if(isset($_POST['city']) && $_POST['city'] == $option->city)
            echo '<option name="city" class="filter_by" selected value="'. $option->city .'">'. $option->city .'</option>';
        else    
         echo '<option name="city" class="filter_by" value="'. $option->city .'">'. $option->city .'</option>';
     };
    ?>
</select>
<select name="avenue" id="filter_mall" class="avenue">
    <option name="default" class="default" value="Avenue" readonly>Avenue</option>
    <?php 
    foreach($result_avenue as $option){
        if(isset($_POST['avenue']) && $_POST['avenue'] == $option->avenue)
            echo '<option name="avenue" class="default" selected value="'. $option->avenue .'">'. $option->avenue .'</option>';
        else    
         echo '<option name="avenue" class="filter_by" value="'. $option->avenue .'">'. $option->avenue .'</option>';
     };
    ?>
</select>
<input type="submit" value="submit" class="submit"/>
</form>

JS:

function cascadeSelect(parent, child){
    var childOptions = child.find('option:not(.default)');
    child.data('options',childOptions);

    parent.change(function(){
        childOptions.remove();
        child
            .append(child.data('options').filter('.filter_by' + this.value))
            .change();
    })

    childOptions.not('.default, .filter_by' + parent.val()).remove();
}

$(function(){
    cascadeForm = $('.loc');
    state= cascadeForm.find('.state');
    city= cascadeForm.find('.city');
    avenue= cascadeForm.find('.avenue');

    cascadeSelect(state, city);
    cascadeSelect(city, avenue);
});

【问题讨论】:

    标签: javascript php jquery drop-down-menu cascadingdropdown


    【解决方案1】:

    我创建了级联父子选择框using AngularJS,但由于您使用的是 NativeJS,我尝试使用 JS 重新创建。我的解决方案的先决条件是一个定义明确的 JSON,将基于该 JSON 创建选择框。您必须在服务器端或手动或在创建选择框数据的任何位置创建 JSON。下面是 JSON 格式:

    每个选择框都是一个具有以下属性的命名对象:

    1. 父属性:对象的名称,它是此选择框对象的父对象。
    2. 选项:选项对象数组,其中每个对象包含: (a) 选项值 (b) 父选项值 - 映射当前值的父选择框值。 (c) 选项 ID。

    3. 选定选项:具有两个属性的对象:(a) 当前选定值 (b) 当前选定值的 ID。

    这是解决方案的working Plunker。希望对您有所帮助。

    ----- 编辑:-----

    应@User014019 的要求

    Here 是此下拉解决方案的另一个版本,其中所有选择框中的所有选项最初都是可见的,并且在用户选择特定值时设置父子关系。


    下面是代码:

    // reads the data and creates the DOM elements (select-boxes and their relevant options)
    function initSelect(data) {
      var select, option, input, filteredOptions;
      for (var key in data) {
        select = document.createElement("select");
        select.name = key;
        container.appendChild(select);
        filteredOptions = optionFilter(data[key].availableOptions, data[data[key].parent], data[key]);
        input = document.querySelector('select[name="' + key + '"');
        input.setAttribute("onchange", "updateSelect(this)");
        for (var i = 0; i < filteredOptions.length; i++) {
          option = document.createElement("option");
          option.value = filteredOptions[i].value;
          option.innerHTML = filteredOptions[i].value;
          input.appendChild(option);
        }
        input.options.selectedIndex = getSelectedIndex(filteredOptions, data[key]);
        input.setAttribute('model', data[key].selectedOption.value);
      }
    }
    
    
    // this function will be called on change of select-box
    function updateSelect(element) {
      var input, option;
      setSelectedOption(element);
      for (var key in data) {
        filteredOptions = optionFilter(data[key].availableOptions, data[data[key].parent], data[key]);
        input = document.querySelector('select[name="' + key + '"');
        while (input.firstChild) {
          input.removeChild(input.firstChild);
        }
        for (var i = 0; i < filteredOptions.length; i++) {
          option = document.createElement("option");
          option.value = filteredOptions[i].value;
          option.innerHTML = filteredOptions[i].value;
          input.appendChild(option);
        }
        input.options.selectedIndex = getSelectedIndex(filteredOptions, data[key]);
        input.setAttribute('model', data[key].selectedOption.value);
      }
    }
    
    // set the selected-option of select-box when it's changed
    function setSelectedOption(element) {
      var inputName = element.getAttribute("name");
      var inputValue = getSelectedText(element);
      var inputItem = data[inputName];
      var selectedOption, filteredOptions;
    
      // setting selected option of changed select-box
      for (var i = 0; i < inputItem.availableOptions.length; i++) {
        if (inputValue === inputItem.availableOptions[i].value) {
          inputItem.selectedOption = inputItem.availableOptions[i];
          break;
        }
      }
      // setting child object selected option now
      for (var key in data) {
        if (data[key].parent === inputName) {
          filteredOptions = optionFilter(data[key].availableOptions, data[data[key].parent], data[key]);
          data[key].selectedOption = filteredOptions[0];
        }
      }
    }
    
    // get the text of select-box
    function getSelectedText(element) {
      if (element.selectedIndex == -1) {
        return null;
      }
      return element.options[element.selectedIndex].text;
    }
    
    function getSelectedIndex(options, self) {
      var index;
      for (var i = 0; i < options.length; i++) {
        if (self.selectedOption.value === options[i].value) {
          index = i;
          break;
        }
      }
      return index;
    }
    
    // get filtered options based on parent's selected value
    function optionFilter(items, parent, self) {
      var result = [];
      if (typeof parent !== "undefined") {
        for (var i = 0; i < items.length; i++) {
          if (typeof parent.selectedOption !== "undefined") {
            if (parent.selectedOption !== null && items[i].parentValue === parent.selectedOption.value) {
              result.push(items[i]);
            }
          }
        }
        if (typeof self.selectedOption === "undefined") {
          self.selectedOption = null;
        }
        if (self.selectedOption === null) {
          self.selectedOption = result[0];
        }
        return result;
      } else {
        return items;
      }
    }
    

    【讨论】:

    • 如何在你的 js 中使用我现有的下拉模板?
    • 如何使用mysql中的数据?
    • 我发布的解决方案完全取决于我使用的数据结构(在帖子中解释)。并且 HTML 生成是完全动态的(没有手动或静态的 HTML 代码)。如果您希望使用此解决方案,则必须重新构建完整的代码。至于MySql,能否请您详细说明您的问题。
    • 每个下拉菜单的数据都是从 mysql dbase 中实现的。如果来自 mysql dbase,我如何调用 function getData() 中的数据?
    • 您目前如何在客户端获取 MySql 数据?您是否使用任何中间层?
    猜你喜欢
    • 1970-01-01
    • 2018-10-22
    • 1970-01-01
    • 2016-09-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多