fix(VDatePicker): select same date as start/end in date range picker
fixes 19989
Description
fixes #19989
Markup:
<template>
<v-app>
<v-container>
<v-date-picker v-model="dates" multiple="range" />
Selected dates: {{ dates }}
</v-container>
</v-app>
</template>
<script setup>
import { ref } from 'vue'
const dates = ref([new Date('2024-06-11'), new Date('2024-06-11')])
</script>
How do you clear a value then?
Thank you for your question!
In my understanding, if the user clicks on the wrong first date, they can click on any other date to complete the range selection, and then click again to select the right first date. This UX seems intuitive enough.
If we are talking about clearing the input completely - yes, it's not possible. But it's not possible for a single date picker either (:multiple="false"). And it makes sense - after all, we show the form to get the user's input and we are probably not interested in an empty value. (And if the developer is interested in this functionality, they can implement a custom 'clear' icon to clear the state)
Thank you for your question!
In my understanding, if the user clicks on the wrong first date, they can click on any other date to complete the range selection, and then click again to select the right first date. This UX seems intuitive enough.
If we are talking about clearing the input completely - yes, it's not possible. But it's not possible for a single date picker either (
:multiple="false"). And it makes sense - after all, we show the form to get the user's input and we are probably not interested in an empty value. (And if the developer is interested in this functionality, they can implement a custom 'clear' icon to clear the state)
Fair arguments. @vuetifyjs/core-team thoughts?
and we are probably not interested in an empty value. (And if the developer is interested in this functionality, they can implement a custom 'clear' icon to clear the state)
We still run into the case that people more than likely already have applications that depend on or expect this behavior, so we can't simply remove it, especially in a patch.
We still run into the case that people more than likely already have applications that depend on or expect this behavior, so we can't simply remove it, especially in a patch.
Counterpoint is that people upgrading from Vuetify2 expect the original
For the context, other libraries also have the proposed behavior in their date-range pickers: https://primevue.org/datepicker/#range https://vue3datepicker.com/props/modes/#range https://quasar.dev/vue-components/date#range-selection (although in Quasar, the output format is different for the same-date range compared to the different-date range. But that's another story. The main point is that it allows you to select the same date).
The range with the same start/end dates is a valid date range and not a bizarre edge case. And so it must be covered by the date selector out of the box.
We can think of the date range as a time period that starts at 12:00 AM, startDate and finishes at 11:59 PM, endDate.
The current behaviour allows you to select a minimal period of 48h only.
But what about a 24h period? You can imagine a use case for booking something, e.g. a venue for an event. How can you choose to book it for one day only?
If clearing the state is critical, it could also be done when the user clicks on the existing range selection (the same approach as in Quasar). Or a dedicated “x” icon can be added for clearing. I suggest this be done in a separate PR though.
We still run into the case that people more than likely already have applications that depend on or expect this behavior, so we can't simply remove it, especially in a patch.
I have added an allowOneDayRange prop for backward compatibility :tada:
The new behaviour is enabled only if the prop is set to true.
Problem
Unfortunately, there is another problem. modelValue becomes [startDate] after the first click already, and doesn't change after the second click. This is to comply with the existing contract for modelValue, which is a list of dates in the selected range, so for the same-day date range, modelValue should be a one-item array.
But in the parent component, we might want to do something when the user completes the range selection. When we receive [startDate] value, we cannot know if that is the whole range (the same day as start/end) or an incomplete range.
Proposal
Ideally, we could change when we emit update:modelValue.
We could avoid emitting it when only the startDate is selected (after all, the range selection is not yet complete then).
And emit it only when both startDate and endDate get selected.
Would this be acceptable?
Alternative proposal
Alternatively, we could emit an additional event on the second click, to indicate range selection completion.
- name it
update:range? - the payload could be:
- empty (we can read the
modelValueinstead), - the same as for
update:modelValue:[startDate, ..., endDate], - or
[startDate, endDate]- another convenient format for date ranges, although it kind of increases the api surface area.
- empty (we can read the
I like the alternate proposal.