Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I search through multiple fields in Vue.js 2

I am trying to search or filter through 3 fields firstname, lastname and email in my Vue.js 2 application. I understand that Vue 2 does not come with a built in filter method unlike in Vue 1, hence I created a custom method which is only able to filter through just one field. How do I extend this to multiple fields? I have tried something like this filterBy(list, value1, value2, value3) but it does not work.

This is my code

<template>
<div class="customers container">
<input class="form-control" placeholder="Enter Last Name" v-
model="filterInput">
<br />
<table class="table table-striped">
  <thead>
    <tr>
      <th>First Name</th>
      <th>Last Name</th>
      <th>Email</th>
      <th></th>
    </tr>
  </thead>
  <tbody>
    <tr v-for="customer in filterBy(customers, filterInput)">
      <td>{{customer.first_name}}</td>
      <td>{{customer.last_name}}</td>
      <td>{{customer.email}}</td>
      <td><router-link class="btn btn-default" v-bind:to="'/customer/'+customer.id">View</router-link></td></tr>
  </tbody>
</table>

</div>
</template>

<script>

export default {
name: 'customers',
data () {
return {

  customers: [],
  filterInput:'',

}
},

methods: {
fetchCustomers(){
  this.$http.get('http://slimapp.dev/api/customers')
    .then(function(response){

      this.customers = (response.body); 
    });
 },

 filterBy(list, value){
    value = value.charAt(0).toUpperCase() + value.slice(1);
    return list.filter(function(customer){
      return customer.last_name.indexOf(value) > -1;
    });
  },


  },

  created: function(){
  if (this.$route.params.alert) {
  this.alert = $route.params.alert
  }
  this.fetchCustomers();
  },

  updated: function(){
  this.fetchCustomers();
  },
  components: {

  }
  }
  </script>

  <!-- Add "scoped" attribute to limit CSS to this component only -->
  <style scoped>

like image 433
Caleb Oki Avatar asked Jan 29 '23 03:01

Caleb Oki


2 Answers

Extend your filterBy method to check more then just last_name

filterBy(list, value){
    value = value.charAt(0).toUpperCase() + value.slice(1);
    return list.filter(function(customer){
      return customer.first_name.indexOf(value) > -1 ||
             customer.last_name.indexOf(value) > -1 ||
             customer.email.indexOf(value) > -1
    });
  },

But you can use computed to provide filtered results (it might perform better because it caches computations)

computed: {
  filteredList() {
    const value= this.filterInput.charAt(0).toUpperCase() + this.filterInput.slice(1);
    return this.customers.filter(function(customer){
      return customer.first_name.indexOf(value) > -1 ||
             customer.last_name.indexOf(value) > -1 ||
             customer.email.indexOf(value) > -1
    })
  }
}

and use it in your template

<tr v-for="customer in filteredList">
 ...
</tr>
like image 99
Piotr Pasieka Avatar answered Feb 03 '23 08:02

Piotr Pasieka


The above method finds all strings STARTING with the word you are looking for and ignores all middle-sentence words.

This means that if you have a customer like Vincent Van Patten you will only find it by searching for Vincent or Vincent(space)Van. If you search for the word Van or Patten it will return an empty search because you are using indexOf inside filter.

This is why I would rather use JS includes():

computed: {
  filteredList() {
    const value= this.filterInput.charAt(0).toUpperCase() + this.filterInput.slice(1);
    return this.customers.filter(function(customer){
      return customer.first_name.includes(value) ||
             customer.last_name.includes(value) ||
             customer.email.includes(value)
    })
  }
}

Any search like Van or Patten will now match

like image 27
Mr.Web Avatar answered Feb 03 '23 07:02

Mr.Web