I am trying to populate a vuetify v-select from a rest api json response. Below is the code I have so far. Populating the list using a simple array is no problem but I am having difficutly setting both the value and text properties.
<template>
<v-container fluid>
<v-slide-y-transition mode="out-in">
<v-layout column align-center>
<v-select v-model="dbSelect" v-on:change="dbConnect()" :items="dbOptions" single-line></v-select>
</v-layout>
</v-slide-y-transition>
</v-container>
</template>
<script>
import axios from 'axios'
export default {
name: 'HelloWorld',
data () {
return {
dbSelect: '',
dbOptions: [],
}
},
mounted () {
axios.get('http://localhost:5000/api/values')
.then(r => {
// var formatted = []
for (let i = 0; i < r.data.length; i++) {
this.dbOptions.push(r.data[i])
// formatted[i] = { value: r.data[i].id, text: r.data[i].name }
}
},
error => {
console.error(error)
}
)
}
}
</script>
This is the simple Json dataset:
[{"id":1,"name":"A"},{"id":2,"name":"B"},{"id":3,"name":"C"},{"id":4,"name":"D"},{"id":5,"name":"E"}]
Currently I am pushing in the whole object because I have been trying to use item-value and item-text but according to documentation I can see that is not right. r.data[i].id and r.data[i].name produce a drop-down list as expected. I want to set dbSelect to the value of the selection on change for a secondary call after selection.
Many thanks all for your help.
I had the same issue and felt this needed to be added as the correct answer that solved the issue.
Using the properties of item-text="" and item-value=""
<v-select
:items="dbOptions"
v-model="dbSelect"
item-text="name"
item-value="id"
></v-select>
The array of objects using name and id
[{"id":1,"name":"A"},{"id":2,"name":"B"},{"id":3,"name":"C"},{"id":4,"name":"D"},{"id":5,"name":"E"}]
See Example
This was originally answered by #Bert in the comments.
Related
I dynamically draw form input component (as in the image) using this code:
In this case the key can be "name","gruppo","codice" and so on.
<v-row>
<v-col v-for="(key,i) in keys_visible" :key="key" v-if="headers_visible[i].visible == true" cols="12" sm="12" md="12"
v-if="!(headers_visible[i].type == 'bit' && editedItem[key] == -9)">
<v-text-field #change="comp_change(key)" v-else-if="headers_visible[i].type == 'varchar'" v-model="editedItem[key]" :label="headers_visible[i].text"></v-text-field>
</v-col>
</v-row>
Then I have comp_change function which is defined in methods block:
comp_change (par1) {
var self = this;
self.editedItem["name"] = "example text";
},
I have placed a debugger; at the beginning of comp_change function, and it stops everytime so the function is triggered, but without displaying new value in "Nome" field (which v-model is editedItem["name"]). Why after comp_change I can't see "example text" in the field?
The form is already opened when I fire change
This is likely a reactivity issue. You should read up on this here. Also, if you use v-model, you do not need to set the value yourself, meaning you can do away with the #change call. You have two options as I see it.
a. Use root data objects on your component instead of an array/object and then use v-model as normal. This looks like:
<template>
<v-text-field v-model="name" />
<v-text-field v-model="email" />
</template>
<script>
export default {
data() {
return {
name: '',
email: '',
etc: ''
}
}
}
</script>
Now, when your form fields are updated by the user, you won't need to use #change to set the value. It will happen automatically.
b. Or, set the model with Vue.set(). In this case, you are not going to use v-model. Instead, you have defined your own methods to manage the data. This looks like:
<template>
<v-text-field #change="comp_change(key)" />
</template>
<script>
import Vue from 'vue';
export default {
data() {
return {
editedItem: {}
}
},
methods: {
comp_change (par1) {
Vue.set( this.editedItem, 'name', 'example text' );
}
}
}
</script>
I have two methods in a vue component.
First makes the user choose from a v-select, either itemone or itemtwo. Then, to retreive the value for later i call #change to assign the variable to a method declared later - getItemValue.
Second is a submit button, when clicked, we go to handleSubmit.
After handleSubmit is called, I want to use the value I got from getItemValue (in variable theItem), but how can I call another method if it's out of my scope?
Mycomponent.vue
<template>
<v-form
ref="form"
v-model="valid"
lazy-validation
>
<v-select
v-model="select"
:items="items"
#change="getItemValue"
></v-select>
<v-btn
#click="handleSubmit"
>
Submit
</v-btn>
</v-form>
</template>
<script>
export default {
data: () => ({
items: [
'itemone',
'itemtwo'
],
}),
methods: {
getItemValue(theItem) {
},
handleSubmit(e) {
e.preventDefault()
// i need "theItem" here!
}
},
}
</script>
v-model already writes to your local variable, so there is absolutely no need to setup a get method to write the select value to a variable.
Actually, v-model is a bit more complicated than just 'write' to a variable, but the important bit is that in your template you are setting up v-model="select", which basically means that whenever the user uses the select to pick a value, your local select variable will be updated with the selected value.
Now, there is no select in your example component data, I don't know why. But if you had it, you could just sent that variable in your handleSubmit:
<template>
<v-form
ref="form"
v-model="valid"
lazy-validation
>
<v-select
v-model="select"
:items="items"
></v-select>
<v-btn
#click="handleSubmit"
>
Submit
</v-btn>
</v-form>
</template>
<script>
export default {
data: () => ({
select: '',
items: [
'itemone',
'itemtwo'
],
}),
methods: {
handleSubmit(e) {
e.preventDefault()
doSomethingWith(this.select); // this will be updated at this point
// with the option the user selected
}
},
}
</script>
Now, however, be aware that if the select variable is a component prop, then you should not do this right away, since props are not intended to be modified directly by child components. If that would be the case, please update your question with more info.
You would simple set the variable (theItem) value to the data
getItemValue(theItem) {
this.theItem;
},
and then retrieve it later
handleSubmit(e) {
e.preventDefault()
// i need "theItem" here!
// simple access theItem
console.log('theItem', this.theItem);
}
I use vuetify in my project and need typeahead component. Sadly v-autocomplete implemented as combobox with filter, so it doesn't allow setting user input as v-model (or at least I can't find I way how to do so).
Could someone please explain me how to implement such functionality (maybe by another vuetify component)? I load items from server, but they are serve just as suggestions. Users need to have an ability to type and set any value they want to.
Here is a base example https://codepen.io/miklever/pen/oMZxzZ. The problem is that if I type any word that doesn't start with 'John' v-autocomplete clears it on blur. I've tried to set v-model manually and to add user input to array, but any of this methods has issues and doesn't work as expected.
<div id="app">
<v-app>
<v-content>
<v-container>
<p>Name: {{ select || 'unknown'}}</>
<v-autocomplete
:items="items"
:search-input.sync="search"
v-model="select"
cache-items
flat
hide-no-data
label="Name"
></v-autocomplete>
</v-container>
</v-content>
</v-app>
</div>
new Vue({
el: "#app",
data: () => ({
items: [],
search: null,
select: null,
commonNames: ["John", "John2", "John3"]
}),
watch: {
search(val) {
val && val !== this.select && this.querySelections(val);
}
},
methods: {
querySelections(v) {
setTimeout(() => {
this.items = this.commonNames.filter(e => {
return (e || "").toLowerCase().indexOf((v || "").toLowerCase()) > -1;
});
}, 500);
}
}
});
In Vuetify 1.1.7 Combobox has new feature which you can refer to.
Its on the Advance custom options.
had this same issue and solved it with the v-combobox it's kinda like the same as v-autocomplete so, you can just replace your tags with <v-combobox></v-combobox> or check the documentation here: https://vuetifyjs.com/en/components/combobox/#usage
I am getting the error below. The weird part is that I'm positive the data is there because in my vue add on I can see that it successfully grabs the information from the vuex store. My initial guess is that somehow the data is not yet grabbed from the store, at the point that it creates the template?
Vue warn]: Error in render: "TypeError: Cannot read property 'length' of undefined"
The data: 'spaces' is grabbed from the store.
export default {
name: "myspaces",
data() {
return {
filterMaxLength: 3,
selectedSpace: 0,
selectedRoom: 0
}
},
created() {
// Default selected space (first in json)
this.selectedSpace = this.spaces[0].id;
// Default selected room (first in json)
this.selectedRoom = this.spaces[0].rooms[0].id;
},
computed: {
// Get 'spaces' from store.
...mapState([
'spaces'
])
}
Template:
<template>
<div>
<v-flex v-if="spaces.length < filterMaxLength">
<v-btn v-for="space in spaces">
<h4> {{space.name}} </h4>
</v-btn>
</v-flex>
</div>
<template>
The store:
import Vuex from 'vuex'
Vue.use(Vuex);
export default new Vuex.Store({
state: {
spaces:[
{
id:1,
name:'House in Amsterdam',
rooms:[
{
id:1,
name:'Bedroom Otto',
},
{
id:2,
name:'Bedroom Mischa'
}
]
},
{
id:2,
name:'Office in Amsterdam',
rooms:[
{
id:1,
name:'Office 1',
},
{
id:2,
name:'Office 2'
}
]
}
]} });
The vue chrome add on says this information is in the component:
Always before check length, be sure your property its set then check length
<v-flex v-if="spaces && spaces.length < filterMaxLength">
Update ECMAScript 2020
You can use Optional chaining for this purpose too
<v-flex v-if="spaces?.length < filterMaxLength">
You should use Object.keys(spaces).length, such as:
<template>
<div>
<v-flex v-if="typeof spaces !== 'undefined' && typeof spaces === 'object' && Object.keys(spaces).length < filterMaxLength">
<v-btn v-for="space in spaces">
<h4> {{space.name}} </h4>
</v-btn>
</v-flex>
</div>
<template>
just to be sure you have following in your vue
import { mapState } from "vuex";
Else, you can use getters also, eg. :
In your vue file
v-if="this.getSpaces.length !== 0"
In computed fonctions of your vue file
getSpaces() {
return this.$store.getters.getSpaces;
}
In your store
getters: {
getSpaces: state => {
return state.spaces;
}
},
I also had this problem, I imported a sass style sheet with functions(#mixins) and a sass style sheet with variables into one sass style sheet.
I imported them as
(
#import url('./_variables.scss');
#import url('./_func.scss');
)
so i just took out the url() for both import statements and that error went away.
I'm working on a VueJs file and try to use <v-select> so what I'm doing is that :
<v-select :options="divisions" label="text" ></v-select>
and my divisions is an array of object conatining id and text but when i'm going on my page I have <% getOptionLabel(option) %> instead of the text value for each one of my divisions value
here is a screenshot of console.log(this.divisions) :
So this is my code :
<form id="MassUpdateDivisionForm">
<v-select v-bind:label="text" :options="divisions"></v-select>
</form>
<script>
import vSelect from "js/vue-select/vue-select.js"
export default {
props: ['product'],
components: {vSelect},
data() {
return {
divisions: []
}
}
methods: {
getDivisions(){
let self = this
this.$http({
url: 'divisions',
method: 'get'
}).then((response)=>{
self.$set('divisions', response.data)
console.log(self.divisions)
//that's where I got the pic
},(response)=>{
alert('something went wrong')
}
)
}
},
created () {
this.getDivisions()
},
}
</script>
If I am understanding you correctly, you want the text attribute of the selected option to be displayed as the label? If so, you will need to pass the data of the selected option back to the <v-select>. You can emit an event on change to change label to the text value, but make sure you bind to the label attribute using either v-bind:label=textor the shorthand :label=text
I just had the same problem and solved it by passing the name of the label as a string.
<v-select :options="warehouses" :label="'name'"></v-select>
or you could do it with an html attribute without vue binding.
<v-select :options="warehouses" label="name"></v-select>
Cheers,