Vuetify Autocomplete Showing [object Object] - vue.js

I am new in vue 3. I am trying to use vuetify autocomplete feature for my project. I have consulted official doc of vuetify . Autocomplete Showing [object Object]. Thanks in advance.
<script>
import { Form, Field } from 'vee-validate';
export default {
components: {
Form,
Field,
},
setup(props) {
},
data() {
return {
add: {
id: 1,
},
states: [
{ name: 'Florida', id: 1 },
{ name: 'Georgia', id: 2 },
{ name: 'Nebraska', id: 3 },
{ name: 'California', id: 4 },
{ name: 'New York', id: 5 },
],
};
},
methods: {
},
};
</script>
<template>
<v-row>
<v-autocomplete
v-model="add.id"
:items="states"
item-text="name"
item-value="id"
chips
deletable-chips
filled
></v-autocomplete>
</v-row>
</template>
How to show state name instead of [object object]

If you're using Vuetify 3, you should use "item-title" instead of "item-text".
And i think that Vuetify 2.6 is not compatible with Vue 3.
Give a feedback if this worked for you or not.

use :items="states.map(x=> x.name)" you need to use a string array.

Add return-object in v-autocomplete
<v-autocomplete
v-model="add.id"
:items="states"
item-text="name"
item-value="id"
chips
deletable-chips
filled
return-object
></v-autocomplete>

First of all, you mentioned the wrong reference URL of Vuetify (or maybe you are using the wrong version) because Vuetify 2 is not compatible with Vue 3. So, use Vuetify 3 for your development.
Second, if you don't want to select multiple items (because you didn't use multiple props) then the use of the chips prop doesn't seem worth it. However, if you want to use it, fix two syntax mistakes first-
Use closable-chips instead of deletable-chips (it is Vuetify 2 syntax.).
Use variant="filled" instead of filled (it is also Vuetify 2 syntax.)
Now, the reason autocomplete is showing object object is that you are using item-text which is Vuetify 2 belonging. Instead of that, you should use item-title and the issue will be fixed.
Here is the working demo of output when using item-text and when using item-title-
<!DOCTYPE html>
<html>
<head>
<link
href="https://cdn.jsdelivr.net/npm/#mdi/font#4.x/css/materialdesignicons.min.css"
rel="stylesheet"
/>
<link
href="https://cdn.jsdelivr.net/npm/vuetify#3.0.5/dist/vuetify.min.css"
rel="stylesheet"
/>
</head>
<body>
<div id="app"></div>
<script src="https://unpkg.com/vue#3/dist/vue.global.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vuetify#3.0.5/dist/vuetify.min.js"></script>
<script type="text/x-template" id="app-template">
<v-app>
<v-card flat>
<v-card-text>
<v-row no-gutters>
<v-col>
<h3 class="my-2">When using "item-text"</h3>
<v-autocomplete
v-model="add.id"
:items="states"
item-text="name"
item-value="id"
variant="filled"
chips
closable-chips
></v-autocomplete>
</v-col>
<v-col class="ms-3">
<h3 class="my-2">When using "item-title"</h3>
<v-autocomplete
v-model="add.id"
:items="states"
item-title="name"
item-value="id"
variant="filled"
chips
closable-chips
></v-autocomplete>
</v-col>
</v-row>
</v-card-text>
</v-card>
</v-app>
</script>
<script>
const { createApp } = Vue;
const { createVuetify } = Vuetify;
const vuetify = createVuetify();
const app = createApp({
template: "#app-template",
data() {
return {
add: {
id: 1,
},
states: [
{ name: 'Florida', id: 1 },
{ name: 'Georgia', id: 2 },
{ name: 'Nebraska', id: 3 },
{ name: 'California', id: 4 },
{ name: 'New York', id: 5 },
],
};
},
})
.use(vuetify)
.mount("#app");
</script>
</body>
</html>

Related

How can I update an existing v-select by setting the v-model?

