简体   繁体   English

动态过滤Vue.js中的对象数组

[英]Dynamically Filter an Array of Objects in Vue.js

I have a Vue.js app. 我有一个Vue.js应用程序。 In this app, I'm trying to dynamically apply filter value to an Array of objects. 在这个应用程序中,我正在尝试动态地将过滤器值应用于对象Array Each object in the Array has fields. 数组中的每个对象都有字段。 I'm trying to filter these objects by field values. 我试图通过字段值过滤这些对象。 Each field can be filtered by multiple values. 每个字段可以通过多个值进行过滤。

At this time, I have been unsuccessful in figuring out how to do this filtering. 目前,我还没有成功搞清楚如何进行这种过滤。 I've tried using JavaScript's baked-in filter function. 我尝试过使用JavaScript的烘焙filter功能。 However, that always returned an empty result set for me. 但是,这总是为我返回一个空结果集。 I've put together this Fiddle , which includes this code: 我把这个小提琴放在一起,其中包括以下代码:

new Vue({
  el: '#app',
  data: {
    currentFilterProperty: '',
    currentFilterValue: '',

    cols: [
      { title: 'Name', prop:'name' },
      { title: 'Age', prop:'age' },
      { title: 'Birthday', prop:'birthday' },      
    ],

    dataFilters: [],
    data: [
      { name:'Patricia Miller', age:69, birthday:'04-15-1948' },
      { name:'Bill Baggett', age:62, birthday:'05-07-1955' },      
      { name:'Maxine Thies', age:21, birthday:'11-28-1995' },      
      { name:'Alison Battle', age:65, birthday:'08-07-1952' },      
      { name:'Dick Triplett', age:25, birthday:'08-27-1982' } 
    ]
  },

  methods: {
    addFilter: function() {
      var f = this.dataFilters[this.currentFilterProperty];
      if (!f) {
        this.dataFilters = {};
        this.dataFilters[this.currentFilterProperty] = [ this.currentFilterValue ];
      } else {
        this.dataFilters[this.currentFilterProperty].push(this.currentFilterValue);
      }

      // How to apply filter?
    }
  }
})

I'm not sure how to apply the filters to the data object. 我不确定如何将过滤器应用于data对象。

Complete solution. 完整解决方案 Best test: add filter Age 62, then Birthday 04-15-1948, then 'tri' in Name Patricia. 最佳测试:添加过滤器年龄62,然后生日04-15-1948,然后在名称Patricia中添加'tri'。

 new Vue({ el: '#app', data: { filteredProperty: 'name', query: '', activeFilters: [], data: [ {name: 'Patricia Miller', age: 62, birthday: '04-15-1948'}, {name: 'Bill Baggett', age:62, birthday: '04-15-1948' }, {name:'Maxine Thies', age:62, birthday:'11-28-1948'}, {name:'Alison Battle', age:65, birthday:'08-07-1952'}, {name:'Dick Triplett', age:25, birthday:'08-27-1982'} ] }, computed: { filtered () { var filtered = this.data this.activeFilters.forEach(filter => { filtered = filtered.filter(record => { return filter.name === 'name' ? new RegExp(filter.value, 'i').test(record[filter.name]) : record[filter.name] == filter.value }) }) return filtered } }, methods: { addFilter () { this.activeFilters.push({ name: this.filteredProperty, value: this.query }) this.query = '' }, removeFilter (idx) { this.activeFilters.splice(idx, 1) } } }) 
 <div id="app"> <div> <select v-model="filteredProperty"> <option value="name">Name</option> <option value="age">Age</option> <option value="birthday">Birthdate</option> </select> <input placeholder="filter value" v-model="query"> <button @click="addFilter">add filter</button> </div> <hr> <table v-if="activeFilters.length"> <tr style="width: 100px"> <th colspan="3">Filters in use:</th> </tr> <tr v-for="(filter, index) in activeFilters" :key="index"> <td>{{ _.capitalize(filter.name) }}:</td> <td>{{ filter.value }}</td> <td style="padding-left: 10px;"> <a href="#" @click.prevented=removeFilter(index)> remove </a> </td> </tr> </table> <hr v-if="activeFilters.length"> <table> <tbody> <tr v-for="(record, index) in filtered" :key="index"> <td style="padding-right:18px;">{{ record.name }}</td> <td style="padding-right:18px;">{{ record.age }}</td> <td>{{ record.birthday }}</td> </tr> </tbody> </table> </div> <script src="https://unpkg.com/vue"></script> <script src="https://unpkg.com/lodash"></script> 

