Vuepic / vue-datepicker

Datepicker component for Vue 3
https://vue3datepicker.com
MIT License
1.48k stars 147 forks source link

Custom month picker with disable-year-select and @update-month-year #760

Closed tmihalcin closed 8 months ago

tmihalcin commented 8 months ago

Is your feature request related to a problem? Please describe. Hi! The requirements for our datepicker are to show the calendar with month & year in the header with arrows which would show previous/next month as follows image when user clicks on the month/year, we should display month picker with year in the header and arrows which increment/decrement years image there is no year picker

I have used #month slot to render month & year with disable-year-select to not render the year-picker button, but as a side effect, the @update-month-year does not change year when incrementing month from December to January.

Describe the solution you'd like disable-year-select could get other configuration options in addition to existing boolean values to make this rolling over to next/previous year work.

Describe alternatives you've considered The only solution right now is to remove disable-year-select and hide the year-picker button with CSS I have also tried to use #month-year slot, but was unable to open the month-picker overlay through the API. Not sure if it was bug or some issue on my side.

Jasenkoo commented 8 months ago

You need to call updateMonthYear function from slot props to update the value inside the picker

tmihalcin commented 8 months ago

@Jasenkoo I have already tried using #month-year slot like this

<template
          #month-year="{
              month,
              year,
              months,
              handleMonthYearChange
      }">
        <div class="flex justify-between items-center w-full">
          <LeftArrowIcon color="primary" class="cursor-pointer" @click="handleMonthYearChange(false)"/>
          <span class="text-m text-black cursor-pointer" @click="openMonthView">{{ months[month].text }} {{ year }}</span>
          <LeftArrowIcon color="primary" class="cursor-pointer rotate-180" @click="handleMonthYearChange(true)"/>
        </div>
      </template>

openMonthView calls calendarRef.value.switchView('month'), but this doesn't open the overlay. Maybe it interferes with some other configuration.

Here is the full configuration including all overridden slots:

<VueDatePicker ref="calendarRef"
                   :model-value="modelValue" @update:model-value="$emit('update:model-value', $event)"
                   placeholder="Select date" text-input
                   hide-offset-dates no-today auto-apply
                   :week-start="0" :day-names="['M', 'T', 'W', 'T', 'F', 'S', 'S']"
                   :enable-time-picker="false" hide-input-icon
                   :offset="8" position="left"  month-name-format="long"
                   :hide-navigation="['month']" six-weeks="append" @update-month-year="updateMonthYear">

      <template #arrow-left>
        <LeftArrowIcon color="primary" class="cursor-pointer" />
      </template>

      <template #arrow-right>
        <LeftArrowIcon color="primary" class="cursor-pointer rotate-180" />
      </template>

      <template
          #month-year="{
              month,
              year,
              months,
              handleMonthYearChange
      }">
        <div class="flex justify-between items-center w-full">
          <LeftArrowIcon color="primary" class="cursor-pointer" @click="handleMonthYearChange(false)"/>
          <span class="text-m text-black cursor-pointer" @click="openMonthView">{{ months[month].text }} {{ year }}</span>
          <LeftArrowIcon color="primary" class="cursor-pointer rotate-180" @click="handleMonthYearChange(true)"/>
        </div>
      </template>

      <template #calendar-header="{ day }">
        <div class="text-grey-7 text-xs font-normal">{{ day }}</div>
      </template>

      <template #day="{ day }">
        <span class="text-xs">{{ day }}</span>
      </template>

      <template #month-overlay-value="{ text, value }">
        <div class="rounded-full relative w-12 h-12" :class="isMonthSelected(value) ? 'bg-primary' : 'bg-white'">
          <div class="absolute left-2.5 top-2.5 text-m" :class="isMonthSelected(value) ? 'text-white' : 'text-black'">
            {{ text.substring(0, 3) }}
          </div>
        </div>
      </template>

      <template #month-overlay-header>
        <div class="flex justify-between items-center px-4 pt-4 pb-3">
          <LeftArrowIcon color="primary" class="cursor-pointer" @click="updateYear(year - 1)" />
          <span class="text-m">{{ year }}</span>
          <LeftArrowIcon color="primary" class="cursor-pointer rotate-180" @click="updateYear(year + 1)" />
        </div>
      </template>
    </VueDatePicker>