jQuery and css: hide/show select options with a ce

2019-01-18 10:07发布

In the html code I have select options like this:

  <option value="1" class="myclass5">Value1</option>

In jQuery:

var cod = $(this).val(); // This is the value of another select: when the value 
$("option[class^=myclass]").hide();
$("option[class^=myclass]").each(function () {
    $("option[class^=myclass" + cod + "]").show();
});

EDIT

I have two select. When I select a value in the first select, the second one must be populated accordingly (I have to prevent an ajax call).

I put all the second select values in a session var, but my problem is in selecting only those ones tied to the first select, so I was trying through css classes.

EDIT2

<select name="firstselect">
   <option value="0" selected="selected">Choose...</option>
   <option value="1">Value1</option>
   <option value="2">Value2</option>
   <option value="3">Value3</option>
</select>

<select name="secondselect">
   <option value="0" selected="selected">Choose...</option>
   <option value="myclass1">Value11</option>
   <option value="myclass1">Value12</option>
   <option value="myclass1">Value13</option>
   <option value="myclass2">Value21</option>
   <option value="myclass2">Value22</option>
   <option value="myclass2">Value23</option>
   <option value="myclass3">Value31</option>
   <option value="myclass3">Value32</option>
   <option value="myclass3">Value33</option>
</select>

EDIT3

For me greenish's solution is good, but there is an issue on IE that I don't succeed in explaining: when I use the back button, the user selected value is "lost", that is, if I log on the console the user selected value, I see its "index" in the new cloned select. In the html source code, there is the whole original select.

EDIT4

I resolved thanks to this post

https://forum.jquery.com/topic/jquery-select-box-selectedindex-problems-in-internet-explorer-ie-on-refresh-and-back-buttons

5条回答
贪生不怕死
2楼-- · 2019-01-18 10:34

I'm not sure I completely understand your question but what about something like this:

$(document).ready(function(){
    var cod = '';
    $('select[name="firstselect"]').change(function(){
        cod = $(this).val();
        if ( cod > 0 ) {
            $('select[name="secondselect"] option').hide().filter(function(){
               return ( $(this).val().substr(7,1) == cod || $(this).val() == 0 ); 
            }).show();
        }
    });
});

http://jsfiddle.net/wVCcH/1/

Alternatively, the dynamic writing option also exists:

var dataset = [ 
    { set: 1, data: [
        { val: "value11", label: "Value 1 - 1" },
        { val: "value12", label: "Value 1 - 2" },
        { val: "value13", label: "Value 1 - 3" } ]
    },
    { set: 2, data: [
        { val: "value21", label: "Value 2 - 1" },
        { val: "value22", label: "Value 2 - 2" },
        { val: "value23", label: "Value 2 - 3" } ]
    }];

var chooser = "<option value='0' selected='selected'>Choose...</option>";

$('select[name="firstselect"]').change(function(){
    var n = $(this).val();                            //get value of data set
    if ( n != 0 ) {
       var str = chooser; n--;                        //0-based n
       for (i=0; i<dataset[n].data.length; i++) {     //write options
          str += "<option value='" + dataset[n].data[i].val + "'>" + dataset[n].data[i].label + "</option>"
        }
        $('select[name="secondselect"]').html(str).attr("disabled",false);
    }
});

http://jsfiddle.net/UNy9Z/4/

查看更多
在下西门庆
3楼-- · 2019-01-18 10:37

Include a javascript object that has a mapping of selections

this type of question comes up often in SPA development, and I've developed this approach. What I recommend is creating a javascript object with the different option lists, and object keys consisting of the names of the select fields which will cause sibling:after select fields to be dynamically created, by binding to the 'select' event of the dependent select element, and running a custom script to evaluate the selected option, parse your map, and then render options accordingly.

I've taken this concept, and created a pretty nifty shell, that should not only allow you to this between the two select elements you mention, but essentially allowing you to have as many depending select elements as you want... populating all of them based on the selection made in the dependent element. Here are the even cooler advantages:

  • the html markup is extremely clean
  • you can initialize dependencies on even the dynamically created dependee options
  • the javascript code is very clean and precise
  • this can easily be made modular, so it could be converted into a plugin or module with only a few lines of code
  • easy to asynchronously create new options and asynchronously alter dependencies using $.extend() and the provided SelectOption object
  • code is built in such a way that the different option lists can be injected into the map object by calling custom functions
  • will work on ANY ELEMENT that can trigger the select event. Allowing you to use non-form elements and inject dropdown type functionality and still affect other elements (**works with Bootstrap!

I have created a gist to demonstrate the concepts. I have the initial shell listed here, but check the link to ensure you have the most updated version and information on this gist. (I may turn it into a plugin)

https://gist.github.com/LongLiveCHIEF/7880119.js

form.html

<head>
  <script src="jquery.js"></script><!-- use .js for easier DOM manipulation, can be done without, using the native DOM api -->
  <script src="selection-map.js"></script>
</head>

    <body>
     <!-- select name="" values will be used inside the map object to initialize watch -->
     <!-- the custom data-selmap-cascade="" property initializes the dynamic functionality, and the value should be an
     -- string array format, where the values are the names of the select field whose options will depend on this
     -- elements selected option
     -->
     <select data-selmap-cascade="['secondselect','fourthselect']" name="firstselect">
        <option data-selmap-set-cascade="['second-select : set2', 'fourth-select : set1']" value="0" selected="selected">Choose...</option>
      <!-- list other options here, using the data-selmap-showselectfields settings for each dependent select field -->
      </select>
      <select class="selmap" name="secondselect">
        <!-- will be created via selection-map.js -->
       </select>
</body>

selection-map.js

// first we map our dependencies
var map = {
  secondselect: [ //high level keys are the fields that will cause cascades
      'set1' : {[new SelectOption('','','')],[new SelectOption('','','')],[new SelectOption('','','')]} // this is an option list, with gets a name as a key
      'set2' : {[new SelectOption('','','')],[new SelectOption('','','')],[new SelectOption('','','')]},
      'set3' : {[new SelectOption('','','')],[new SelectOption('','','')],[new SelectOption('','','')]},  
    ],

  fourthselect: [
      'set1' : {[new SelectOption('','','')],[new SelectOption('','','')],[new SelectOption('','','')]}
    ]

  };

// now we make it easy to inject select options at any point  
var SelectOption = function(text, value, dependenSelectFields){
  return {}; //retun object with properties corresponding to the attributes and values of a specific option
}

//and now we kick off processing

var $primaryElements = $.data('selmap-cascade'); // create a collection consisting of any and all elements with selmap-cascade data option

//here we act when any designated dependent field has a selection change
$primaryelements.select(function(){
  var mapkey = $(this + ':selected').data('selmap-set-cascade'); // get the data that will allow us to grab the proper select options for the dependent elements

  //and now we render the correct option into the correct place in the DOM

});
查看更多
The star\"
4楼-- · 2019-01-18 10:49

So when I understand your question correctly, you want to make the options of the second select field dependent of the selected value in the first select field.

I tried this quickly and hiding an option with css does not seem to work cross browser, even the latest version of chrome on mac won't hide the options.

So I came up with the following:

HTML first: I used classes to mark the dependencies. This allows the value attribute in the second select field to be used without restrictions.

Also, only options marked as conditional will be changed, the others won't be affected. This is useful for something like the Default value in this scenario.

<select id="firstSelect">
   <option value="0" selected="selected">Choose...</option>
   <option value="value1">Value1</option>
   <option value="value2">Value2</option>
   <option value="value3">Value3</option>
</select>

<select id="secondSelect">
   <option value="0" selected="selected">Choose...</option>
   <option class="conditional value1" value="subValue1">Value1: Sub1</option>
   <option class="conditional value2" value="subValue2">Value2: Sub1</option>
   <option class="conditional value2" value="subValue3">Value2: Sub2</option>
   <option class="conditional value2" value="subValue4">Value2: Sub3</option>
   <option class="conditional value2" value="subValue5">Value2: Sub4</option>
   <option class="conditional value2" value="subValue6">Value2: Sub5</option>
   <option class="conditional value3" value="subValue7">Value3: Sub1</option>
   <option class="conditional value3" value="subValue8">Value3: Sub2</option>
   <option class="conditional value3" value="subValue9">Value3: Sub3</option>
</select>

And the Javascript: To make this work, I copied the options of the secondSelect field and saved them in a variable. This allows me to actually remove options from the select field while I'm still able to retrieve the options from the copy.

$(function(){
    var conditionalSelect = $("#secondSelect"),
        // Save possible options
        options = conditionalSelect.children(".conditional").clone();

    $("#firstSelect").change(function(){
        var value = $(this).val();
        // Remove all "conditional" options               
        conditionalSelect.children(".conditional").remove();
        // Attach options that needs to be displayed for the selected value.
        options.clone().filter("."+value).appendTo(conditionalSelect);
    }).trigger("change");
});

And here's a fiddle that shows the script in action: http://jsfiddle.net/Kn8Gc/

Note: If you get Data form a database and the user already selected #firstSelect, just use the selected="selected" attribute. #secondSelect will automatically display the correct values. Just try the fiddle above and "preselect" for example value1 instead of 0!


Also here's a "generic" function that can be used easily to make any two select fields dependent on eachother (still using the classes conditional+ source value to make the relation):

// "Generic" function
$.conditionalize = function(sourceSelect, conditionalSelect){
    var options = conditionalSelect.children(".conditional").clone();

    sourceSelect.change(function(){
        var value = $(this).val();                  
        conditionalSelect.children(".conditional").remove();
        options.clone().filter("."+value).appendTo(conditionalSelect);
    }).trigger("change");
}

// Used like this:
$.conditionalize($("#firstSelect"), $("#secondSelect"));

And here it is in action: http://jsfiddle.net/NUxQ9/

查看更多
Melony?
5楼-- · 2019-01-18 10:52

Hiding an option is not defined in all browser. It is not defined in the W3C specification.

http://www.w3.org/TR/html401/interact/forms.html#h-17.6

Disabling the option based on first select value

You can disable the second option which will not allow the user to select the option.

DEMO: http://jsfiddle.net/HrpF2/

Code:

$(function () {
    var $secondOptions = $('select[name=secondselect] option');
    $("select[name=firstselect]").change(function () {
        var value = $(this).val();

        $secondOptions.prop('disabled', true).filter(function () {
            return this.value == 'myclass' + value;
        }).prop('disabled', false);
    }).trigger("change");
});

Show/Hide options based on first select value

If you really want to show/hide options, then you need to clone the second options and add them back based on the first select value. See below,

DEMO: http://jsfiddle.net/HrpF2/1/

Code:

$(function () {
    var $secondOptions = $('select[name=secondselect]');
    var $cloneOptions = $secondOptions.find('option').clone();
    $("select[name=firstselect]").change(function () {
        var value = $(this).val();

        $secondOptions.empty().append($cloneOptions.filter(function () {
            return this.value == 'myclass' + value;
        }));
    }).trigger("change");
});
查看更多
啃猪蹄的小仙女
6楼-- · 2019-01-18 10:52

The only way I got this to work across browsers was to detach and then re-attach the options. I added a class to each option to also break the value of the option apart from its grouping. These two things may be related, but I won't assume that.

<select name="firstselect" id="firstselect">
   <option value="0" selected="selected">Choose...</option>
   <option value="1">Value1</option>
   <option value="2" selected>Value2</option>
   <option value="3">Value3</option>
</select>

<select name="secondselect" id="secondselect">
   <option value="0">Choose...</option>
   <option value="myclass1" class="group1">Value11</option>
   <option value="myclass1" class="group1">Value12</option>
   <option value="myclass1" class="group1">Value13</option>
   <option value="myclass2" class="group2">Value21</option>
   <option value="myclass2" class="group2">Value22</option>
   <option value="myclass2" class="group2">Value23</option>
   <option value="myclass3" class="group3">Value31</option>
   <option value="myclass3" class="group3">Value32</option>
   <option value="myclass3" class="group3">Value33</option>
</select>

and the Javascript...

var groups = false;

function update_selected() {
  // reset the secondselect
  $("#secondselect").val(0);
  $("#secondselect").find("option[value!=0]").detach();

  // re-attach the correct options
  $("#secondselect").append(groups.filter(".group" + $(this).val()));
}

$(function() {
  // initialize by detaching all the options (except for the "Choose..." option)
  groups = $("#secondselect").find("option[value!=0]");
  groups.detach();

  // add the onchange event handler
  $("#firstselect").change(update_selected);

  // immediately call update_selected to update on page load
  $("#firstselect").trigger("change");
});

Fiddle: http://jsfiddle.net/JbVWV/8/

Edit - I added the call to $("#firstselected").trigger("change") on page load. So, if there is something selected in the first dropdown already, the second dropdown will already be populated correctly.

查看更多
登录 后发表回答