vue.jsvuejs3vuetify.jsvuetifyjs3

Vuetify date range that allows start and end to be the same day


I'm using Vuetify 3 (composition API) and have a date-picker triggered by a menu/text-field combination. It works fine, but I need to be able to select a start and end date that are the same day, and when I attempt to do that at runtime, nothing happens. Here is my code:

<script setup lang="ts">
import { ref, computed } from 'vue'

const dateRange = ref<Date[]>([])
const showDateRangeMenu = ref(false)

const dateRangeFilterText = computed(() => {
  if (dateRange.value.length < 2) {
    return ''
  }
  return `${formatDate(dateRange.value[0])} - ${formatDate(dateRange.value[dateRange.value.length - 1])}`
})

function formatDate(date: Date) {
  const year = date.getFullYear()
  const month = String(date.getMonth() + 1).padStart(2, '0')
  const day = String(date.getDate()).padStart(2, '0')
  return `${year}-${month}-${day}`
}

function onDatePickerClick() {
  if (dateRange.value.length > 1) {
    showDateRangeMenu.value = false
  }
}
</script>

Template:

<template>
  <div>
    <v-card tile min-height="110px">
      <v-card-text class="py-2">
        <label for="date-range-filter" class="pl-2">Date Range</label>
        <v-menu
          id="date-range-filter"
          v-model="showDateRangeMenu"
          :close-on-content-click="false"
          location="bottom"
          transition="scale-transition"
        >
          <template #activator="{ props }">
            <v-text-field
              v-model="dateRangeFilterText"
              v-bind="props"
              density="compact"
              outlined
              single-line
              hide-details
              readonly
              placeholder="Select Date Range...."
              prepend-inner-icon="mdi-calendar"
              class="mt-2"
            ></v-text-field>
          </template>
          <v-date-picker
            v-model="dateRange"
            multiple="range"
            hide-header
            @update:model-value="onDatePickerClick"
          ></v-date-picker>
        </v-menu>
      </v-card-text>
    </v-card>
  </div>
</template>

Playground available here.

What I want is for the user to be able to click the same date twice and have that be the start and end date in the range. E.g., user clicks December 25, 2024 twice, and my range is 2024-12-25 - 2024-12-25.

I think it has something to do with the fact that the model is an array, and it's attempting to enter the same value in the array twice, but I can't figure out how I would allow for this to happen.

Is it possible to have a range date-picker with Vuetify 3 and have the start and end dates be the same?


Solution

  • This is a known issue of Vuetify 3. Click the start date twice will cancel the selection. Previously reported in #19989 but closed by bot. I've opened a new one #20805

    Currently, you can use the following workaround:

      watch(dateRange, (value, oldValue) => {
        if (oldValue?.length === 1 && value?.length === 0)
          dateRange.value = [oldValue[0], oldValue[0]]
      })
    

    Playground