I'm creating a form with a v-combobox component.
The :items are being retrieved from a table in my DB and I am using v-model to enter whatever is selected into a different table in the DB, so I'm using v-model to link to the new DB table.
I know that I can use v-model to set a default value (meaning that that item is automatically selected), however is there an alternative way to do this since I'm currently using v-model for connecting to the DB?
Form:
<v-combobox
outlined
:items="allTypes"
v-model="plates[plates.findIndex(obj => obj.id === 1)].value"
:search-input="search"
>
</v-combobox>
If I'm following what you are trying to accomplish here...
You want to have a default value set on your combo box that is not the true value of the data it is binded to with v-model?
I'm not sure that is a great idea. Because if the user wants the default value they will leave it, thinking "it's already set to what I want" but it's not actually an accurate reflection of the value they would be setting?
Either way, it sounds like you probably want to move the logic from your current v-model prop to a computed property, so you can separate the logic of getting and setting.
UPDATED With Code Snippet
new Vue({
el: '#app',
vuetify: new Vuetify(),
data() {
return {
// the set value, initially false to use as a 'has a value been set' flag
setValue: false,
// the default value shown before selection has happened
defaultValue: "Pick a value (default)",
// the options to select from
allTypes: [
'dogs',
'cats',
'hamsters',
'something else',
],
// your table data
table: {
value: "null (initially)"
}
}
},
computed: {
// the value the we are binding the combo box to
comboBoxValue: {
// the value to output
get() {
// if a value has not been set
if (!this.setValue) {
// return the default
return this.defaultValue;
} else {
// else return whatever you would like
return this.setValue;
/* plates[plates.findIndex(obj => obj.id === 1)].value */
}
},
// the function that happens when the combo box is set
set(val) {
// val is the value the combox HAS been set to, not something you define here
console.log(val);
// update your table, pass in "val" the combo box value
this.updateTable(val);
// update the set value, combo box no longer show the default value
this.setValue = val;
}
}
},
methods: {
// some method to update your table
updateTable(newValue) {
alert('update table with value: ' + newValue)
this.table.value = newValue;
}
}
})
<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">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no, minimal-ui">
<div id="app">
<v-app>
<v-content>
<v-container fluid>
<v-row>
<v-col cols="12">
table value: {{table.value}}
</v-col>
<v-col cols="12">
<v-combobox outlined :items="allTypes" v-model="comboBoxValue">
</v-combobox>
</v-col>
</v-row>
</v-container>
</v-content>
</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>
Related
How to add tootlip in the disabled days when using the Vuetify's date picker
I cannot seem to find it in documentation, is this possible somehow?
I don't think that you can do this in Vuetify because there are no slots provided to customize the dates' display. I can think of one solution using pure JS. The strategy would be to-
Find all disabled date elements and assign a title attribute (HTML tooltip) to it.
Important 1- The title attribute will not work with the disabled elements, so, you need to use pointer-events: auto on that disabled element. (Reference from this answer.)
Important 2- Above CSS will add a pointer cursor on the disabled button but it won't trigger any click event.
Here is a working demo. Try hovering on disabled dates and you should see a tooltip. Hope this helps.
new Vue({
el: '#app',
vuetify: new Vuetify(),
data: () => ({
date: '2023-02-16',
}),
mounted() {
let disabled_dates = document.querySelectorAll('.v-date-picker-table button');
disabled_dates.forEach(date => {
if(date.disabled) {
date.title = "tooltip";
}
})
},
methods: {
allowedDates: val => parseInt(val.split('-')[2], 10) % 2 === 0,
},
})
.v-btn--disabled {
pointer-events: auto !important;
}
<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>
<link href="https://cdn.jsdelivr.net/npm/vuetify#2.x/dist/vuetify.min.css" rel="stylesheet">
<div id="app">
<v-app id="inspire">
<v-row justify="center">
<v-date-picker
v-model="date"
:allowed-dates="allowedDates"
class="mt-4"
min="2023-02-01"
max="2023-02-28"
></v-date-picker>
</v-row>
</v-app>
</div>
The Problem-
The purpose of this v-text-field is, to allow users manually type in and change their name on the website. But for security, I hope to hide all the parts of the input value except the last char of the username.
Since the Vuetify text field is two-way binding, it's cumbersome to set up. I didn't find the proper npm extension to serve this request as well.
My Code-
<template>
<ValidationProvider>
<v-text-field
hide-details="auto"
v-model="YourName"
label="username"
placeholder="type your name" />
</ValidationProvider>
</template>
<script>
export default {
data() {
return {
YourName: ''
}
}
}
</script>
Expectation
(1) User type name as "Allen Walker" in the text field.
(2) v-model receives the user name "Allen Walker" to Database. If he buys products from the website, the username will automatically be put as "Allen Walker" in the step of Checkout.
(3) What I want to achieve-
In the User-Profile, the username will be displayed and the user can edit it but before clicking on the text field, the displayed name should look like "**********r".
There could be more methods to do this but that relies on your UX as well like how you want to show the hidden characters and when to show the full name, etc.
I can think about the subsequent technique-
On the user profile page's mounted hook, replace the desired characters with the special symbol (*), and make your text field read-only, so it won't update.
When focusing on the text field, show the full name inside it and make it editable.
When focusing out from the text field, save the updated name to your DB, replace the desired characters with the special symbol (*), and make the text field read-only again.
Here is the functioning demo-
<!DOCTYPE html>
<html>
<head>
<link href="https://cdn.jsdelivr.net/npm/vuetify#2.x/dist/vuetify.min.css" rel="stylesheet">
</head>
<body>
<div id="app">
<v-app>
<v-text-field
label="username"
:readonly="readonly"
v-model="updatedName"
#focus="onFocus"
#blur="onBlur"
></v-text-field>
</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>
<script>
new Vue({
el: '#app',
vuetify: new Vuetify(),
data() {
return {
readonly: true, // initial state
username: "nehasoni", // this should come from API
updatedName: null, // for v-model use
}
},
mounted() {
this.hideName()
},
methods: {
hideName() {
// replace all characters except first with a *
this.updatedName = this.username.replace(/.(?=.{1,}$)/g, '*');
},
onFocus() {
// make text field editable
this.readonly = false;
// show full name
this.updatedName = this.username;
},
onBlur() {
/**
* save your name to database and assign response to the username, like this-
* this.username = api_response
* For now, I am using updatedName as API response
*/
this.username = this.updatedName;
// make text field read only again
this.readonly = true;
// Hide the name again.
this.hideName();
}
}
})
</script>
</body>
</html>
I want to make vuetify v-autocomplete behave like google search bar
Do not open dropdown when focusing
Only show dropdown when user press Enter key in searchbar
In https://vuetifyjs.com/en/api/v-autocomplete/, I did not see any function could control dropdown is shown or not
you can bind items to an empty array like searchResults and have your actual items in another array, then you can use #update:search-input event to update the searchText property and then call a method on #keydown.enter to populate the searchResults array.
also use hide-no-data prop to prevent dropdown from opening when there is no data in searchResults array.
side-note: you can pass empty string to append-icon prop to remove the drop down icon from the input
try the demo below by typing 'zz' in the input and pressing enter for example:
Vue.config.productionTip = false;
Vue.config.devtools = false;
new Vue({
el: '#app',
vuetify: new Vuetify(),
data: () => ({
items: ['foo', 'bar', 'fizz', 'buzz'],
searchResults: [],
searchText: '',
msg: '',
}),
methods: {
search() {
this.searchResults = this.items.filter((x) => this.searchText && x.includes(this.searchText));
this.msg = `${this.searchResults.length} result(s) found`;
},
},
});
<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">
<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>
<div id="app">
<v-app>
<v-container>
<v-autocomplete ref="searchBar" :items="searchResults" outlined dense hide-no-data label="type and press Enter to search" #update:search-input="searchText = $event" #keydown.enter="search" :messages="msg" append-icon=""></v-autocomplete>
</v-container>
</v-app>
</div>
I need to add a listener to a vue-multiselect, like this (but this does not work):
$('.multiselect').change(console.log("multiselect changed"));
It must be added in the updated hook.
I've tried a lot of things, but because of the nature of vue-multiselect, conventional jQuery doesn't work ie, you can't listen for a change on the multiselect__input because its value doesn't actually change.
There's a .multiselect__single element that is added\removed depending on the state, but I'd rather not listen\test for html changes.
The vue-multiselect events don't include change, but you're probably looking for input (emitted after the value changes) or searchChanged (emitted after the search query changes).
The idiomatic way to listen to an event is to use this syntax: #EVENTNAME="METHOD". Example:
<multiselect #input="onSelection">
new Vue({
el: '#app',
components: {
Multiselect: window.VueMultiselect.default
},
data() {
return {
value: '',
options: ['list', 'of', 'options']
};
},
methods: {
onSelection(newValue) {
console.log({newValue})
}
}
})
<script src="https://unpkg.com/vue#2.5.17"></script>
<script src="https://unpkg.com/vue-multiselect#2.1.0"></script>
<link rel="stylesheet" href="https://unpkg.com/vue-multiselect#2.1.0/dist/vue-multiselect.min.css">
<div id="app">
<multiselect :options="options" v-model="value" #input="onSelection"></multiselect>
<div>value: {{value}}</div>
</div>
I'm trying to follow this video using Vue and Vuetify to apply the current date with v-model to the date picker component v-date-picker using the data value date that's initially being set with new Date().
This is a simplified structure of my project:
JS
new Vue({
el:"#app",
data: {
date: new Date(),
time: new Date()
}
})
Template
<div id="app">
<v-date-picker v-model="date"></v-date-picker>
{{ date }}
<v-time-picker v-model="time"></v-time-picker>
</div>
And here's a CodePen. Unfortunately I couldn't get the Vuetify CSS to work with the CodePen, but if you open up the console, you'll see that I get errors in the v-date-picker when trying to use new Date() with the v-model directive. Also the date picker isn't rendering. The v-time-picker however works fine.
On my local setup I've created a Vue project with the vue-cli. Here's the error I'm getting there:
[Vue warn]: Error in created hook: "TypeError: dateString.split is not
a function"
found in
--->
at src/components/Meetup/CreateMeetup.vue
at src/App.vue
I'm doing exactly as in the tutorial I'm following, so I don't know if this is a bug with the latest version of either Vue or Vuetify? Or am I missing something?
Obviously (from the error message you're getting) v-datepicker expects to be bound to a String. You might want to try
data: {
date: new Date().toJSON(),
time: new Date().toJSON()
}
https://codepen.io/connexo/pen/ypWxLv
Also see Vuetify API docs (which explicitly states it expects v-model to be of type String):
v-model String null Controls the displayed date. Must use ISO 8601 format.
Instead, use the value attribute in order to overcome the binding.
example
data: {
date: new Date().toISOString().substr(0, 10)
}
<v-text-field slot="activator" :value="dataValue.datePass" label="Date" append-icon="event" readonly style="font-size:14px"></v-text-field>
<v-date-picker v-model="dataValue.datePass"></v-date-picker>
In my case, I needed the date to be stored as a Date object instead of a String. So instead of using v-model in the date-picker, I handled this using #input and :value.
new Vue({
el: '#app',
data() {
return {
isActive: false,
theDate: new Date()
}
},
computed: {
formattedDate() {
return this.theDate ? moment(this.theDate).format('MM/DD/YYYY') : undefined; // Custom format
},
datePickerFormattedDate() {
return this.theDate ? moment(this.theDate).format('YYYY-MM-DD') : undefined; // Date picker objects needs date in this particular format
}
},
methods: {
inputHandler(date) {
if (typeof date === 'string')
date = moment(date).toDate();
this.isActive = false;
this.theDate = date;
}
}
})
<html>
<head>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.22.1/locale/en-gb.js">
</script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vuetify/1.3.12/vuetify.min.js">
</script>
<script src="https://cdn.jsdelivr.net/momentjs/2.10.6/moment-with-locales.min.js">
</script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/material-design-icons/3.0.1/iconfont/material-icons.min.css">
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900|Material+Icons">
<link rel="stylesheet" href="https://unpkg.com/vuetify/dist/vuetify.min.css">
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
<div id="app">
<v-app id="inspire">
<v-content>
<v-container>
<v-layout row wrap>
<v-flex pb-4 xs12>
Stored date: {{ theDate }}
</v-flex>
<v-flex xs12>
<v-text-field :readonly="true" :value="formattedDate" label="I want to enter dates here"></v-text-field>
<v-menu :close-on-content-click="true" v-model="isActive" :nudge-right="40" lazy transition="scale-transition" offset-y full-width min-width="290px">
<v-icon slot="activator">event</v-icon>
<v-date-picker :value="datePickerFormattedDate" #input="inputHandler"></v-date-picker>
</v-menu>
</v-flex>
</v-layout>
</v-container>
</v-content>
<v-footer></v-footer>
</v-app>
</div>
</body>
</html>
You can use a computed property as a "shim" for v-model. The computed property contains all the logic for the type coercion and everything else is business as usual.
JS
new Vue({
el:"#app",
data: {
date: new Date()
},
computed: {
// "shim" for v-date-picker
sdate: {
get() {
return this.date?.toISOString()
},
set(val) {
this.date = new Date(val)
}
}
}
})
Template
<div id="app">
<v-date-picker v-model="sdate"></v-date-picker>
{{ date }}
</div>
Vuetify date picker need date in that particular format ('YYYY-MM-DD'). This could be solved by replacing this with:-
new Vue({
el:"#app",
data: {
date: moment(new Date()).format('YYYY-MM-DD'),
time: new Date()
}
})
From the official examples, it looks like you have to use like this
data: {
date: new Date().toISOString().substr(0, 10),
time: new Date().getHours() + ':' + new Date().getMinutes(),
}
Example -
https://github.com/vuetifyjs/vuetifyjs.com/blob/master/src/examples/date-pickers/dateDialogAndMenu.vue