Display value of array from select input in Vuetify - javascript

I have a set of data which has a city name and a value attributed to the city. When someone selects the city it should show the value. I know that I can get the selection by having {{selected.value}}. However, as I want to extract the value to later use it in a calculation (i.e. sum for example 30 to it), I try to calculate it using a computed value. My problem is that I can't seem to return the value or a part of the array. Whenever I have return this.selected I can see the entire selected array, but when I have return this.selected.value or return.this.selected.name I get nothing.
I'm quite new to vuejs so I'm not sure what am I missing.
<template>
<v-container fluid>
<v-layout wrap align_center>
<v-flex xs12 sm6>
<v-select
v-model="selected"
:items="items"
item-text= "city"
item-value="value"
:menu-props="{ maxHeight: '400'}"
label="Select"
hint="Pick your favorite states"
multiple
persistent-hint
return-object
single-line
></v-select>
</v-flex>
<v-flex>
{{getselection}}
</v-flex>
</v-layout>
</v-container>
</template>
<script>
export default {
data () {
return {
text:'',
selected: [],
newsel: [],
items:[
{city: 'NY', value: 32},
{city: 'Gent', value: 80},
{city: 'Coimbra', value: 41}
]}
},
computed:{
getselection(){
return this.selected.value
}
},
}
</script>

