Cascading dropdown using Vuejs - javascript

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.

Related

How to pass data from component file to view file in vue js

I'm trying to pass data from vue component to vue view file. I tried creating props but it didn't work. I have one component file on path src/components/list.vue and another file on path src/views/select.vue
The flow goes like this: User lands on select.vue page, here on click of input box a pop-up appears which have have list of elements in <ul> <li> tag from list.vue (component file).
What I want to achieve:
Whenever user select any option from list.vue file, modal pop-up should close and selected element should be displayed in input box of select.vue file.
Below is code:
src/views/select.vue
<label class="primary-label mb-2">First Question</label>
<div class="form-block">
<label class="secondary-label mb-1">Question</label>
<b-form-input placeholder="Select Question" v-model="questions.first" class="form-control l-input" #click="onOptionChanged"></b-form-input>
</div>
<div class="form-block">
<label class="secondary-label mb-1">Answer</label>
<b-form-input v-model="answers.first" placeholder="Enter answer" class="form-control l-input"></b-form-input>
</div>
<script>
export default {
data() {
return {
questions: {
first: null,
},
answers: {
first: null,
},
options: [
{ value: null, text: 'Select Question', disabled:true },
{ value: 1, text: 'In what city were you born?' },
{ value: 2, text: 'What is the name of your favorite pet?' },
{ value: 3, text: 'What is your mother\'s maiden name?' },
{ value: 4, text: 'What high school did you attend?' },
{ value: 5, text: 'What is the name of your first school?' },
{ value: 6, text: 'What was the make of your first car?' },
{ value: 7, text: 'What was your favorite food as a child?' },
{ value: 8, text: 'Where did you meet your spouse?' },
],
}
},
methods: {
onOptionChanged() {
var modal_ref = 'myModalRef';
this.$refs[modal_ref].show();
},
},
components: {
SecurityQuestionsList,
},
}
src/components/list.vue
<template>
<main>
<div class="container">
<div class="row">
<div class="col-md-6">
<div class="search-block">
<span class="s-icon fa fa-search"></span>
</div>
<ul class="l-group" v-if="filteredQuestions.length > 0">
<li class="d-flex align-items-center" :key="item.id" v-for="item in filteredQuestions" #click="onOptionSelect(item.question)"
:class="selected === item.id ? 'my-selected-item-class':null">
{{item.question}}
</li>
</ul>
</div>
</div>
</div>
</main>
</template>
<script>
export default {
data() {
return {
search: '',
selected: null,
questions: [
{ id: 1, question: 'In what city were you born?' },
{ id: 2, question: 'What is the name of your favorite pet?' },
{ id: 3, question: 'What is your mother\'s maiden name?' },
{ id: 4, question: 'What high school did you attend?' },
{ id: 5, question: 'What is the name of your first school?' },
{ id: 6, question: 'What was the make of your first car?' },
{ id: 7, question: 'What was your favorite food as a child?' },
{ id: 8, question: 'Where did you meet your spouse?' },
],
}
},
computed: {
filteredQuestions() {
return this.questions.filter(item => {
return item.question.toLowerCase().includes(this.search.toLowerCase());
});
}
},
methods: {
onOptionSelect(selectedId) {
this.selected = selectedId;
console.log(this.selected);
this.$emit('questions-selected', this.selected);
},
}
}
</script>
I am getting selected value in console but not sure how to catch it in search.vue file.
Thanks!
You need to connect your components and pass props, try like following snippet:
Vue.component('list', {
template: `
<main>
<div class="container">
<div class="row">
<div class="col-md-6">
<div class="search-block">
<span class="s-icon fa fa-search"></span>
</div>
<ul class="l-group" v-if="filteredQuestions.length > 0">
<li class="d-flex align-items-center" :key="item.id" v-for="item in filteredQuestions" #click="onOptionSelect(item.question)"
:class="selected === item.id ? 'my-selected-item-class':null">
{{item.question}}
</li>
</ul>
</div>
</div>
</div>
</main>
`,
props: ['search'],
data() {
return {
selected: null,
questions: [
{ id: 1, question: 'In what city were you born?' },
{ id: 2, question: 'What is the name of your favorite pet?' },
{ id: 3, question: 'What is your mother\'s maiden name?' },
{ id: 4, question: 'What high school did you attend?' },
{ id: 5, question: 'What is the name of your first school?' },
{ id: 6, question: 'What was the make of your first car?' },
{ id: 7, question: 'What was your favorite food as a child?' },
{ id: 8, question: 'Where did you meet your spouse?' },
],
}
},
computed: {
filteredQuestions() {
if (this.search) {
return this.questions.filter(item => {
return item.question.toLowerCase().includes(this.search.toLowerCase());
});
} return this.questions
}
},
methods: {
onOptionSelect(selectedId) {
this.selected = selectedId;
this.$emit('questions-selected', selectedId);
},
}
})
new Vue({
el: "#demo",
name: 'select',
data() {
return {
questions: {
first: null,
},
answers: {
first: null,
},
selected: false
}
},
methods: {
onOptionChanged() {
this.selected = true
},
onSelected(val) {
this.questions.first = val
this.selected = false
},
},
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<link type="text/css" rel="stylesheet" href="https://unpkg.com/bootstrap/dist/css/bootstrap.min.css" />
<link type="text/css" rel="stylesheet" href="https://unpkg.com/bootstrap-vue#latest/dist/bootstrap-vue.min.css" />
<script src="https://unpkg.com/bootstrap-vue#latest/dist/bootstrap-vue.min.js"></script>
<script src="https://unpkg.com/bootstrap-vue#latest/dist/bootstrap-vue-icons.min.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.1.1/css/all.min.css" integrity="sha512-KfkfwYDsLkIlwQp6LFnl8zNdLGxu9YAA1QvwINks4PhcElQSvqcyVLLD9aMhXd13uQjoXtEKNosOWaZqXgel0g==" crossorigin="anonymous" referrerpolicy="no-referrer" />
<div id="demo">
<div>
<label class="primary-label mb-2">First Question</label>
<div class="form-block">
<label class="secondary-label mb-1">Question</label>
<b-form-input placeholder="Select Question" v-model="questions.first" class="form-control l-input" #click="onOptionChanged()"></b-form-input>
</div>
<div class="form-block">
<label class="secondary-label mb-1">Answer</label>
<b-form-input v-model="answers.first" placeholder="Enter answer" class="form-control l-input"></b-form-input>
<list :search="questions.first" #questions-selected="onSelected" v-if="selected"></list>
</div>
</div>
</div>

How to make dropdown list with Vue 3?

I was searching whole internet but that didn't help me to resolve issue.
With this code below I'm encountering 'Uncaught ReferenceError: VueSelect is not defined'
What's wrong with the code?
var productForm = Vue.createApp ({
data: function() {
return {
product: {
sku: 0,
name: 'asdf',
price: 0
}
}
}
})
productForm.component('custom-form', {
props: ['value', 'options'],
template: `
<label>SKU<input type="text" :value=this.sku></label>
<label>Name<input type="text" :value=this.name></label>
<label>Price<input type="text" :value=this.price></label>
<vue-select :options="options" label="option"
></vue-select>
` ,
data: function() {
return {
sku: 0,
name: 'asdf',
price: 0,
options: [
{ option: "Size" },
{ option: "Weight" },
{ option: "Dimensions" }
]
}
}
})
const vm = productForm.mount('#product_form')
vm.component('vue-select', VueSelect )
Anyway, I managed successfully to do following without VueSelect:
var productForm = Vue.createApp ({})
productForm.component('custom-form', {
template: `
<label>SKU<input type="text" v-model="this.product.sku"></label>
<label>Name<input type="text" v-model="this.product.name"></label>
<label>Price<input type="text" v-model="this.product.price"></label>
<label>Attributes<select v-model="selected">
<option
v-for="item in options"
>{{item}}
</option>
</select></label>
` ,
data: function() {
return {
product: {
sku: 0,
name: 'asdf',
price: 0
},
options: ['Size', 'Weight', 'Dimensions'],
selected: 'Size'
}
}
})
productForm.mount('#product_form')

filtering items with multiple filters using vue js

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>

How to filter a bootstrap vue table with an input field

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>

How to style grouped rows in Vuetify datatable using slots?

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',
},
],
}
},
})

Categories

Resources