Take a look the below code. 看看下面的代码。 Change your method to a computed property and then the filter can happen automatically without pressing a button. 将您的方法更改为计算属性,然后过滤器可以自动发生而无需按下按钮。 The fiddle always filters by Name so you'll need to make a few adjustments to work for all filter criteria, but it should get you moving in the correct direction. 小提琴总是按名称进行过滤,因此您需要进行一些调整以适用于所有过滤条件,但它应该让您朝着正确的方向前进。

 new Vue({ el: '#app', data: { currentFilterProperty: '', currentFilterValue: '', cols: [ { title: 'Name', prop:'name' }, { title: 'Age', prop:'age' }, { title: 'Birthday', prop:'birthday' } ], data: [ { name:'Patricia Miller', age:69, birthday:'04-15-1948' }, { name:'Bill Baggett', age:62, birthday:'05-07-1955' }, { name:'Maxine Thies', age:21, birthday:'11-28-1995' }, { name:'Alison Battle', age:65, birthday:'08-07-1952' }, { name:'Dick Triplett', age:25, birthday:'08-27-1982' } ] }, computed:{ filteredData(){ var self = this; // Add condition for currentFilterProperty == 'Name' if(this.currentFilterValue != undefined && this.currentFilterValue != ''){ return this.data.filter(function(d){ //alert(d.name + " " + this.currentFilterValue); return d.name.indexOf(self.currentFilterValue) != -1; }); } // else if(currentFilterProperty == 'Date'){ // return this.data.filter(function(d){ //return d.birthday.indexOf(self.currentFilterValue) != -1; // }); else{ return this.data; } } } }) 
 <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.4/vue.min.js"></script> <div id="app"> <div> <select v-model="currentFilterProperty"> <option v-for="c in cols" :value="c.prop">{{c.title}}</option> </select> <input placeholder="filter value" v-model="currentFilterValue" /> </div> <hr /> <table> <tbody> <tr v-for="(record, index) in filteredData"> <td style="padding-right:18px;">{{ record.name }}</td> <td style="padding-right:18px;">{{ record.age }}</td> <td>{{ record.birthday }}</td> </tr> </tbody> </table> </div> 

Here is working solution By checking captaining condition 这是工作解决方案通过检查captaining条件

 new Vue({ el: '#app', data: { currentFilterProperty: 'name', currentFilterValue: '', filteredData:[], cols: [ { title: 'Name', prop:'name' }, { title: 'Age', prop:'age' }, { title: 'Birthday', prop:'birthday' }, ], dataFilters: [], addFilters:[], data: [ { name:'Patricia Miller', age:69, birthday:'04-15-1948' }, { name:'Bill Baggett', age:62, birthday:'05-07-1955' }, { name:'Maxine Thies', age:21, birthday:'11-28-1995' }, { name:'Alison Battle', age:65, birthday:'08-07-1952' }, { name:'Dick Triplett', age:25, birthday:'08-27-1982' } ] }, methods: { addFilter: function() { if(!this.currentFilterValue){ return false; } var obj = {}; this.addFilters.push({name:this.currentFilterProperty,value:this.currentFilterValue}); this.currentFilterValue = ""; var vm = this; this.dataFilters = this.data //var temp = []; for(var i in vm.addFilters){ this.dataFilters = this.dataFilters.filter(function(a,b){ return ((a[vm.addFilters[i].name]).toString().toLowerCase()).indexOf((vm.addFilters[i].value).toString().toLowerCase()) !== -1; }); } // How to apply filter? } }, mounted(){ this.dataFilters = this.data; } }) 
 <script src="https://unpkg.com/vue"></script> <div id="app"> <div> <select v-model="currentFilterProperty"> <option value="name">Name</option> <option value="age">Age</option> <option value="birthday">Birthdate</option> </select> <input placeholder="filter value" v-model="currentFilterValue" /> <button v-on:click="addFilter"> add filter </button> </div> <div v-for="(filter,index) in addFilters">{{filter.name}} : {{filter.value}}</div> <hr /> <table> <tbody> <tr v-for="(record, index) in dataFilters"> <td style="padding-right:18px;">{{ record.name }}</td> <td style="padding-right:18px;">{{ record.age }}</td> <td>{{ record.birthday }}</td> </tr> </tbody> </table> </div> 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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