I'm using vuetify's v-datetime-picker library to save the start and end date of an event. My code is the following:
<template>
<v-datetime-picker label="DateTime Start" okText="Accept" clearText="Clear"
:datePickerProps="{
'min':actualDate,
'max':'2022-12-31 24:59:59',
}"
v-model="meeting.meeting_date_start">
</v-datetime-picker>
<v-datetime-picker okText="Accept" clearText="Clear" label="DateTime End"
:datePickerProps="{
'min':dateInit,
'max':'2022-12-31 24:59:59',
}"
v-model="meeting.meeting_date_end">
</v-datetime-picker>
</template>
<script>
export default {
data: function () {
return {
actualDate:'',
}
},
computed: {
dateInit:function(){
return this.meeting.meeting_date_start.toLocaleString('sv',{timeZoneName:'short'}).substring(0,19).replace(' GMT','')
},
mounted(){
this.getCurrentDate();
},
methods:{
getCurrentDate(){
this.actualDate=new Date().toLocaleString('sv',{timeZoneName:'short'}).substring(0,19).replace(' GMT','')
console.log(this.actualDate)
},
},
}
</script>
Put the same date but 2 hours before and I did not get an error even though it is not correct. I tried creating a computed property to set the minimum date equal to the start date but it doesn't work.
CodePudding user response:
Check this codesanbox I made: https://codesandbox.io/s/stack-72497203-datetimepicker-range-example-ri2o7d?file=/src/components/DateTimeExample.vue
You need to understand how vuetify-datetime-picker
works, this is a custom component that combines three main vuetify's components in one: a v-text-field
, a v-date-picker
and a v-time-picker
. You'll need to modify the library to fully achieve what you want.
If you check the documentation of the library you will find that you can customize the props of each vuetify component through the props: textFieldProps, datePickerProps and timePickerProps, respectively.
So what I did first here is create a props object for each component in my data block, these objects contains the props I want to share across all my datetime pickers:
data: () => ({
today: new Date().toISOString(),
dateEnds: null,
dateStart: null,
textFieldProps: {
prependIcon: 'mdi-calendar',
color: 'purple darken-3'
},
datePickerProps: {
scrollable: true,
color: 'purple darken-3'
},
timePickerProps: {
scrollable: true,
ampmInTitle: true,
format: 'ampm',
color: 'purple darken-3'
}
}),
The v-datetime-picker
library returns a javascript date object. The v-date-picker
and v-time-picker
have the props min
and max
that you can use to restrict the input. But these props expects to receive a string, not a date object.
To pass the correct strings formats to each min
and max
props I created a couple computed properties that use the date-fns
library to give the format I need for each prop. The date-fns
is a library that already comes in the node_modules so you can import it and use it out of the box. This is same library that the datetime picker component use internally to give format to the text in the v-text-field
.
computed: {
dateStartFormat() {
if (this.dateStart) {
return format(this.dateStart, 'yyyy-MM-dd')
} else {
return null
}
},
dateEndsFormat() {
if (this.dateEnds) {
return format(this.dateEnds, 'yyyy-MM-dd')
} else {
return null
}
},
timeStartFormat() {
if (this.dateStart) {
return format(this.dateStart, 'HH:mm')
} else {
return null
}
},
timeEndsFormat() {
if (this.dateEnds) {
return format(this.dateEnds, 'HH:mm')
} else {
return null
}
},
}
Now that we have the correct strings formats for min
and max
props, you can pass them to your datetime pickers accordingly. In this case I set the props directly in each component and concatenated the global props with the help of the spread
operator.
<v-col cols="6">
<v-datetime-picker
v-model="dateStart"
label="Start"
:text-field-props="textFieldProps"
:date-picker-props="{
min: today,
max: dateEndsFormat,
...datePickerProps
}"
:time-picker-props="{
max: timeEndsFormat,
...timePickerProps
}"
ok-text="Save"
clear-text="Clear"
time-format="HH:mm"
>
<template slot="dateIcon">
<v-icon color="purple darken-4">mdi-calendar-month</v-icon>
</template>
<template slot="timeIcon">
<v-icon color="purple darken-4">mdi-clock-outline</v-icon>
</template>
</v-datetime-picker>
</v-col>
<v-col cols="6">
<v-datetime-picker
v-model="dateEnds"
label="Ends"
:disabled="!dateStart"
:text-field-props="textFieldProps"
:date-picker-props="{
min: dateStartFormat,
...datePickerProps
}"
:time-picker-props="{
min: timeStartFormat,
...timePickerProps
}"
ok-text="Save"
clear-text="Clear"
time-format="HH:mm"
>
<template slot="dateIcon">
<v-icon color="purple darken-4">mdi-calendar-month</v-icon>
</template>
<template slot="timeIcon">
<v-icon color="purple darken-4">mdi-clock-outline</v-icon>
</template>
</v-datetime-picker>
</v-col>
You're almost there!, if you test the example in the codesanbox you will find that it works but it has a couple bugs, from here you'll need to create your own custom datepicker component to fully achieve what you need since the original library might lack of customization options or events.
This library offers a good starting point for making your own component, that's why you can see it has a lot of forks in github, from my own experience I stumble with it the past and also ended making my own version of it since I wanted to customize it a little bit more and extend the functionality of it.
If you don't want to mess with making an npm package, you can just simply copy the component code from the github repo right here. And modify it to your needs.
What's next? TODO
- If you tested the codesandbox, the
min
prop of thev-time-picker
works kinda right, but if you choose a different date than thedateStartFormat
themin
property doesn't gets cleared. I would emit an even when the inner date of thev-date-picker
gets setted to remove themin
prop from the clock if the user specifies a different date than thedateStartFormat
. - The value of the v-model of the
v-datetime-picker
doesn't get setted if you don't click the "Save" button, but you can still click outside the dialog to close it, I would either set the dialog aspersistent
or execute the code of the save button when dialog close to fix this. This is an issue that already comes with the original library. - You could add a few more props to customize the colors of tabs, buttons, etc.
I hope this helps you get a better understanding about how the component works and achieve what you want.