Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Filter table rows with vue

I am new to vuejs. I have this table:

<table>
 <thead>
    <tr
      v-for="(items, index) in data"
      v-if="index == 0">
      <td v-for="(item, key) in items">
        {{ key }}
      </td>
    </tr>
  </thead>
  <tbody>
    <tr v-for="(items, index) in filteredData">
      <td v-for="item in items">
        {{ item }}
      </td>
    </tr>
  </tbody>
</table>

I want to filter the rows and display the ones that matches whatever is in this input:

<input
  type="text"
  placeholder="Search something..."
  v-model="searchQuery">

I have successfully done this with a computed property.

computed: {
  filteredData: function() {
    return this.data.filter((items) => {
      for (var item in items) {
        if(String(items[item]).indexOf(this.searchQuery) !== -1) {
          return true
        }
      }
      return false
    })
  }
},

This filters the table and displays only the rows that have a cell that matches whatever is in the input. This works perfectly.

However, now I want to filter and show only the rows whose cells match what is in the input but only search through a column chosen from a select tag, which I have created below:

<select
  id="columnsSelect"
  v-model="selected">
  <option
    v-for="column in columns"
    :value="column">
    {{ column }}
  </option>
</select>

I hope I am making sense. I do not know how to proceed from here. Cookies and a big thank you to anyone who helps!

like image 283
sunny_adriann Avatar asked Jan 27 '19 22:01

sunny_adriann


1 Answers

You're on the right track with filtering using a computed property, now you just need to add the logic to filter the rows based on the selected column. For example:

new Vue({
  el: '#app',
  data: () => ({
    search: null,
    column: null,
    items: []
  }),
  beforeMount () {
    this.items = Array.from(Array(20), (x,i) => {
      return {
        id: i,
        name: Math.random().toString(36).substring(7),
        title: Math.random().toString(36).substring(7),
        description: Math.random().toString(36).substring(7)
      }
    })
  },
  computed: {
    cols () {
      return this.items.length >= 1 ? Object.keys(this.items[0]) : []
    },
    rows () {
      if (!this.items.length) {
        return []
      }
      
      return this.items.filter(item => {
        let props = (this.search && this.column) ? [item[this.column]] : Object.values(item)
        
        
        return props.some(prop => !this.search || ((typeof prop === 'string') ? prop.includes(this.search) : prop.toString(10).includes(this.search)))
      })
    }
  }
})
* {
  margin: 0;
  padding: 0;
}

body {
  display: flex;
  flex-direction: column;
  align-items: center;
}

#app {
  width: 20rem;
}

#app > div {
  display: flex;
  flex-direction: row;
}

select, input {
  width: 50%;
}

table {
  width: 100%;
  border: 1px solid black;
  text-align: center;
  border-spacing: 0;
}

td {
  border-top: 1px solid black;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
  <div>
  <select v-model="column">
    <option :value="null">No Column Filter</option>
    <option v-for="col in cols" :key="col">{{ col }}</option>
  </select>
  <input type="text" v-model="search" placeholder="Search">
  </div>
  <table>
    <thead>
      <tr>
        <th v-for="col in cols" :key="col">{{ col }}</th>
      </tr>
    </thead>
    <tbody>
      <tr v-for="row in rows" :key="row.id">
        <td v-for="col in cols" :key="col">{{ row[col] }}</td>
      </tr>
    </tbody>
  </table>
</div>
like image 85
Brian Lee Avatar answered Nov 07 '22 02:11

Brian Lee