根据多项选择过滤对象数组

时间:2019-08-03 12:54:28

标签: javascript

我有一个看起来像这样的对象数组

[
    {
        id: 101,
        name: 'Alex',
        tg: 'REV001',
        eng: 'IP'
    },
    {
        id: 102,
        name: 'Bob',
        tg: 'REV002',
        eng: 'CAD'
    },
    {
        id: 103,
        name: 'Carl',
        tg: 'REV001',
        eng: 'OPP'
    },
    {
        id: 104,
        name: 'Dave',
        tg: 'REV003',
        eng: 'IP'
    },
    {
        id: 105,
        name: 'Jeffry',
        tg: 'REV005',
        eng: 'OPP'
    },
]

我也有3个选择框,就像

// Name select
<select>
  <option value="">All</option>
  <option value="Alex">Alex</option>
  <option value="Bob">Bob</option>
  <option value="Carl">Carl</option>
  <option value="Dave">Dave</option>
  <option value="Jeffry">Jeffry</option>
</select>

// TG select
<select>
  <option value="">All</option>
  <option value="REV001">REV001</option>
  <option value="REV002">REV002</option>
  <option value="REV003">REV003</option>
  <option value="REV005">REV005</option>
</select>

// ENG select
<select>
  <option value="">All</option>
  <option value="IP">IP</option>
  <option value="CAD">CAD</option>
  <option value="OPP">OPP</option>
</select>

这些选择框显示了数组中存在的所有可能值,并根据名称,TG和ENG进行了分类。

我想根据这些选择输入中的选项来过滤数据。

例如,

如果我拥有全部名称,ENG全部和TG REV001,那么它应该过滤数据数组并获得一个新数组,其中只有TG为REV001的对象。

我已经有一些要求更改值的事件,只是想知道如何根据所选选项过滤数据的逻辑。该函数应从原始数据中返回一个新的过滤数据数组。

我尝试创建一个变量

  filteredSearch: any = {
    NAME: 'All',
    ENG: 'All',
    TG: 'All'
  }

并编写了

之类的方法
  onFilterSearch() {
    this.filteredList = [];
    this.requestData.forEach(element => {
      for (let key in this.filteredSearch) {
        if (!(this.filteredSearch[key] === '')) {
          if (element.header[key].includes(this.filteredSearch[key])) {
            this.filteredList.push(element);
          }
        } 
      }
    });
  }

随着选择输入的更改,我正在更改filteredSearch并调用onFilterSearch()。但这对我不起作用,也许我在这里错过了一些东西。

2 个答案:

答案 0 :(得分:2)

请在下面找到逻辑和代码段

逻辑:

var filteredData = data.filter(e => { 
  return (!nameSelect || e.name === nameSelect) && (!tgSelect || e.tg === tgSelect) && (!engSelect || e.eng === engSelect);
});

代码段:

// Name select
<select id="nameSelect">
  <option value="">All</option>
  <option value="Alex">Alex</option>
  <option value="Bob">Bob</option>
  <option value="Carl">Carl</option>
  <option value="Dave">Dave</option>
  <option value="Jeffry">Jeffry</option>
</select>
// TG select
<select id="tgSelect">
  <option value="">All</option>
  <option value="REV001">REV001</option>
  <option value="REV002">REV002</option>
  <option value="REV003">REV003</option>
  <option value="REV005">REV005</option>
</select>
// ENG select
<select id="engSelect">
  <option value="">All</option>
  <option value="IP">IP</option>
  <option value="CAD">CAD</option>
  <option value="OPP">OPP</option>
