1

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" class="p-5">
  <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

1 Answer 1

2

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" class="p-5">
  <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.

Sign up to request clarification or add additional context in comments.

2 Comments

#tao Thanks. Your solution is brilliant. It will take me some time to understand it. I'm not familiar with the map() function and some() is something new to me.
@user, some returns true when the first array member satisfying the condition is met (so it's cheap, it doesn't go through the entire array). map is fairly straight forward. Keep MDN close, it's a high quality beginner friendly resource for all web technologies. Whenever you don't understand something, use breakpoints and/or console.log() every step, until it's clear what each one does.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.