I have a BootstrapVue table that looks like this;
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 currentfilter
value (optional and not needed: you can read it fromthis.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.