</select>
<br/>
<button id="filterBtn" type="button">Filter</button>
<script>
var data = [
    {
        id: 101,
        name: 'Alex',
        tg: 'REV001',
        eng: 'IP'
    },
    {
        id: 102,
        name: 'Bob',
        tg: 'REV002',
        eng: 'CAD'
    },
    {
        id: 103,
        name: 'Carl',
        tg: 'REV001',
        eng: 'OPP'
    },
    {
        id: 104,
        name: 'Dave',
        tg: 'REV003',
        eng: 'IP'
    },
    {
        id: 105,
        name: 'Jeffry',
        tg: 'REV005',
        eng: 'OPP'
    },
];

function filterData(data) {
  var nameSelect = document.getElementById("nameSelect");
  nameSelect = nameSelect.options[nameSelect.selectedIndex].value;
  var tgSelect = document.getElementById("tgSelect");
  tgSelect = tgSelect.options[tgSelect.selectedIndex].value;
  var engSelect = document.getElementById("engSelect");
  engSelect = engSelect.options[engSelect.selectedIndex].value;
  var filteredData = data.filter((e) => { 
    return (!nameSelect || e.name === nameSelect) && (!tgSelect || e.tg === tgSelect) && (!engSelect || e.eng === engSelect);
  });
  console.log(filteredData);
}

document.getElementById("filterBtn").addEventListener("click", e => {
  filterData(data);
});
</script>

答案 1 :(得分:1)

通过将currentFilter定义为对象而不是数组(并通过在JavaScript的相应列表中构建<select>元素以确保HTML永不超出标准),可以使此解决方案更加健壮与脚本同步),但它可以按原样处理您的用例。

// Defines globals
const lists = {
  name: "Alex,Bob,Carl,Dave,Jeffry".split(","),
  tg:   "REV001,REV002,REV003,REV004,REV005".split(","),
  eng:  "IP,CAD,OPP".split(",")
};
let data = [
    { id: 101, name: 'Alex',   tg: 'REV001', eng: 'IP'  },
    { id: 102, name: 'Bob',    tg: 'REV002', eng: 'CAD' },
    { id: 103, name: 'Carl',   tg: 'REV001', eng: 'OPP' },
    { id: 104, name: 'Dave',   tg: 'REV003', eng: 'IP'  },
    { id: 105, name: 'Jeffry', tg: 'REV005', eng: 'OPP' },
];
const dropdowns = document.getElementsByClassName("filterable");

// Runs the `filterData` function when the user changes something
document.addEventListener("change", filterData);

// Defines the `filterData` function
function filterData(event){

  // Converts the NodeList to an Array so we can use the `.includes`,
  //   `.map`, and `.filter` methods
  const dropdownArr = Array.from(dropdowns);

  // Makes sure the changed element was one we care about before proceeding
  if(dropdownArr.includes(event.target)){

    // Makes a new array from the selected values
    const currentFilter = dropdownArr.map(dropdownArr => dropdownArr.value);

    // Makes a new (filtered) array by applying each element of `currentFilter`
    //   to its respective property in each element of `data`
    //   (This is the fragile bit because it assumes the order is correct.)
    const output = data.filter(item =>
      (!currentFilter[0] || currentFilter[0] == item.name) &&
      (!currentFilter[1] || currentFilter[1] == item.tg) &&
      (!currentFilter[2] || currentFilter[2] == item.eng)
    );

    // Does something with the filtered data
    console.log(output.length > 0 ? output : "No matching results");
  }
}
<select id="name" class="filterable">
  <option value="">All</option>
  <option value="Alex">Alex</option>
  <option value="Bob">Bob</option>
  <option value="Carl">Carl</option>
  <option value="Dave">Dave</option>
  <option value="Jeffry">Jeffry</option>
</select>
<select id="tg" class="filterable">
  <option value="">All</option>
  <option value="REV001">REV001</option>
  <option value="REV002">REV002</option>
  <option value="REV003">REV003</option>
  <option value="REV005">REV005</option>
</select>
<select id="eng" class="filterable">
  <option value="">All</option>
  <option value="IP">IP</option>
  <option value="CAD">CAD</option>
  <option value="OPP">OPP</option>
</select>