最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Dynamically Filter an Array of Objects in Vue.js - Stack Overflow

programmeradmin5浏览0评论

I have a Vue.js app. In this app, I'm trying to dynamically apply filter value to an Array of objects. 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. 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.

I have a Vue.js app. In this app, I'm trying to dynamically apply filter value to an Array of objects. 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. 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.

Share Improve this question asked Nov 17, 2017 at 15:44 user687554user687554 11.2k26 gold badges83 silver badges142 bronze badges
Add a ment  | 

3 Answers 3

Reset to default 13

Complete solution. Best test: add filter Age 62, then Birthday 04-15-1948, then 'tri' in Name Patricia.

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'}
    ]
  },
  puted: {
    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./vue"></script>
<script src="https://unpkg./lodash"></script>

Take a look the below code. Change your method to a puted 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' } 
    ]
  },
  puted:{
  	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./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

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./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>

发布评论

评论列表(0)

  1. 暂无评论