Has anybody implemented grouped rows with v-slot in latest Vuetify versions? Their example looks like this:
<template>
<v-data-table
:headers="headers"
:items="desserts"
item-key="name"
group-by="category"
class="elevation-1"
show-group-by
></v-data-table>
</template>
<script>
export default {
data () {
return {
headers: [
{
text: 'Dessert (100g serving)',
align: 'left',
value: 'name',
},
{ text: 'Category', value: 'category' },
],
desserts: [
{
name: 'Frozen Yogurt',
category: 'Ice cream',
},
{
name: 'Ice cream sandwich',
category: 'Ice cream',
},
{
name: 'Eclair',
category: 'Cookie',
},
{
name: 'Cupcake',
category: 'Pastry',
},
{
name: 'Gingerbread',
category: 'Cookie',
},
{
name: 'Jelly bean',
category: 'Candy',
},
{
name: 'Lollipop',
category: 'Candy',
},
{
name: 'Honeycomb',
category: 'Toffee',
},
{
name: 'Donut',
category: 'Pastry',
},
{
name: 'KitKat',
category: 'Candy',
},
],
}
},
}
</script>
This works but I want to roll out my own style. I tried something like this:
<template v-slot:group="data">
{{data}}
</template>
I see the object, but the styles are missing. It's missing in the docs as far as I can see.
If anybody already implemented something like this, it would be appreciated.
Yes you can have your own style in group by by adding classes dynamically from items props or hardcoded
Updated the codepen with Vuetify 2.x: https://codepen.io/chansv/pen/wvvzXRj?editors=1010
<div id="app">
<v-app id="inspire">
<v-data-table
:headers="headers"
:items="desserts"
item-key="name"
group-by="category"
class="elevation-1"
show-group-by
>
<template v-slot:group="props">
<span class="font-weight-bold">
{{props.group }}
</span>
<v-data-table
:headers="props.headers"
:items="props.items"
item-key="name"
hide-default-footer
>
<template v-slot:body="{ items }">
<tbody>
<tr v-for="item in items" :key="item.name" class="success">
<td>{{ item.name }}</td>
</tr>
</tbody>
</template>
</v-data-table>
</template>
</v-data-table>
</v-app>
</div>
new Vue({
el: '#app',
vuetify: new Vuetify(),
data () {
return {
headers: [
{
text: 'Dessert (100g serving)',
align: 'left',
value: 'name',
},
{ text: 'Category', value: 'category' },
],
desserts: [
{
name: 'Frozen Yogurt',
category: 'Ice cream',
},
{
name: 'Ice cream sandwich',
category: 'Ice cream',
},
{
name: 'Eclair',
category: 'Cookie',
},
{
name: 'Cupcake',
category: 'Pastry',
},
{
name: 'Gingerbread',
category: 'Cookie',
},
{
name: 'Jelly bean',
category: 'Candy',
},
{
name: 'Lollipop',
category: 'Candy',
},
{
name: 'Honeycomb',
category: 'Toffee',
},
{
name: 'Donut',
category: 'Pastry',
},
{
name: 'KitKat',
category: 'Candy',
},
],
}
},
})
Related
I'm wondering if there is a way to hide a whole row/item in a vuetify data-table. I've read threads about hiding columns but not data-table items.
As per my understanding, You want to hide the specific rows from the <v-data-table>. If Yes, you can achieve that by using v-slot and manipulate the template.
Demo :
new Vue({
el: '#app',
vuetify: new Vuetify(),
data () {
return {
headers: [
{
text: 'Dessert',
value: 'name'
}
],
items: [
{
name: 'Frozen Yogurt',
show: true
},
{
name: 'Ice cream sandwich',
show: false
},
{
name: 'Eclair',
show: true
},
{
name: 'Cupcake',
show: false
}
]
}
},
})
<script src="https://unpkg.com/vue#2.x/dist/vue.js"></script>
<script src="https://unpkg.com/vuetify#2.6.6/dist/vuetify.min.js"></script>
<link rel="stylesheet" href="https://unpkg.com/vuetify#2.6.6/dist/vuetify.min.css"/>
<link rel="stylesheet" href="https://unpkg.com/#mdi/font#6.x/css/materialdesignicons.min.css"/>
<div id="app">
<v-app id="inspire">
<v-data-table
:headers="headers"
:items="items"
class="elevation-1"
>
<template v-slot:item="props">
<template v-if="props.item.show">
<tr>{{ props.item.name }}</tr>
</template>
</template>
</v-data-table>
</v-app>
</div>
I think passing an empty array to your :items would fix your problem. or you can do this one :items="defaultVales || desserts".
In my opinion, the best way to handle this is to add a show property to your objects and use a computed property to hide and show items
Working example
Here it will hide column on click
new Vue({
el: '#app',
vuetify: new Vuetify(),
computed:{
showItems(){
return this.desserts.filter(x => x.show)
}
},
data() {
return {
headers: [
{ text: 'Name', value: 'name' },
{ text: 'Score', value: 'score' },
],
desserts: [{
name: "Frozen",
score: 66,
show: true,
},
{
name: "Tom",
score: 100,
show: true,
},
{
name: "Eclair",
score: 100,
show: true,
},
{
name: "Frozen",
score: 89,
show: true,
},
]
}
},
methods: {
hideColumn(col){
col.show = false
}
}
})
<link rel='stylesheet' href='https://cdn.jsdelivr.net/npm/vuetify#2.3.4/dist/vuetify.min.css'>
<script src='https://cdn.jsdelivr.net/npm/vue#2.x/dist/vue.js'></script>
<script src='https://cdn.jsdelivr.net/npm/vuetify#2.3.4/dist/vuetify.min.js'></script>
<div id="app">
<v-data-table
:items="showItems"
:headers="headers"
#click:row="hideColumn"
>
</v-data-table>
</div>
I'm trying to create a cascading dropdown using vue.js.
I want to set the data on the second dropdown based on the item chosen from the first dropdown.
I don't know how to filter the data based on the chosen item.
I've tried to use computed property but didn't succeed.
I need some help please.
Thanks in advance.
<template>
<b-container class="my-2">
<b-row>
<b-col col="12" md="6" lg="3">
<b-form-group id="fieldset" :label="$t('tradingCalculators.fields.currencyPair')" label-for="currency-first" label-size="lg">
<v-select
id="assetPair"
#click="changeAssetClass(assetPair)"
v-model="assetPair"
:searchable="true"
:options="assetSymbols"
/>
</b-form-group>
</b-col>
<b-col cols="12" md="6" lg="3">
<b-form-group id="fieldset-1" :label="$t('tradingCalculators.fields.currencyPair')" label-for="currency-pair" label-size="lg">
<v-select id="symbolsPair" v-model="symbolsPair" :searchable="true" :options="currencyArray" />
</b-form-group>
</b-col>
</b-row>
</b-container>
</template>
export default {
data() {
assetPair: 'Forex',
symbolsPair: '',
currencyArray: [],
assetsSymbols: [{
text: 'Forex',
id: 1
},
{
text: 'Metal',
id: 2
},
{
text: 'Indices',
id: 3
},
],
symbolsPair: {
1: [{
text: 'AUDCAD',
id: 1,
},
{
text: 'AUDCHF',
id: 2,
},
{
text: 'AUDJPY',
id: 3,
},
],
2: [{
text: 'XAUUSD',
id: 1,
},
{
text: 'XAGUSD',
id: 2,
},
],
3: [{
text: 'GER30Cash',
id: 1,
},
{
text: 'US30Cash',
id: 2,
},
{
text: 'EU50Cash',
id: 3,
},
],
}
},
computed() {
changeAssetClass(e) {
return this.currencyArray.push(this.symbolsPair[e])
}
}
}
One observation : You are updating the source array this.currencyArray on first dropdown select. Hence, the cascading dropdown will not contain the filtered data.
Working Demo :
new Vue({
el: '#app',
data: function() {
return {
assetsSymbols: [{
text: 'Forex',
id: 1
}, {
text: 'Metal',
id: 2
}, {
text: 'Indices',
id: 3
}
],
selectedSymbol: '',
selectedSymbolPair: '',
symbolsPairArr: [],
symbolsPair: {
1: [{
text: 'AUDCAD',
id: 1,
},
{
text: 'AUDCHF',
id: 2,
},
{
text: 'AUDJPY',
id: 3,
},
],
2: [{
text: 'XAUUSD',
id: 1,
},
{
text: 'XAGUSD',
id: 2,
},
],
3: [{
text: 'GER30Cash',
id: 1,
},
{
text: 'US30Cash',
id: 2,
},
{
text: 'EU50Cash',
id: 3,
},
]}
}
},
watch: {
selectedSymbol: function() {
this.symbolsPairArr = [];
if (this.selectedSymbol > 0) {
this.symbolsPairArr = this.symbolsPair[this.selectedSymbol];
}
}
},
mounted() {
this.selectedSymbol = 2;
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<div class="cascading-dropdown">
<div class="dropdown">
<span>Symbol :</span>
<select v-model="selectedSymbol">
<option value="">Select a Symbol</option>
<option v-for="symbol in assetsSymbols" :value="symbol.id" :key="symbol.id">{{ symbol.text }}</option>
</select>
</div>
<div class="dropdown">
<span>Symbol Pair:</span>
<select :disabled="!selectedSymbol" v-model="selectedSymbolPair">
<option value="">Select a Pair</option>
<option v-for="pair in symbolsPairArr" :value="pair.id" :key="pair.id">{{ pair.text }}</option>
</select>
</div>
</div>
</div>
Note : I created this snippet to demonstrate you how it will work as per your requirement. You can modify it as per the need if required.
I'm learning Vue JS and trying to use multiple filters to filter multiple products.
So, I have an example of 6 filters, product 1 to product 6. And I also have 6 products with different categories. I've coded as below, but when I try to click button filter, to filter the product, it doesn't work. I've tried various ways still not working.
Can anyone help me explain it and deal with this problem?
new Vue({
el: '#app',
data () {
return {
categories:[
{
category_title: 'Product 1',
category_name: "product-1"
},
{
category_title: 'Product 2',
category_name: "product-2"
},
{
category_title: 'Product 3',
category_name: "product-3"
},
{
category_title: 'Product 4',
category_name: "product-4"
},
{
category_title: 'Product 5',
category_name: "product-5"
},
{
category_title: 'Product 6',
category_name: "product-6"
},
],
productItems: [
{
name: 'Pro1',
category: 'product-1'
},
{
name: 'Pro2',
category: 'product-2'
},
{
name: 'Pro3',
category: 'product-3'
},
{
name: 'Pro4',
category: 'product-4'
},
{
name: 'Pro5',
category: 'product-5'
},
{
name: 'Pro6',
category: 'product-6'
},
],
}
},
computed: {
productFilter(){
return this.productItems;
},
filterProduct(){
return this.productItems.filter((product) => product.category == this.categories.category_name)
}
}
})
.product-items span{
margin: 20px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.3/css/all.min.css" integrity="sha512-iBBXm8fW90+nuLcSKlbmrPcLa0OT92xO1BIsZ+ywDWZCvqsWgccV3gFoRBv0z+8dLJgyAHIhR35VZc2oM/gI1w==" crossorigin="anonymous" referrerpolicy="no-referrer" />
<div id="app">
<div class="product-filter">
<button #click="filterProduct" v-for="cat in categories" :key="cat.id">
{{ cat.category_title }}
</button>
</div>
<div class="product-items">
<span v-for="product in productFilter" :key="product.id">{{ product.name }}</span>
</div>
</div>
Move the filterProduct from the computed properties to methods. Generally actions are to be placed inside methods and the computed properties holds the data which changes with respect to the dependent values used inside the defenition of that particular computed property.
Here I have created a data property called activeCategory which is being set when the user clicks any one of the category button. The productFilter computed property makes use of activeCategory data property. So when ever the data property activeCategory gets updated from the function filterProduct, the productFilter computed property automatically retrns new set of products.
new Vue({
el: '#app',
data() {
return {
categories: [
{
category_title: 'Product 1',
category_name: "product-1"
},
{
category_title: 'Product 2',
category_name: "product-2"
},
{
category_title: 'Product 3',
category_name: "product-3"
},
{
category_title: 'Product 4',
category_name: "product-4"
},
{
category_title: 'Product 5',
category_name: "product-5"
},
{
category_title: 'Product 6',
category_name: "product-6"
},
],
productItems: [
{
name: 'Pro1',
category: 'product-1'
},
{
name: 'Pro2',
category: 'product-2'
},
{
name: 'Pro3',
category: 'product-3'
},
{
name: 'Pro4',
category: 'product-4'
},
{
name: 'Pro5',
category: 'product-5'
},
{
name: 'Pro6',
category: 'product-6'
},
],
activeCategory: null,
}
},
methods: {
filterProduct(category) {
this.activeCategory = category;
}
},
computed: {
productFilter() {
return this.activeCategory ?
this.productItems.filter((product) => product.category == this.activeCategory.category_name) :
this.productItems;
},
}
})
.product-items span {
margin: 20px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.3/css/all.min.css"
integrity="sha512-iBBXm8fW90+nuLcSKlbmrPcLa0OT92xO1BIsZ+ywDWZCvqsWgccV3gFoRBv0z+8dLJgyAHIhR35VZc2oM/gI1w=="
crossorigin="anonymous" referrerpolicy="no-referrer" />
<div id="app">
<div class="product-filter">
<button #click="filterProduct(cat)" v-for="cat in categories" :key="cat.id">
{{ cat.category_title }}
</button>
</div>
<div class="product-items">
<span v-for="product in productFilter" :key="product.id">{{ product.name }}</span>
</div>
</div>
The method filterProduct should be defined inside methods option and add filtered property that will take the filtered products when you click the button, this click button runs the method that takes the current category as parameter :
new Vue({
el: '#app',
data() {
return {
categories: [{
category_title: 'Product 1',
category_name: "product-1"
},
{
category_title: 'Product 2',
category_name: "product-2"
},
{
category_title: 'Product 3',
category_name: "product-3"
},
{
category_title: 'Product 4',
category_name: "product-4"
},
{
category_title: 'Product 5',
category_name: "product-5"
},
{
category_title: 'Product 6',
category_name: "product-6"
},
],
productItems: [{
name: 'Pro1',
category: 'product-1'
},
{
name: 'Pro2',
category: 'product-2'
},
{
name: 'Pro3',
category: 'product-3'
},
{
name: 'Pro4',
category: 'product-4'
},
{
name: 'Pro5',
category: 'product-5'
},
{
name: 'Pro6',
category: 'product-6'
},
],
filtered: []
}
},
computed: {
productFilter() {
return this.productItems;
},
},
methods: {
filterProduct(cat) {
this.filtered = this.productItems.filter((product) => product.category == cat.category_name)
}
}
})
.product-items span {
margin: 20px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.3/css/all.min.css" integrity="sha512-iBBXm8fW90+nuLcSKlbmrPcLa0OT92xO1BIsZ+ywDWZCvqsWgccV3gFoRBv0z+8dLJgyAHIhR35VZc2oM/gI1w==" crossorigin="anonymous" referrerpolicy="no-referrer"
/>
<div id="app">
<div class="product-filter">
<button #click="filterProduct(cat)" v-for="cat in categories" :key="cat.id">
{{ cat.category_title }}
</button>
</div>
<div class="product-items">
<span v-for="product in filtered" :key="product.id">{{ product.name }}</span>
</div>
<pre>
<pre>
{{filtered}}
</pre>
</div>
I am using <v-data-table> component to show data table in in my app. Is there any way to add the serial number column in this data-table. which starts from 1 to length of my articles array.
and it should start from 1 if any article with any id comes to first.
There is no built-in way to do this, but you can achieve it by adding a computed property and use .map() method to add a new property to each items like sno, which stands for serial number. You can rename it anything you want.
computed: {
itemsWithSno() {
return this.desserts.map((d, index) => ({ ...d, sno: index + 1 }))
}
},
Next, just add a new column in header array to map this new property like:
{
text: 'Serial #',
value: 'sno'
},
The value here needs to be exactly same as the new property name sno that you have added in the computed property.
Next, just update v-data-table items prop to use the computed property itemsWithSno instead of the original array like:
<v-data-table :headers="headers" :items="itemsWithSno">
</v-data-table>
That's it.
Working Demo:
new Vue({
el: '#app',
vuetify: new Vuetify(),
computed: {
itemsWithSno() {
return this.desserts.map((d, index) => ({ ...d, sno: index + 1 }))
}
},
data() {
return {
headers: [{
text: 'Serial #',
value: 'sno'
},
{
text: 'Dessert (100g serving)',
align: 'start',
sortable: false,
value: 'name',
},
{
text: 'Calories',
value: 'calories'
},
{
text: 'Fat (g)',
value: 'fat'
}
],
desserts: [{
name: 'Frozen Yogurt',
calories: 159,
fat: 6.0
},
{
name: 'Ice cream sandwich',
calories: 237,
fat: 9.0
},
{
name: 'Eclair',
calories: 262,
fat: 16.0
},
{
name: 'Cupcake',
calories: 305,
fat: 3.7
},
{
name: 'Gingerbread',
calories: 356,
fat: 16.0
}
],
}
},
})
<link href="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/#mdi/font#5.x/css/materialdesignicons.min.css" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/vuetify#2.x/dist/vuetify.min.css" rel="stylesheet">
<script src="https://cdn.jsdelivr.net/npm/vue#2.x/dist/vue.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vuetify#2.x/dist/vuetify.js"></script>
<div id="app">
<v-app>
<v-main>
<v-container>
<v-data-table :headers="headers" :items="itemsWithSno" class="elevation-1">
</v-data-table>
</v-container>
</v-main>
</v-app>
</div>
The title says it all. I want to filter my bootstrap table with an input box.
Here is my .html part of the component:
<b-table
:items="Table"
:fields="fields"
striped
small
>
</b-table>
Here is the .vue file
<template src="./jointable.component.html"> </template>
<style scoped src="./jointable.component.css"> </style>
<script>
import axios from 'axios'
export default {
name: 'jointable',
data(){
return {
Table: [],
fields: [
{key: 'client_id', label: "School Code", sortable: true},
{key: 'client_name', sortable: true},
{key: 'uuid', label: "ID", sortable: true},
{key: 'step', label: "Job Running", sortable: true},
{key: 'serverid', sortable: true},
{key: 'create_timestamp', label: "Job Start", sortable: true},
{key: 'time_elapsed', sortable: true},
{key: 'wh_db_host', sortable: true}
]
}
},
methods : {
loadData: function(){
axios.get("http://192.168.56.101:5000/jointable")
.then((res) => {
this.Table = res.data
})
.catch((err) => {
console.log(err)
})
}
},
mounted() {
this.loadData();
setInterval(function(){
this.loadData()
}.bind(this), 10000)
},
computed() {
}
}
</script>
So right now you can see that my script reloads the table every 10 seconds with updated data. This is fine. I want to also now have my table searchable/filterable. I know I have to use the computed thing but how do I use it.
Thank you to whoever helps me!
There's various ways to filter, but the most simple version is simply passing in a string to the filter prop on b-table.
This will search all columns for the string you pass in, so if you bind a data property to a input's v-model and the same data property to the filter property on your table, anything you type in the input will filter the table.
You can read more about how filtering works and some of the other methods in the documentation.
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/bootstrap-vue#2.6.1/dist/bootstrap-vue.min.js"></script>
<link href="https://unpkg.com/bootstrap-vue#2.6.1/dist/bootstrap-vue.css" rel="stylesheet" />
<link href="https://unpkg.com/bootstrap#4.4.1/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>
Detailed Code for filtering bootstrap-vue please refer documentation Thanks
new Vue({
el: '#app',
data() {
return {
items: [{
isActive: true,
age: 40,
name: {
first: 'Dickerson',
last: 'Macdonald'
}
},
{
isActive: false,
age: 21,
name: {
first: 'Larsen',
last: 'Shaw'
}
},
{
isActive: false,
age: 9,
name: {
first: 'Mini',
last: 'Navarro'
},
_rowVariant: 'success'
},
{
isActive: false,
age: 89,
name: {
first: 'Geneva',
last: 'Wilson'
}
},
{
isActive: true,
age: 38,
name: {
first: 'Jami',
last: 'Carney'
}
},
{
isActive: false,
age: 27,
name: {
first: 'Essie',
last: 'Dunlap'
}
},
{
isActive: true,
age: 40,
name: {
first: 'Thor',
last: 'Macdonald'
}
},
{
isActive: true,
age: 87,
name: {
first: 'Larsen',
last: 'Shaw'
},
_cellVariants: {
age: 'danger',
isActive: 'warning'
}
},
{
isActive: false,
age: 26,
name: {
first: 'Mitzi',
last: 'Navarro'
}
},
{
isActive: false,
age: 22,
name: {
first: 'Genevieve',
last: 'Wilson'
}
},
{
isActive: true,
age: 38,
name: {
first: 'John',
last: 'Carney'
}
},
{
isActive: false,
age: 29,
name: {
first: 'Dick',
last: 'Dunlap'
}
}
],
fields: [{
key: 'name',
label: 'Person full name',
sortable: true,
sortDirection: 'desc'
},
{
key: 'age',
label: 'Person age',
sortable: true,
class: 'text-center'
},
{
key: 'isActive',
label: 'Is Active',
formatter: (value, key, item) => {
return value ? 'Yes' : 'No'
},
sortable: true,
sortByFormatted: true,
filterByFormatted: true
},
{
key: 'actions',
label: 'Actions'
}
],
totalRows: 1,
currentPage: 1,
perPage: 5,
pageOptions: [5, 10, 15, {
value: 100,
text: "Show a lot"
}],
sortBy: '',
sortDesc: false,
sortDirection: 'asc',
filter: null,
filterOn: [],
infoModal: {
id: 'info-modal',
title: '',
content: ''
}
}
},
computed: {
sortOptions() {
// Create an options list from our fields
return this.fields
.filter(f => f.sortable)
.map(f => {
return {
text: f.label,
value: f.key
}
})
}
},
mounted() {
// Set the initial number of items
this.totalRows = this.items.length
},
methods: {
info(item, index, button) {
this.infoModal.title = `Row index: ${index}`
this.infoModal.content = JSON.stringify(item, null, 2)
this.$root.$emit('bv::show::modal', this.infoModal.id, button)
},
resetInfoModal() {
this.infoModal.title = ''
this.infoModal.content = ''
},
onFiltered(filteredItems) {
// Trigger pagination to update the number of buttons/pages due to filtering
this.totalRows = filteredItems.length
this.currentPage = 1
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.11/vue.js"></script>
<script src="https://unpkg.com/bootstrap-vue#2.6.1/dist/bootstrap-vue.min.js"></script>
<link href="https://unpkg.com/bootstrap-vue#2.6.1/dist/bootstrap-vue.css" rel="stylesheet" />
<link href="https://unpkg.com/bootstrap#4.4.1/dist/css/bootstrap.min.css" rel="stylesheet" />
<div id="app" class="p-5">
<template>
<b-container fluid>
<!-- User Interface controls -->
<b-row>
<b-col lg="6" class="my-1">
<b-form-group
label="Sort"
label-for="sort-by-select"
label-cols-sm="3"
label-align-sm="right"
label-size="sm"
class="mb-0"
v-slot="{ ariaDescribedby }"
>
<b-input-group size="sm">
<b-form-select
id="sort-by-select"
v-model="sortBy"
:options="sortOptions"
:aria-describedby="ariaDescribedby"
class="w-75"
>
<template #first>
<option value="">-- none --</option>
</template>
</b-form-select>
<b-form-select v-model="sortDesc" :disabled="!sortBy" :aria-describedby="ariaDescribedby" size="sm" class="w-25">
<option :value="false">Asc</option>
<option :value="true">Desc</option>
</b-form-select>
</b-input-group>
</b-form-group>
</b-col>
<b-col lg="6" class="my-1">
<b-form-group label="Initial sort" label-for="initial-sort-select" label-cols-sm="3" label-align-sm="right" label-size="sm" class="mb-0">
<b-form-select id="initial-sort-select" v-model="sortDirection" :options="['asc', 'desc', 'last']" size="sm"></b-form-select>
</b-form-group>
</b-col>
<b-col lg="6" class="my-1">
<b-form-group label="Filter" label-for="filter-input" label-cols-sm="3" label-align-sm="right" label-size="sm" class="mb-0">
<b-input-group size="sm">
<b-form-input id="filter-input" v-model="filter" type="search" placeholder="Type to Search"></b-form-input>
<b-input-group-append>
<b-button :disabled="!filter" #click="filter = ''">Clear</b-button>
</b-input-group-append>
</b-input-group>
</b-form-group>
</b-col>
<b-col lg="6" class="my-1">
<b-form-group v-model="sortDirection" label="Filter On" description="Leave all unchecked to filter on all data" label-cols-sm="3" label-align-sm="right" label-size="sm" class="mb-0" v-slot="{ ariaDescribedby }">
<b-form-checkbox-group v-model="filterOn" :aria-describedby="ariaDescribedby" class="mt-1">
<b-form-checkbox value="name">Name</b-form-checkbox>
<b-form-checkbox value="age">Age</b-form-checkbox>
<b-form-checkbox value="isActive">Active</b-form-checkbox>
</b-form-checkbox-group>
</b-form-group>
</b-col>
<b-col sm="5" md="6" class="my-1">
<b-form-group label="Per page" label-for="per-page-select" label-cols-sm="6" label-cols-md="4" label-cols-lg="3" label-align-sm="right" label-size="sm" class="mb-0">
<b-form-select id="per-page-select" v-model="perPage" :options="pageOptions" size="sm"></b-form-select>
</b-form-group>
</b-col>
<b-col sm="7" md="6" class="my-1">
<b-pagination v-model="currentPage" :total-rows="totalRows" :per-page="perPage" align="fill" size="sm" class="my-0"></b-pagination>
</b-col>
</b-row>
<!-- Main table element -->
<b-table :items="items" :fields="fields" :current-page="currentPage" :per-page="perPage" :filter="filter" :filter-included-fields="filterOn" :sort-by.sync="sortBy" :sort-desc.sync="sortDesc" :sort-direction="sortDirection" stacked="md" show-empty small
#filtered="onFiltered">
<template #cell(name)="row">
{{ row.value.first }} {{ row.value.last }}
</template>
<template #cell(actions)="row">
<b-button size="sm" #click="info(row.item, row.index, $event.target)" class="mr-1">
Info modal
</b-button>
<b-button size="sm" #click="row.toggleDetails">
{{ row.detailsShowing ? 'Hide' : 'Show' }} Details
</b-button>
</template>
<template #row-details="row">
<b-card>
<ul>
<li v-for="(value, key) in row.item" :key="key">{{ key }}: {{ value }}</li>
</ul>
</b-card>
</template>
</b-table>
<!-- Info modal -->
<b-modal :id="infoModal.id" :title="infoModal.title" ok-only #hide="resetInfoModal">
<pre>{{ infoModal.content }}</pre>
</b-modal>
</b-container>
</template>
</div>
Is this what you are looking for?
new Vue({
el: "#app",
data: {
Items: [
{Name: 'Lorem ipsum'},
{Name: 'consectetur'},
{Name: 'adipisicing.'}
],
search: ''
},
computed: {
filteredItems() {
return this.Items.filter(item => item.Name.toLowerCase().includes(this.search.toLowerCase()))
}
}
})
.item {
border: solid black 2px;
padding: 10px;
margin: 10px;
}
.search {
border: solid black 2px;
padding: 10px;
margin: 10px;
}
p {
padding: 10px;
}
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
<div id="app">
<p>Found {{filteredItems.length}} items</p>
<input class="search" type="text" placeholder="Search" v-model="search">
<div class="item" v-for="item in filteredItems">{{item.Name}}</div>
</div>