Using new Date() with v-date-picker doesn't work - vue.js

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

Related

Vuetify date picker add tooltip in disabled days

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>

Vue3 v-calendar v-date-picker Moving to Next Month

I want to generate an event when I move to the next month or to the previous month.
I'd really appreciate your help.
Is there an event that can use this function?
Here's my code.
<v-date-picker
v-if="reservList[0].dates.length>0"
is-expanded
locale="ko"
color="indigo"
class="date-picker"
:model-config="{
type: 'string',
mask: 'YYYY-MM-DD',
}"
:masks="{ L: 'YYYY.MM.DD',title: 'YYYY년 MM월' }"
mode="date"
v-model="pickDate"
:attributes="reservList"
:reactive="true"
#change:month="changeMonth"
>
</v-date-picker>
<script>
export default{
setup(){
//none action
function monthChange(e){
console.log('test',e);
}
return{
monthChange
}
}
}
</script>
https://vcalendar.io/api/v2.0/datepicker.html
I tried the API of the site, but there was no clear result.
The event you are looking for is #update:from-page.
It sends a page object as parameter.
Example:
<template>
<v-date-picker update:from-page="changeMonth">
</template>
<script setup>
function changeMonth(page) {
console.log(`Moved to ${page.month} (${page.monthLabel}) month.`)
}
</script>

How to reset a v-input-file with vuetify?

I'm trying to reset my v-input-file when i click on a button. But, i don't see any function to do that.
I tried the following commands :
(upload_json is the name of my v-input-file)
this.$refs.upload_json.files=[]
this.$refs.upload_json.files=null
this.$refs.upload_json.value=""
this.$refs.upload_json.reset()
For all the commands, I had the same following error :
Uncaught TypeError: proxy set handler returned false for property
You can clear input by using this approach
<div id="app">
<v-app id="inspire">
<v-file-input
v-model="files"
accept="image/png, image/jpeg, image/bmp"
placeholder="Pick an avatar"
prepend-icon="mdi-camera"
label="Avatar"
></v-file-input>
<v-btn #click="restInput">Clear Input</v-btn>
</v-app>
</div>
main.js
new Vue({
el: '#app',
vuetify: new Vuetify(),
data: () => ({
files:{},
}),
methods:{
restInput(){
this.files = {}
}
}
})
you can use this.$refs.upload_json.value=null
You can clear input this way:
this.$refs.upload_json.internalValue = this.multiple ? [] : null
I tested it and it works. If you look at the source of the v-file component, that is how Vuetify developers clear the input when you click on the clear icon.
Try the following
this.$refs.upload_json.$refs.input.value = null
With Vue2, there was no warning as well!

Vuetify Date Picker - How to Set the initial date on dialog usage

I have tried using picker-date prop, and looked at the others, but I can't yet figure out how to have <v-date-picker> show with the year, month and day of my own choosing. Has anyone done this and know how to manage it? The component where the picker is used is a child component, and the date I'd like to initialize with comes in as a prop.
I tried with picker:'2020-06-04' initial value in v-data-picker and its showing this chosen value. Are you looking for something similar?
https://codepen.io/manojkmishra/pen/oNbYPvv?editors=1010
<div id="app">
<v-app id="inspire">
{{picker}}
<v-row justify="center">
<v-date-picker v-model="picker"></v-date-picker>
</v-row>
</v-app>
</div>
new Vue({
el: '#app',
vuetify: new Vuetify(),
data () {
return {
picker:'2020-06-04',
//picker: new Date().toISOString().substr(0, 10),
}
},
})
I usually initialize the date picker with the current date minus the timezone offset like so:
<div id="app">
<v-app id="blabla">
<v-row justify="center">
<v-date-picker v-model="datePicker"></v-date-picker>
</v-row>
</v-app>
</div>
new Vue({
el: '#app',
vuetify: new Vuetify(),
data () {
return {
datePicker: (new Date(Date.now() - (new Date()).getTimezoneOffset() * 60000)).toISOString().substr(0, 10),
}
},
})

Without using v-model, how to set default value of v-combobox?

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>