Try to remove multiple prop from v-select component in order to return one item:
<v-flex xs12 sm6>
<v-select
v-model="selected"
:items="items"
item-text= "city"
item-value="value"
:menu-props="{ maxHeight: '400'}"
label="Select"
hint="Pick your favorite states"
persistent-hint
return-object
single-line
></v-select>
See the Pen
Vuetify Example Pen by boussadjra (#boussadjra)
on CodePen.
If you want to keep multiple prop the computed property could be like :
getselection(){
return !!this.selected.length ?this.selected[0].value:0;
}

Related

TextArea Avoid mutating a prop directly since the value will be overwritten

I know that a similar question has already been dealt with on stackoverflow. But I could not put together a solution from the proposed one. I am very ashamed.
The essence is this: I have a component and another one inside it.
The child component-VClipboardTextField is a ready-made configured text-area. I couldn't get the input out of there and I don't get an error when I try to enter it.
Avoid mutating a prop directly since the value will be overwritten
whenever the parent component re-renders. Instead, use a data or
computed property based on the prop's value. Prop being mutated:
"message"
code tabs-item.vue
<template>
<v-container fluid>
<v-row align="center">
<v-col cols="9">
<v-card flat>
<v-card-text>
<h1>Request</h1>
<v-container>
<v-textarea v-model="message"
placeholder="Placeholder"
label="Request"
auto-grow
clear-icon="mdi-close-circle-outline"
clearable
rows="10"
row-height="5"
#click:clear="clearMessage"
></v-textarea>
<v-textarea v-model="response"
placeholder="Placeholder"
label="Request2"
auto-grow
counter
rows="10"
row-height="5"
color="success"
></v-textarea>
<VClipboardTextField ></VClipboardTextField>
<VClipboardTextField isReadOnly></VClipboardTextField>
</v-container>
<v-row>
<v-btn
dark
color="primary"
elevation="12"
justify="end"
float-right
#click="sendRequest"
>
Send Request
</v-btn>
</v-row>
</v-card-text>
</v-card>
</v-col>
<v-col cols="3">
<schema-selector #changeSchema="onChangeSchema"></schema-selector>
</v-col>
</v-row>
</v-container>
</template>
<script>
export default {
name: 'tabs-item',
props: ['response'],
data() {
return {
schema: String,
message: '',
}
},
methods: {
sendRequest() {
const message = {
message: this.message,
method: this.schema.state
}
this.$emit('sendRequest', message)
},
clearMessage() {
this.message = ''
},
onChangeSchema(selectS) {
console.log("get schema: ", selectS.state)
this.schema = selectS
}
},
}
</script>
and child VClipboardTextField.vue
<template>
<v-container>
<v-tooltip bottom
v-model="show">
<template v-slot:activator="{ on, attrs }">
<v-textarea
v-model="message"
:append-outer-icon="'mdi-content-copy'"
:readonly="isReadOnly"
auto-grow
filled
counter
clear-icon="mdi-close-circle-outline"
clearable
label="Response message"
type="text"
#click:append-outer="copyToBuffer"
#click:clear="clearMessage"
></v-textarea>
</template>
<span>Tooltip</span>
</v-tooltip>
</v-container>
</template>
<script>
export default {
name: 'VClipboardTextField',
props: {
isReadOnly: Boolean,
message : { type :String, default: "msg"}
},
data() {
return {
show: false,
// messageLocal: 'Response!',
iconIndex: 0,
}
},
methods: {
copyToBuffer() {
console.log("this: ", this)
navigator.clipboard.writeText(this.message);
this.toolTipChange()
setTimeout(() => this.toolTipChange(), 1000)
},
clearMessage() {
this.message = ''
},
toolTipChange() {
if (this.show)
this.show = false
}
}
}
</script>
I will be glad to see an example of the code that will explain how to correctly solve this problem without crutches!
Thanks.
you cannot modify props in components, if the initial value of message is needed as placeholder (meaning the input might not be empty at the begining), you can store the data in message prop to another data variable and use that as v-model to the textarea.
if there is no initial value for message, just use another data variable for textarea and emit an update for message in a watcher.
in code tabs-item.vue
<VClipboardTextField :message.sync="message"></VClipboardTextField>
and child VClipboardTextField.vue
<template>
<v-container>
<v-tooltip bottom
v-model="show">
<template v-slot:activator="{ on, attrs }">
<v-textarea
v-model="message_slug"
:append-outer-icon="'mdi-content-copy'"
:readonly="isReadOnly"
auto-grow
filled
counter
clear-icon="mdi-close-circle-outline"
clearable
label="Response message"
type="text"
#click:append-outer="copyToBuffer"
#click:clear="clearMessage"
></v-textarea>
</template>
<span>Tooltip</span>
</v-tooltip>
</v-container>
</template>
<script>
export default {
name: 'VClipboardTextField',
props: {
isReadOnly: Boolean,
message : { type :String, default: "msg"}
},
data() {
return {
show: false,
// messageLocal: 'Response!',
iconIndex: 0,
message_slug: '',
}
},
watch: {
message_slug(x) {
this.$emit('update:message', x)
}
},
}
</script>
It will bind the value to message_slug and update the message on parent component when it's value changes.
Instead of watching for change every time, you can only emit when there are changes.
In your tabs-item.vue
<VClipboardTextField v-model="message"></VClipboardTextField>
In your VClipboardTextField.vue component, you can receive the v-model input prop as a "VALUE" prop and assign it to a local data property. That way u can manipulate the local property and emit only when in it is changed!
<template>
<v-container>
<v-tooltip bottom v-model="show">
<template v-slot:activator="{ on, attrs }">
<v-textarea
v-model="message"
:append-outer-icon="'mdi-content-copy'"
:readonly="isReadOnly"
v-on="on"
v-bind="attrs"
auto-grow
filled
counter
clear-icon="mdi-close-circle-outline"
clearable
label="Response message"
type="text"
#click:append-outer="copyToBuffer"
#click:clear="clearMessage"
#change="$emit('input', v)"
></v-textarea>
</template>
<span>Tooltip</span>
</v-tooltip>
</v-container>
</template>
<script>
export default {
name: "VClipboardTextField",
props: {
isReadOnly: { type: Boolean },
value: {
type: String,
},
},
data() {
return {
show: false,
message: this.value,
};
},
};
</script>

VuetifyJS Advanced slots autocomplete with Google Places API

I need to get VuetifyJS advanced slots to work with the Google Places API. Currently some addresses only show up in the autocomplete dropdown after clicking the "x" in the form field to delete the input text.
Here is a CodePen demonstrating the issue:
https://codepen.io/vgrem/pen/Bvwzza
EDIT: I just found out that populating the dropdown menu with the suggestions is the issue. The suggestions are visible in the console.log but not in the dropdown. Any ideas how to fix this issue?
(Some addresses work right away, some not at all - it's pretty random.
Any ideas on how to fix this are very welcome.)
JS:
new Vue({
el: "#app",
data: () => ({
isLoading: false,
items: [],
model: null,
search: null,
}),
watch: {
search(val) {
if (!val) {
return;
}
this.isLoading = true;
const service = new google.maps.places.AutocompleteService();
service.getQueryPredictions({ input: val }, (predictions, status) => {
if (status != google.maps.places.PlacesServiceStatus.OK) {
return;
}
this.items = predictions.map(prediction => {
return {
id: prediction.id,
name: prediction.description,
};
});
this.isLoading = false;
});
}
}
});
HTML:
<div id="app">
<v-app id="inspire">
<v-toolbar color="orange accent-1" prominent tabs>
<v-toolbar-side-icon></v-toolbar-side-icon>
<v-toolbar-title class="title mr-4">Place</v-toolbar-title>
<v-autocomplete
v-model="model"
:items="items"
:loading="isLoading"
:search-input.sync="search"
chips
clearable
hide-details
hide-selected
item-text="name"
item-value="symbol"
label="Search for a place..."
solo
>
<template slot="no-data">
<v-list-tile>
<v-list-tile-title>
Search for a <strong>Place</strong>
</v-list-tile-title>
</v-list-tile>
</template>
<template slot="selection" slot-scope="{ item, selected }">
<v-chip :selected="selected" color="blue-grey" class="white--text">
<v-icon left>mdi-map-marker</v-icon>
<span v-text="item.name"></span>
</v-chip>
</template>
<template slot="item" slot-scope="{ item, tile }">
<v-list-tile-avatar
color="indigo"
class="headline font-weight-light white--text"
>
{{ item.name.charAt(0) }}
</v-list-tile-avatar>
<v-list-tile-content>
<v-list-tile-title v-text="item.name"></v-list-tile-title>
<v-list-tile-sub-title v-text="item.symbol"></v-list-tile-sub-title>
</v-list-tile-content>
<v-list-tile-action> <v-icon>mdi-map-marker</v-icon> </v-list-tile-action>
</template>
</v-autocomplete>
<v-tabs
slot="extension"
:hide-slider="!model"
color="transparent"
slider-color="blue-grey"
>
<v-tab :disabled="!model">Places</v-tab>
</v-tabs>
</v-toolbar>
</v-app>
</div>
(I enabled the relevant API's in Google Cloud.)
the problem is the number of request you do in a certain amount of time. Every character triggers an request to the GoogleApi which is resulting in.
I think the error_message isn't totally correct while I trying afterwards it gives me a result.
To solve this,
upgrade your GoogleApi account
Debounce your input. so wait till the customer is not typing for half a second and then sen a request to The googleApi. You could use lodash to implement to debounce functionality https://lodash.com/docs/#debounce

<V-Model> doesn't work inside <V-Select> and only give no data available

lets say i want to make 2 text field and 1 v-select in vuejs using vuetify
Comodity ID (v-model = id)
Comodity Name (v-model = name)
v-select (v-model = selectType, :item= ['Using Document ID', id])
but whenever i try using the data such as this.id or id v-select always return No data available
I tried some of this topic but it doesn't solve my problem:
Vue Preselect Value with Select, v-for, and v-model
Vue dynamic v-model within v-for
Vue JS - Bind select option value to model inside v-for
this is my code :
<v-flex lg12 sm12>
<v-text-field label="Kode Penjualan" name="kodePenjualan" v-model="kodePenjualan">
</v-text-field>
</v-flex>
<v-flex lg12 sm12>
<v-text-field label="Komoditas" name="komoditas" v-model="komoditas">
</v-text-field>
</v-flex>
<v-flex lg12 sm12>
<v-select
v-model="selectDocs"
:items="tipeDocs"
label="Dokumen yang Dimiliki"
></v-select>
</v-flex>
this is my script:
data: () => ({
kodePenjualan: null,
komoditas: null,
selectDocs: null,
tipeDocs: [
'Dokumen Usaha Dagang Perantara',
kodePenjualan
],
}),
this is what i got right now
This is what i want to achieved
can someone help me with this?
Finally I can solve this, it seems i must computed tipeDocs properly to update my own :items,
computed: {
tipeDocs() {
return [
'Dokumen Usaha Dagang Perantara',
this.kodePenjualan
]
}
}
I hope this solution can help a lot of people who got stuck at the same problem with me
source : Answer for my question in Vue Forum

Using Vuetify how can I place a search bar over a carousel?

As the title says, I want to place a search bar functionality over a carousel and I'm trying to achieve this using <v-autocomplete> and v-carousel>.
Using the code snippets from the official Vuetify docs, I have managed to have this:
<template>
<v-layout
justify-center
app
>
<v-flex
xs12
sm6
>
<v-container
fluid
grid-list-md
>
<v-layout
row
wrap
>
<!--Carousel-->
<v-flex xs6>
<v-carousel
hide-controls
hide-delimiters
height='200'
interval='2500'
>
<v-toolbar
dark
color="teal"
>
<v-toolbar-title>State selection</v-toolbar-title>
<v-autocomplete
v-model="select"
:loading="loading"
:items="items"
:search-input.sync="search"
cache-items
dense
hide-no-data
hide-details
label="What state are you from?"
solo-inverted
>
</v-autocomplete>
<v-btn icon>
<v-icon>more_vert</v-icon>
</v-btn>
</v-toolbar>
<v-carousel-item
v-for="(item,i) in items"
:key="i"
:src="item.src"
>
</v-carousel-item>
</v-carousel>
</v-flex>
</v-layout>
</v-container>
</v-flex>
</v-layout>
</template>
<script>
<!--I use selective imports. This might not be needed for you when trying to reproduce it -->
import VContainer from "vuetify/lib/components/VGrid/VContainer";
import VFlex from "vuetify/lib/components/VGrid/VFlex";
import VLayout from "vuetify/lib/components/VGrid/VLayout";
import VCard from "vuetify/lib/components/VCard/VCard";
import VImg from "vuetify/lib/components/VImg/VImg";
import VCarousel from "vuetify/lib/components/VCarousel/VCarousel";
import VAutocomplete from "vuetify/lib/components/VAutocomplete/VAutocomplete";
export default {
name: "HomeContents",
data: () => ({
loading: false,
items: [],
search: null,
select: null,
states: [
'Alabama',
'Alaska',
'American Samoa',
'Arizona',
'Arkansas',
'California',
'Colorado',
'Ohio',
'Oklahoma',
'Oregon',
'Washington',
'West Virginia',
'Wisconsin',
'Wyoming'
]
}),
watch: {
search (val) {
val && val !== this.select && this.querySelections(val)
}
},
methods: {
querySelections (v) {
this.loading = true
// Simulated ajax query
setTimeout(() => {
this.items = this.states.filter(e => {
return (e || '').toLowerCase().indexOf((v || '').toLowerCase()) > -1
})
this.loading = false
}, 500)
}
},
components: {
VContainer,
VFlex,
VLayout,
VCard,
VImg,
VCarousel,
VAutocomplete
}
}
</script>
The problems I am facing are the following:
How can I lose the teal toolbar and have just one simple single line to use for searching, that will be positioned in the center of the carousel?
Whenever I click on the search bar, I see this: [object Object]. How do I get rid of this?
With my current implementation, every time I'm searching for a state I'm able to successfully find it but the problem is that the carousel background transition effect stops. So for example, If I search for "Oklahoma" I can see the result but the background carousel transition stops. How can this be fixed?
I'll tackle your questions as you've put them.
1: The teal color is specified in your declaration of v-toolbar.
<v-toolbar
dark
color="teal"
>
You can set this color to anything you want, rgb or hex, so if you want it to be transparent you could do this.
<v-toolbar
dark
color="rgba(0,0,0,0)"
>
To specify the position of the toolbar comes down to styling. You can adjust the default vuetify styles but for a single item like this the easiest way to set styling that will override the default is to use inline styling, like this:
<v-toolbar
dark
color="rgba(0,0,0,0)"
style="position:absolute;top:75px;z-index:400;"
>
As you've set the height, you can position the toolbar to center it. The z-index may be necessary to place it above the carousel. In here you could also style the text color, width etc.
2: In your posted code the reason you are getting [object Object] is because the v-autocomplete is trying to iterate through 'items' which is empty. You have 'states'. Set items like this: :items="states" To get this working as expected I set it up like this:
<v-autocomplete
style="background:rgba(0,0,0,0)"
v-model="select"
:items="states"
:loading="isLoading"
:search-input.sync="search"
color="white"
hide-no-data
hide-selected
item-text="Description"
item-value="state"
label="States"
placeholder="Start typing to Search"
prepend-icon="mdi-database-search"
return-object
>
</v-autocomplete>
Which is straight from the vuetify docs.
3: I can't reproduce the carousel pausing, it continues throughout on mine.
Hope this helps somewhat.

toLowerCase localeCompare does not work in NuxtJs VueJs Framework

I have encounter a very strange issue in NuxtJs (VueJs Framework).
I have a code which was working well for my stores list in alphabetical order and search filter. As it was working I copied the same code functionality for my categories. The next day when I click on categories it worked fine but on stores it gave me this two errors:
Cannot read property 'localeCompare' of undefined
Cannot read property 'toLowerCase' of undefined
Not sure what went wrong its the same code on both pages, only the difference in data it loads for stores and categories. If remove both localeCompare & toLowerCase it loads the data properly but without the search filter and the list unordered. Below is my code:
<script>
import axios from "axios";
export default {
asyncData({ req, params }) {
return axios.get(process.env.apiURL + "stores").then(res => {
return {
stores: res.data
};
});
},
data() {
return {
apiURL: process.env.apiURL,
active: null,
search: "",
Searched: "",
filterStores: [],
storeList: ['A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z']
}
},
methods: {
filterStore(n) {
this.tab = n;
axios.get(process.env.apiURL + 'stores?filter[where][store_name][regexp]=^\\b' + this.tab + '/i').then(res => {
return this.filterStores = res.data;
});
}
},
computed: {
AllStores: function() {
return this.stores.filter(store => {
return store.store_name.toLowerCase().includes(this.search.toLowerCase())
})
}
},
head: {
title: "Stores"
}
};
</script>
<template>
<v-container grid-list-md text-xs-center>
<v-text-field append-icon="search" v-model="search" id="filter" name="filter"
label="Search Your Favourite Store . . . ." auto-grow autofocus dont-fill-mask-blanks solo>
</v-text-field>
<br/>
<v-tabs grow dark color="teal accent-4" show-arrows slider-color="white">
<v-tab active>#</v-tab>
<v-tab v-for="n in storeList" :key="n" ripple #click="filterStore(n)">{{ n }}</v-tab>
<v-tab-item>
<v-layout row wrap>
<v-flex v-for="(store, index) in AllStores" :key="index" xs6 sm4 md2 lg2 xl3>
<v-card light>
<nuxt-link :to="'/store/'+store.store_name">
<v-card-media :src="`${apiURL}containers` + `${store.store_image}`" height="80px"></v-card-media>
<v-card-text class="blue">{{store.store_name}}</v-card-text>
</nuxt-link>
</v-card>
</v-flex>
</v-layout>
</v-tab-item>
</v-tabs>
<br/>
<v-layout row wrap>
<v-flex v-if="filterStores != ''" v-for="(store, index) in filterStores" :key="index" xs6 sm4 md2 lg2 xl3>
<v-card light>
<nuxt-link :to="'/store/'+store.store_name">
<v-card-media :src="`${apiURL}containers` + `${store.store_image}`" height="80px"></v-card-media>
<v-card-text class="blue">{{store.store_name}}</v-card-text>
</nuxt-link>
</v-card>
</v-flex>
<v-flex v-else>No Stores Available starting with this letter</v-flex>
</v-layout>
</v-container>
</template>
I tried to update my vue cli and reinstalled the modules and it worked, thanks

Categories

Resources