Skip to content

Commit

Permalink
fix(VDatePicker): add missing allowed-dates support
Browse files Browse the repository at this point in the history
fixes #17983
  • Loading branch information
johnleider committed Oct 9, 2023
1 parent 408aba9 commit 46d68d4
Show file tree
Hide file tree
Showing 6 changed files with 77 additions and 22 deletions.
34 changes: 24 additions & 10 deletions packages/docs/src/examples/v-date-picker/prop-allowed-dates.vue
Original file line number Diff line number Diff line change
@@ -1,29 +1,43 @@
<template>
<v-row justify="center">
<v-date-picker
v-model="date"
:allowed-dates="allowedDates"
class="mt-4"
min="2016-06-15"
max="2018-03-20"
></v-date-picker>
</v-row>
<v-container>
<v-row justify="space-around">
<v-date-picker
v-model="date"
:allowed-dates="allowedDates"
min="2016-06-15"
max="2018-03-20"
></v-date-picker>
</v-row>
</v-container>
</template>

<script setup>
import { useDate } from 'vuetify/labs/date'
import { ref } from 'vue'
const adapter = useDate()
const date = ref('2018-03-02')
function allowedDates (val) {
return parseInt(adapter.toISO(val).split('-')[2], 10) % 2 === 0
}
</script>

<script>
import { useDate } from 'vuetify/labs/date'
const adapter = useDate()
export default {
data: () => ({
date: '2018-03-02',
}),
methods: {
allowedDates: val => parseInt(val.split('-')[2], 10) % 2 === 0,
allowedDates: val => {
return parseInt(adapter.toISO(val).split('-')[2], 10) % 2 === 0
},
},
}
</script>
12 changes: 6 additions & 6 deletions packages/docs/src/pages/en/components/date-pickers.md
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,12 @@ Date picker colors can be set using the **color** and **header-color** props. If

<example file="v-date-picker/prop-colors" />

#### Allowed dates

Specify allowed dates using objects or functions. When using objects, accepts a date string in the format of YYYY-MM-DD. When using functions, accepts a date object as a parameter and should return a boolean.

<example file="v-date-picker/prop-allowed-dates" />

<!--
## Caveats
Expand All @@ -154,12 +160,6 @@ Date picker colors can be set using the **color** and **header-color** props. If
### Props
#### Allowed dates
You can specify allowed dates using arrays, objects, and functions.
<example file="v-date-picker/prop-allowed-dates" />
#### Colors
Date picker colors can be set using the **color** and **header-color** props. If **header-color** prop is not provided header will use the **color** prop value.
Expand Down
2 changes: 2 additions & 0 deletions packages/docs/src/pages/en/features/dates.md
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,8 @@ import type { DateAdapter } from 'vuetify/labs'
export interface DateAdapter<Date> {
date (value?: any): Date | null
format (date: Date, formatString: string): string
parseISO (value: string): Date | null
toISO (date: Date): string

startOfDay (date: Date): Date
endOfDay (date: Date): Date
Expand Down
24 changes: 19 additions & 5 deletions packages/vuetify/src/labs/VDatePicker/VDatePickerMonth.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import { dateEmits, makeDateProps } from '../VDateInput/composables'
import { useDate } from '@/labs/date'

export const makeVDatePickerMonthProps = propsFactory({
allowedDates: [Array, Function],
color: String,
showAdjacentMonths: Boolean,
hideWeekdays: Boolean,
Expand Down Expand Up @@ -109,10 +110,6 @@ export const VDatePickerMonth = genericComponent()({
const endDate = validDates[1]

return days.map((date, index) => {
const isDisabled = !!(
(props.min && adapter.isAfter(props.min, date)) ||
(props.max && adapter.isAfter(date, props.max))
)
const isStart = startDate && adapter.isSameDay(date, startDate)
const isEnd = endDate && adapter.isSameDay(date, endDate)
const isAdjacent = !adapter.isSameMonth(date, month.value)
Expand All @@ -124,7 +121,7 @@ export const VDatePickerMonth = genericComponent()({
formatted: adapter.format(date, 'keyboardDate'),
year: adapter.getYear(date),
month: adapter.getMonth(date),
isDisabled,
isDisabled: isDisabled(date),
isWeekStart: index % 7 === 0,
isWeekEnd: index % 7 === 6,
isSelected: isStart || isEnd,
Expand Down Expand Up @@ -153,6 +150,23 @@ export const VDatePickerMonth = genericComponent()({

const { backgroundColorClasses, backgroundColorStyles } = useBackgroundColor(props, 'color')

function isDisabled (value: any) {
const date = adapter.date(value)

if (props.min && adapter.isAfter(props.min, date)) return true
if (props.max && adapter.isAfter(date, props.max)) return true

if (Array.isArray(props.allowedDates)) {
return !props.allowedDates.some(d => adapter.isSameDay(adapter.date(d), date))
}

if (typeof props.allowedDates === 'function') {
return !props.allowedDates(date)
}

return false
}

function selectDate (date: any) {
let newModel = props.modelValue.slice()

Expand Down
2 changes: 2 additions & 0 deletions packages/vuetify/src/labs/date/DateAdapter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ export interface DateAdapter<T> {
date (value?: any): T | null
format (date: T, formatString: string): string
toJsDate (value: T): Date
parseISO (date: string): T
toISO (date: T): string

startOfDay (date: T): T
endOfDay (date: T): T
Expand Down
25 changes: 24 additions & 1 deletion packages/vuetify/src/labs/date/adapters/vuetify.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// Utilities
import { createRange } from '@/util'
import { createRange, padStart } from '@/util'

// Types
import type { DateAdapter } from '../DateAdapter'
Expand Down Expand Up @@ -278,6 +278,21 @@ function format (value: Date, formatString: string, locale: string): string {
return new Intl.DateTimeFormat(locale, options).format(date)
}

function toISO (adapter: DateAdapter<any>, value: any) {
const date = adapter.toJsDate(value)
const year = date.getFullYear()
const month = padStart(String(date.getMonth() + 1), 2, '0')
const day = padStart(String(date.getDate()), 2, '0')

return `${year}-${month}-${day}`
}

function parseISO (value: string) {
const [year, month, day] = value.split('-').map(Number)

return new Date(year, month - 1, day)
}

function addDays (date: Date, amount: number) {
const d = new Date(date)
d.setDate(d.getDate() + amount)
Expand Down Expand Up @@ -380,6 +395,14 @@ export class VuetifyDateAdapter implements DateAdapter<Date> {
return date
}

toISO (date: Date): string {
return toISO(this, date)
}

parseISO (date: string) {
return parseISO(date)
}

addDays (date: Date, amount: number) {
return addDays(date, amount)
}
Expand Down

0 comments on commit 46d68d4

Please sign in to comment.