Home > OS >  Filter BootstrapVue table using comma separated string with OR condition in input field
Filter BootstrapVue table using comma separated string with OR condition in input field

Time:04-18

I have a BootstrapVue table that looks like this;

enter image description here

The code(credit goes to this answer) for the table is here;

new Vue({
  el: '#app',
  data() {
    return {
      filter: '',
      items: [
        { id: 1, first_name: "Mikkel", last_name: "Hansen", age: 54 },
        { id: 2, first_name: "Kasper", last_name: "Hvidt", age: 42 },
        { id: 3, first_name: "Lasse", last_name: "Boesen", age: 39 },
        { id: 4, first_name: "Kasper", last_name: "Hansen", age: 62 },
        { id: 5, first_name: "Mads", last_name: "Mikkelsen", age: 31 },
      ]
    }
  }
})

<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.11/vue.js"></script>
<script src="https://unpkg.com/[email protected]/dist/bootstrap-vue.min.js"></script>

<link href="https://unpkg.com/[email protected]/dist/bootstrap-vue.css" rel="stylesheet" />
<link href="https://unpkg.com/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet" />

<div id="app" >
  <b-input v-model="filter" placeholder="Filter table.."></b-input>
  <hr />
  <b-table :items="items" :fields="fields" :filter="filter">
  </b-table>
</div>

Based on the above code, table rows will be filtered based on the string inside the input field. Unfortunately, this is not what I want. What I want is for the input field to be able to accept a comma-separated string and the sub-strings can be used to filter the table rows in an OR condition. For example, if the string is 54, Hvidt, then the first and second rows will be filtered.

I am using BootstrapVue, vue.js 2.6

CodePudding user response:

BootstrapVue allows writing your own logic for filtering, using a custom filter function.

In order for it to work, you need:

  • a :filter specified
  • the filter value to be truthy. If it's falsey, the filter function is bypassed (no filtering occurs).
  • a :filter-function specified, taking two arguments: row and current filter value (optional and not needed: you can read it from this.filter).

Here's an example, splitting current filter value by , (comma), normalising the fragments (trim & toLowerCase), and returning whether or not any fragment is found within the normalised values of the row.

new Vue({
  el: '#app',
  data() {
    return {
      filter: '54, Hvidt',
      items: [
        { id: 1, first_name: "Mikkel", last_name: "Hansen", age: 54 },
        { id: 2, first_name: "Kasper", last_name: "Hvidt", age: 42 },
        { id: 3, first_name: "Lasse", last_name: "Boesen", age: 39 },
        { id: 4, first_name: "Kasper", last_name: "Hansen", age: 62 },
        { id: 5, first_name: "Mads", last_name: "Mikkelsen", age: 31 }
      ]
    }
  },
  methods: {
    normalizeString(s) {
      return `${s}`.trim().toLowerCase();
    },
    filterFn(row) {
      return this.filter.split(',')
        .map(this.normalizeString)
        .some(
          term => Object.values(row)
            .map(this.normalizeString)
            .some(
              val => val.indexOf(term) > -1
            )
        );
    }
  }
})
<script src="https://cdn.jsdelivr.net/npm/[email protected]"></script>
<script src="https://unpkg.com/[email protected]/dist/bootstrap-vue.min.js"></script>

<link href="https://unpkg.com/[email protected]/dist/bootstrap-vue.css" rel="stylesheet" />
<link href="https://unpkg.com/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet" />

<div id="app" >
  <b-input v-model="filter" placeholder="Filter table..."></b-input>
  <hr />
  <b-table :items="items" :filter="filter" :filter-function="filterFn">
  </b-table>
</div>

Important note: the filter function provided here is demonstrative, it doesn't take into account BootstrapVue's built-in filter-ignored-fields and filter-included-fields. Nor does it take into account the filterByFormatted field definition.

If you need any of those features, you'll need to improve it yourself.

I guess it's needless to point out the filter function has access to the entire component and can be modified in any way. The row is displayed if the function returns a truthy value and is not displayed if it returns a falsey value.

  • Related