I have been teaching myself Vue (with limited success) but have run into the below issue.
I have two s each with a v-model:
Select 1:
<v-select
class="pr-2"
:items="latteSizeList"
v-model="sizeid"
item-text="sizename"
item-value="id"
#change="updateAvailibleOz(), calculate(), togglesizeSelected()"
solo
>
</v-select>
Select 2:
<v-select
:items="shotsArray"
v-model="shotcount"
:value.sync="shotcount"
item-text="shotsAmountName"
item-value="shotsAmountAmount"
#change="calculate()"
solo
>
</v-select>
I want to update the displayed value of the second v-select when the function togglesizeSelected() is called.
methods: {
togglesizeSelected: function () {
this.shotcount= this.sizeList.filter( (item) => item.id.indexOf(this.sizeid) > -1)[0].latteshots;
console.log("Shots Count: " + this.shotcount)
},
}
The variable is updating and is showing in the console. But I have not been able to get the displayed item to update. What am I missing?
Funny thing is that I met the same exact question today :)
(If the console hides the solution, just click "Full page")
new Vue({
el: '#app',
vuetify: new Vuetify(),
data() {
return {
sizeid: null,
latteSizeList: [{
id: 0,
sizename: "Small",
latteshots: 5,
},
{
id: 1,
sizename: "Large",
latteshots: 10,
},
],
shotcount: null,
shotsArray: [{
shotsAmountName: "5 shots",
shotsAmount: 5,
},
{
shotsAmountName: "10 shots",
shotsAmount: 10,
},
],
}
},
methods: {
latteSizeListClickHandler(e) {
this.togglesizeSelected(e)
this.calculate()
},
togglesizeSelected({
latteshots
}) {
this.shotcount = this.shotsArray.find(({
shotsAmount
}) => shotsAmount === latteshots)
},
calculate() {
console.log('calculate executed')
}
},
})
<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#4.x/css/materialdesignicons.min.css" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/vuetify#2.x/dist/vuetify.min.css" rel="stylesheet">
<div id="app">
<v-app>
<v-main>
<v-container>
Select 1:
<v-select class="pr-2" :items="latteSizeList" v-model="sizeid" item-text="sizename" item-value="id" #change="(e) => latteSizeListClickHandler(e)" return-object solo>
</v-select>
Select 2:
<v-select :items="shotsArray" v-model="shotcount" item-text="shotsAmountName" item-value="shotsAmountAmount" solo>
</v-select>
</v-container>
</v-main>
</v-app>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue#2.x/dist/vue.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vuetify#2.x/dist/vuetify.js"></script>
My idea:
Do not place multiple functions on a handler in the template. Create a "composition function" instead, and call that. (Generally, try to keep the template as simple in terms of JS code as possible. That's just good advice.)
You have to
set the v-select to return the whole object not the value only. You can do this by adding return-object to the v-select
pass in the object to the handler function as the argument ((e) => latteSizeListClickHandler(e) -> e is the argument)
set the shotcount to an object that's in the shotsArray, not only its shotsAmount
remove the :value.sync="shotcount" from the second v-select. .sync is for something else (that's a shorthand syntax for reacting to an event emitted in a child-component)
And voilá! The v-select works!
In a shorter way:
use return-object on the first v-select
find the object in shotsArray & set shotcount to that object
remove :value.sync - this messes up the v-model

Vuetify v-data-table custom filter for dropdown

I have a v-data-table that already has the :search and :sort-by enabled. I have now created a select where I pull in my status from VueX. Accepted, Rejected. What I want to do is not only search or sort but when selecting from the drop down, accepted only the accepted values display in the table.
<v-select
v-model="selectStatus"
label="Status"
:items="statusData"
item-value="id"
item-text="name"
return-object
#change="filterStatus"
/>
Is this the correct way to setup the filter?
methods: {
filterStatus () {
console.log('This is where I am planning to add my custom filter')
}
}
This is my statusData:
userStatus : [
{
id: 0,
name: "Accepted",
},
{
id: 1,
name: " Rejected",
},
];
Or better to pass in the data:
{ text: 'Status', value: 'status.name', filter: value => {}},
To disable certain values to be selected add a disabled property to your items.
var app = new Vue({
el: '#app',
vuetify: new Vuetify(),
data: {
items: [{
id: 0,
name: 'Accepted'
},
{
id: 1,
name: ' Rejected',
disabled: true
}
],
value: null
}
})
<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.6.0"></script>
<script src="https://cdn.jsdelivr.net/npm/vuetify#2.x/dist/vuetify.js"></script>
<div id="app">
<v-app>
<v-container>
Value : {{value}}
<v-select
v-model="value"
label="Status"
:items="items"
item-value="id"
item-text="name"
return-object
/>
</v-container>
</v-app>
</div>
Documentation : props-disabled

How to change the cursor default to pointer in Vuetify component

I want to change cursor default to pointer when active autocomplete in Vuetify.
I tried to make css code to change cursor.
but mouse drag on the autocomplete bottom, cursor change "text" style like "I beem". I want to show the "pointer " style.
I couldn't find out any idea Vuetify web site.
Does anyone have idea?
<template>
<v-card>
<v-container fluid>
<v-row
align="center"
>
<v-col cols="12">
<v-autocomplete
v-model="value"
:items="items"
dense
filled
label="Filled"
class="test_cursor"
></v-autocomplete>
</v-col>
</v-row>
</v-container>
</v-card>
</template>
<script>
export default {
data: () => ({
items: ['foo', 'bar', 'fizz', 'buzz'],
values: ['foo', 'bar'],
value: null,
}),
}
</script>
<style lang="scss" scoped>
.test_cursor{
cursor: pointer;
}
</style>
By default cursor is set to text (which appears as the "I-beam" you mention), but you can change the v-autocomplete's cursor by targeting the input in your CSS:
.test_cursor input {
cursor: pointer;
}
new Vue({
vuetify: new Vuetify(),
el: '#app',
data () {
return {
states: [
{ name: 'Florida', abbr: 'FL', id: 1 },
{ name: 'Georgia', abbr: 'GA', id: 2 },
{ name: 'Nebraska', abbr: 'NE', id: 3 },
{ name: 'California', abbr: 'CA', id: 4 },
{ name: 'New York', abbr: 'NY', id: 5 },
],
}
},
})
.test_cursor input {
cursor: pointer;
}
<script src="https://unpkg.com/vue#2.6.11"></script>
<script src="https://unpkg.com/vuetify#2.3.5"></script>
<link rel="stylesheet" href="https://unpkg.com/vuetify#2.3.5/dist/vuetify.css">
<v-app id="app">
<v-autocomplete
class="test_cursor"
:items="states"
item-text="name"
label="State"
></v-autocomplete>
</v-app>

How to add a custom button in vuetify select

I have a scenario like I have to list a few hundred categories and I have to show them in a select box. Since the list is huge, skip and limit is implemented in the backend, so that it will limit the categories to 20s. My case is like when the user sees the first 20 categories, in the end, I have to add some button stating like 'Load more' so that when the user clicks on it, they can see the next 20 categories. But I have no idea how to add a button in a vuetify select. Can someone help me with this?
new Vue({
el: '#app',
vuetify: new Vuetify(),
data: () => ({
fruits: [
'Item 1',
'Item 2',
'Item 3',
'Item 4'
],
selectedFruits: [],
}),
computed: {
likesAllFruit () {
return this.selectedFruits.length === this.fruits.length
},
likesSomeFruit () {
return this.selectedFruits.length > 0 && !this.likesAllFruit
},
icon () {
if (this.likesAllFruit) return 'mdi-close-box'
if (this.likesSomeFruit) return 'mdi-minus-box'
return 'mdi-checkbox-blank-outline'
},
},
methods: {
toggle () {
this.$nextTick(() => {
if (this.likesAllFruit) {
this.selectedFruits = []
} else {
this.selectedFruits = this.fruits.slice()
}
})
},
loadMore () {
console.log('load more ...')
}
},
})
<link href="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900" rel="stylesheet">
<link href="https://fonts.googleapis.com/css?family=Material+Icons" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/#mdi/font#4.x/css/materialdesignicons.min.css" rel="stylesheet" />
<link href="https://cdn.jsdelivr.net/npm/vuetify#2.2.26/dist/vuetify.min.css" rel="stylesheet">
<script src="https://cdn.jsdelivr.net/npm/babel-polyfill/dist/polyfill.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vue#2.x/dist/vue.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vuetify#2.2.26/dist/vuetify.min.js"></script>
<div id="app">
<v-app id="inspire">
<v-container fluid>
<v-select
v-model="selectedFruits"
:items="fruits"
label="Favorite Fruits"
multiple
>
<template v-slot:prepend-item>
<v-list-item
ripple
#click="toggle"
>
<v-list-item-action>
<v-icon :color="selectedFruits.length > 0 ? 'indigo darken-4' : ''">{{ icon }}</v-icon>
</v-list-item-action>
<v-list-item-content>
<v-list-item-title>Select All</v-list-item-title>
</v-list-item-content>
</v-list-item>
<v-divider class="mt-2"></v-divider>
</template>
<template v-slot:append-item>
<v-divider class="mb-2"></v-divider>
<v-btn color="primary" #click="loadMore">
Click me for load more items.
</v-btn>
</template>
</v-select>
</v-container>
</v-app>
</div>
In Vuetify 2.x there is an virtual scroll component, but I still found the v-intersect easiest to use...
markup:
<v-autocomplete
v-model="selected"
:items="beers"
item-text="name"
item-value="id"
label="Search da beers.."
return-object
autocomplete="off"
>
<template v-slot:append-item>
<div v-intersect="onIntersect" class="pa-4 teal--text">
Loading more items ...
</div>
</template>
</v-autocomplete>
data() {
return {
beers: [],
selected: null,
perPage: 30,
page: 1,
}
},
methods: {
getBeers() {
console.log('page', this.page)
const apiUrl = `https://api.punkapi.com/v2/beers?page=${this.page}&per_page=${this.perPage}`
axios.get(apiUrl)
.then(response => {
this.beers = [
...this.beers,
...response.data
]
})
},
onIntersect () {
console.log('load more...')
this.page += 1
this.getDate()
},
},
created() {
this.getData()
}
Working Codeply

Vue Random Router Component

{
path: '/link_1',
name: 'link_1',
component: () => import('./views/Link1.vue')
},
It is possible to have it one path like /link_1 but every time when go to this route load different component.
Like: First time when go to /link_1 load Link1.vue and second time when user go to /link_1 load and display Link2.vue.
You can use a combination of watch and <component> to render a dynamic component each time the link is clicked.
For example, this generates 100 components named component1 through component100, rendering one at random each time the <router-link></router-link> is clicked:
Vue.use(VueRouter)
const router = new VueRouter({
routes: [{
path: '/random/:id'
}]
})
const components = Array.from(Array(100), (x, i) => {
return {
name: `component${ i+ 1 }`,
props: ['lorem'],
template: `
<v-card>
<v-card-title>
<v-avatar>
<span class="blue-grey--text headline">${i + 1}</span>
</v-avatar>
</v-card-title>
<v-divider></v-divider>
<v-card-text>
<v-container fluid>
<v-layout justify-center>
<v-flex>
<span class="subheader" v-html="lorem"></span>
</v-flex>
</v-layout>
</v-container>
</v-card-text>
</v-card>
`
}
}).reduce((carry, c) => {
carry[c.name] = c
return carry
}, {})
new Vue({
el: '#app',
components,
router,
computed: {
current() {
return `component${this.cid}`
}
},
data() {
return {
cid: 1,
lorem: 'What mystery does the next page hold?'
}
},
watch: {
'$route': {
handler: function() {
let id = this.cid
while (this.cid === id) {
id = Math.floor(Math.random() * 100) + 1
}
this.cid = id
fetch('https://baconipsum.com/api/?type=all-meat&paras=3&format=html').then(res => res.text()).then(data => {
this.lorem = data
})
}
}
}
})
<link href='https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900|Material+Icons' rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/vuetify/dist/vuetify.min.css" rel="stylesheet">
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.21/vue.js"></script>
<script src="https://unpkg.com/vue-router#3.0.2/dist/vue-router.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vuetify/dist/vuetify.js"></script>
<div id="app">
<v-app>
<v-container>
<v-toolbar app>
<v-toolbar-items>
<v-btn :to="`/random/${cid}`" color="deep-orange darken-4" dark>Click Me</v-btn>
</v-toolbar-items>
</v-toolbar>
<v-content>
<v-slide-x-transition leave-absolute mode="out-in">
<component :is="current" :lorem="lorem"></component>
</v-slide-x-transition>
</v-content>
</v-container>
</v-app>
</div>