如何使用jQuery根据多个数据属性筛选列表项?

3

这是我的HTML代码,包含所有的过滤器:

  <div class="search-filters">
    <div class="filter-block">
      <label for="employee_type">Employee Type</label>
      <select id="employee_type" class="category">
        <option value="0">All</option>
        <option value="designer">Designer</option>
        <option value="manager">Manager</option>
        <option value="developer">Developer</option>
        <option value="quality-assurance">Quality Assurance</option>
      </select>
    </div>
    <div class="filter-block">
      <label for="years_xp">Years Experience</label>
      <select id="years_xp" class="category">
        <option value="0">Select years Experience</option>
        <option value="1">1 year</option>
        <option value="2">2 years</option>
        <option value="3">3 years</option>
      </select>
    </div>

  </div>

我的结果列表如下:
 <ul class="result-set">
   <li class="result" data-employee-type="designer" data-xp="3" >John Smith</li>
   <li class="result" data-employee-type="manager" data-xp="2" >Billy Joe</li>
   <li class="result" data-employee-type="developer" data-xp="5" >John Appleseed</li>
 </ul>

我想使用jQuery和数据属性以及选择下拉框的改变来过滤结果。目前,我的jQuery代码只能支持其中一个过滤器的工作。我尝试在jQuery中使用.filter函数,但它仍然只适用于一个下拉框的更改。如果我更改两个下拉框,它似乎会忽略一个条件。

我的jQuery代码如下:

var category_filters = [];

$('.category').on('change', function() {
    category_filters = [];

    $('.search-filters select').each(function() {
        if ($(this).val() != 0) {
            var category = $(this).val();
            category_filters[$(this).attr('id')] = category;
        }
    });

    var employee_type = "";
    var years_xp = "";

    if ('employee_type' in category_filters) {
        employee_type = category_filters['employee_type'];
    }
    if ('years_xp' in category_filters) {
        years_xp = category_filters['years_xp'];
    }

    $(".result-set .result").hide().filter(function() {
        if (employee_type != "") {
            if ($(this).attr('data-employee-type') == employee_type) {
                return true;
            }
        }
        if (years_xp != "") {
            if ($(this).attr('data-xp') == years_xp) {
                return true;
            }
        }
    }).show();

});

我做错了什么?我已经卡在这个问题上将近6个小时了,看了其他的例子但是它们似乎不适用于我的情况。


如果('employee_type' in category_filters)这并不是你想象中的那样。例如:'length' in [] 返回true。 - Farzher
看起来运行良好,只是过滤器与“或”条件结合。你想要变成“AND”吗?https://jsfiddle.net/04v4bqw5/ - Pevara
@StephenBugsKamenar 嗯,当我在那个if语句内部使用console.log打印出'employee_type'变量时,我得到了从下拉菜单返回的当前值,并将其分配给数组'category_filters'中的适当键值对。所以这部分应该是有效的。 - James Ramputh
@Pevara 是的,我希望它是一个AND。 - James Ramputh
3个回答

2

好的,所以你希望两个过滤器同时应用,而不仅仅在单个过滤器匹配时显示一个项目。在您的过滤功能中,一旦找到匹配项,您就会立即返回true,因此问题就出在这里。

我稍微更新了您的代码:

$('.category').on('change', function() {
  var category_filters = [];

  $('.search-filters select').each(function() {
    if ($(this).val() != 0) {
      category_filters[$(this).attr('id')] = $(this).val();
    }
  });

  $(".result-set .result").hide().filter(function() { 
    var show = true;
    for (var category in category_filters) {
       show = show && $(this).data(category) == category_filters[category];
    }

    return show;
  }).show();

});

以下是需要翻译的内容:

这里有个演示:https://jsfiddle.net/04v4bqw5/1/

你会注意到我还进行了一些重构。这段代码假定过滤器的id与你想要应用过滤器的数据属性的名称完全匹配,因此请务必检查更新后的HTML。

Javascript代码中的重复情况明显减少,您可以添加尽可能多的额外过滤器和匹配数据属性,它们会在不更改Javascript的情况下工作。

至于过滤函数,让我添加一些注释以解释:

// assume we'll want to show the item
var show = true;
// go over each active filter
for (var category in category_filters) {
   // check if the filter value matches the data attribute value, and any
   // previous filters did not exclude this item yet (show &&)
   show = show && $(this).data(category) == category_filters[category];
}

return show;

非常感谢,这对我帮助很大!而且你发现数据属性和选择的ID不匹配是一个好的发现。我完全忽视了它。 - James Ramputh

1
你得到这个结果的原因是由于return true;的行为。可以将其视为break语句 - 一旦在.filter函数中达到此点,它会认为它的工作已经完成,可以停止处理。为了克服这个问题,使用一些本地布尔值,然后在函数末尾评估它们来决定是否返回true或false:
var etMatch = false, xpMatch = false;

if (employee_type != "") {
    if ($(this).attr('data-employee-type') == employee_type) {
        etMatch = true;
    }
}

if (years_xp != "") {
    if ($(this).attr('data-xp') == years_xp) {
        xpMatch = true;
    }
}

if (etMatch && xpMatch) { return true; }

0

你应该使用每个过滤器的函数进行比较:

var compare = {
  "employee-type": function(a,b) { return a===b},
  "years-xp": function(a,b) { return (1*a)<=(1*b) }
}

$(".result-set .result").show().filter(function() {

  var self = this;

  return 
    !Object
     .keys(category_filters)
     .reduce( function(result, i) {

       var filterValue = category_filters[i];
       var itemValue = $(self).attr('data-'+i);

       return result && compare[ i ]( filterValue, itemValue)

     }, true)

}).hide();

[ https://jsfiddle.net/qqc9w4xm/ ]

的内容与编程有关。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接