简体   繁体   中英

How to filter / clone select box options with jQuery?

I have the following two select boxes:

<select id="project">
  <option data-person_ids="[75,76,77]">None</option>
  <option data-person_ids="[77]">Project A</option>
  <option data-person_ids="[75,76]">Project B</option>
  <option data-person_ids="[75]">Project C</option>
</select>

<select id="person">
  <option value="75">Person A</option>
  <option value="76">Person B</option>
  <option value="77">Person C</option>
</select>

How can I filter the #person options based on the value selected in #project ?

This is a jQuery code snippet that a colleague came up with but I was unable to get it working because I am still new to jQuery:

$(function() {

  var $person = $('#person');

  $allPersonOptions = $person.children();

  $('#project').on('change', function() {
    var selected_project = $('#project').data('person_ids');
    filterOptions($allPersonOptions.clone(), +selected_project).appendTo($person.empty());
  });

});

function filterOptions($options, id) {
  return $options.filter(function() {
    return $.inArray(id, $(this).data('project_ids')) > -1
  });
}

Thanks for any help in this matter.

Well your colleague gave you bad code.

First

var selected_project = $('#project').data('person_ids');

will return undefined since it is not on the select, it is on the option. It does not magically get the selected option's data attribute

var selected_project = $('#project option:selected').data('person_ids');

Next there is a random + in the code

filterOptions($allPersonOptions.clone(), +selected_project).appendTo($person.empty());
                                        ^^^

That is going to do a conversion, bad.

Next the filter code is looking for a data attribute

return $.inArray(id, $(this).data('project_ids')) > -1

There is no data attribute on that select's options. And the arguments are switched.

 $(function() { var $person = $('#person'); $allPersonOptions = $person.children(); $('#project').on('change', function() { var selected_project = $('#project option:selected').data('person_ids'); filterOptions($allPersonOptions.clone(), selected_project).appendTo($person.empty()); }); }); function filterOptions($options, id) { return $options.filter(function() { return $.inArray(parseInt(this.value,10), id) > -1 }); } 
 <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script> <select id="project"> <option data-person_ids="[75,76,77]">None</option> <option data-person_ids="[77]">Project A</option> <option data-person_ids="[75,76]">Project B</option> <option data-person_ids="[75]">Project C</option> </select> <select id="person"> <option value="75">Person A</option> <option value="76">Person B</option> <option value="77">Person C</option> </select> 

I have a version that reuses allPersonOptions (no need to clone) and only copies applicable options.

 $(function() { var $person = $('#person'); $allPersonOptions = $person.children(); $('#project').on('change', function() { var ids = $('#project option:selected').data('person_ids'); $person.empty(); $allPersonOptions.each( function() { var id = parseInt($(this).attr('value')); if ($.inArray(id, ids) != -1 ) $person.append(this); }) }); }); 
 <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script> <select id="project"> <option data-person_ids="[75,76,77]">None</option> <option data-person_ids="[77]">Project A</option> <option data-person_ids="[75,76]">Project B</option> <option data-person_ids="[75]">Project C</option> </select> <select id="person"> <option value="75">Person A</option> <option value="76">Person B</option> <option value="77">Person C</option> </select> 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM