src/components/form-datepicker/README.md
<b-form-datepicker>is a BootstrapVue custom date picker input form control, which provides full WAI-ARIA compliance and internationalization support.
As a form control wrapper component for the <b-calendar> component,
it provides additional validation state presentation and a compact interface. Native HTML5 date
inputs vary in presentation, accessibility, and in some instances are not supported by all browsers.
<b-form-datepicker> provides a consistent and accessible interface across all browser platforms
and devices.
<template>
<div>
<label for="example-datepicker">Choose a date</label>
<b-form-datepicker id="example-datepicker" v-model="value" class="mb-2"></b-form-datepicker>
<p>Value: '{{ value }}'</p>
</div>
</template>
<script>
export default {
data() {
return {
value: ''
}
}
}
</script>
<!-- b-form-datepicker.vue -->
<b-form-datepicker> supports many of the props available on
<b-calendar> as well as some of the props available on
<b-dropdown>.
v-model return valueBy default, <b-form-datepicker> returns dates as a string in the YYYY-MM-DD format, which is the
same format returned by native browser <input type="date"> controls. You can have
<b-form-datepicker> return a Date object (with no time portion) as the v-model value instead
by setting the value-as-date prop.
If no date is selected, <b-form-datepicker> returns an empty string '', or returns null if the
value-as-date prop is set.
Note that when value-as-date prop is set, the returned Date object will be in the browser's
default timezone.
If <b-form-datepicker> has a value set for the name prop, a hidden input will be created which
will have its name attribute set to the value of the name prop, and the value attribute will be
set to the selected date as a YYYY-MM-DD string. This will allow the <b-form-datepicker>
selected value to be submitted via native browser form submission.
Setting the disabled prop will remove all interactivity of the <b-form-datepicker> component.
Setting the readonly prop will disable selecting a date, but will keep the component interactive,
allowing for date navigation. The v-model will not be updated in the readonly state.
For disabling specific dates or setting minimum and maximum date limits, refer to the Date constraints section.
<template>
<div>
<b-form-group
label="Select date picker interactive state"
v-slot="{ ariaDescribedby }"
>
<b-form-radio-group
v-model="state"
:aria-describedby="ariaDescribedby"
aria-controls="ex-disabled-readonly"
>
<b-form-radio value="disabled">Disabled</b-form-radio>
<b-form-radio value="readonly">Readonly</b-form-radio>
<b-form-radio value="normal">Normal</b-form-radio>
</b-form-radio-group>
</b-form-group>
<b-form-datepicker
id="ex-disabled-readonly"
:disabled="disabled"
:readonly="readonly"
></b-form-datepicker>
</div>
</template>
<script>
export default {
data() {
return {
state: 'disabled'
}
},
computed: {
disabled() {
return this.state === 'disabled'
},
readonly() {
return this.state === 'readonly'
}
}
}
</script>
<!-- b-form-datepicker-disabled-readonly.vue -->
Restrict the calendar range via the min and max props. The props accept a date string in the
format of YYYY-MM-DD or a Date object.
<template>
<div>
<b-form-datepicker v-model="value" :min="min" :max="max" locale="en"></b-form-datepicker>
</div>
</template>
<script>
export default {
data() {
const now = new Date()
const today = new Date(now.getFullYear(), now.getMonth(), now.getDate())
// 15th two months prior
const minDate = new Date(today)
minDate.setMonth(minDate.getMonth() - 2)
minDate.setDate(15)
// 15th in two months
const maxDate = new Date(today)
maxDate.setMonth(maxDate.getMonth() + 2)
maxDate.setDate(15)
return {
value: '',
min: minDate,
max: maxDate
}
}
}
</script>
<!-- b-form-datepicker-min-max.vue -->
If you need to disable specific dates within the date picker, specify a function reference to the
date-disabled-fn prop. The function is passed two arguments:
ymd The date as a YYYY-MM-DD stringdate The date as a Date objectThe function should either return true if the date cannot be selected (disabled), or false if
the date can be selected (enabled). Note that the function cannot be asynchronous, and should
return a value as quickly as possible.
<template>
<div>
<b-form-datepicker v-model="value" :date-disabled-fn="dateDisabled" locale="en"></b-form-datepicker>
</div>
</template>
<script>
export default {
data() {
return {
value: ''
}
},
methods: {
dateDisabled(ymd, date) {
// Disable weekends (Sunday = `0`, Saturday = `6`) and
// disable days that fall on the 13th of the month
const weekday = date.getDay()
const day = date.getDate()
// Return `true` if the date should be disabled
return weekday === 0 || weekday === 6 || day === 13
}
}
}
</script>
<!-- b-form-datepicker-disabled-dates.vue -->
Note the min and max date constraints are evaluated first, before date-disabled-fn.
<b-form-datepicker> supports invalid and valid styling via the boolean state prop. Setting
state to boolean false will style the input as invalid, while setting it to boolean true will
style it as valid. Setting state to null will not show any validation state styling (the
default).
<template>
<div>
<label for="datepicker-invalid">Choose a date (invalid style)</label>
<b-form-datepicker id="datepicker-invalid" :state="false" class="mb-2"></b-form-datepicker>
<label for="datepicker-valid">Choose a date (valid style)</label>
<b-form-datepicker id="datepicker-valid" :state="true"></b-form-datepicker>
</div>
</template>
<!-- b-form-datepicker-invalid-valid.vue -->
Note that native browser validation is not available with <b-form-datepicker>.
The selected date button (background color) defaults to the 'primary' theme variant. You can
change this to any of the Bootstrap v4 theme variant colors: 'secondary', 'success', 'danger',
'warning', 'info', etc, via the selected-variant prop.
Today's date will also be highlighted (text color) using the same variant as the selected date by
default. To specify a different theme color to use for today's date, use the today-variant prop.
To disable highlighting of today's date altogether, set the no-highlight-today prop.
The navigation buttons default to the 'secondary' theme variant. You can change this via the
nav-button-variant prop.
Fancy a smaller or larger <b-form-datepicker> control? Set the size prop to 'sm' for a smaller
form control, or 'lg' for a larger form form control. Note this does not affect the size of the
popup calendar dialog.
<template>
<div>
<label for="datepicker-sm">Small date picker</label>
<b-form-datepicker id="datepicker-sm" size="sm" locale="en" class="mb-2"></b-form-datepicker>
<label for="datepicker-lg">Large date picker</label>
<b-form-datepicker id="datepicker-lg" size="lg" locale="en"></b-form-datepicker>
</div>
</template>
<!-- b-form-datepicker-sizes.vue -->
Add custom placeholder text to the control, when no date is selected, via the placeholder prop. If
a placeholder is not provided, the value of the label-no-date-selected prop is used.
<template>
<div>
<label for="datepicker-placeholder">Date picker with placeholder</label>
<b-form-datepicker id="datepicker-placeholder" placeholder="Choose a date" locale="en"></b-form-datepicker>
</div>
</template>
<!-- b-form-datepicker-placeholder.vue -->
Add optional control buttons to the bottom of the calendar popup via the props today-button,
reset-button and close-button.
reset-value (if provided)By default, clicking on the today or reset button will also close the calendar popup, unless the
prop no-close-on-select is set.
<template>
<div>
<label for="datepicker-buttons">Date picker with optional footer buttons</label>
<b-form-datepicker
id="datepicker-buttons"
today-button
reset-button
close-button
locale="en"
></b-form-datepicker>
</div>
</template>
<!-- b-form-datepicker-buttons.vue -->
The text for the optional buttons can be set via the label-today-button, label-reset-button, and
the label-close-button props. Due to the limited width of the footer section, it is recommended to
keep these labels short.
Note that the Set Today button may not set the control today's date, if today's date is outside of
the min or max date range restrictions. In the case it is outside of the range, it will set to
either min or max (depending on which is closes to today's date).
Use the dropdown props right, dropup, dropright, dropleft, no-flip, and offset to
control the positioning of the popup calendar.
Refer to the <b-dropdown> positioning section for details
on the effects and usage of these props.
<span class="badge badge-info small">v2.7.0+</span>
By default, when no date is selected, the calendar view will be set to the current month (or the
min or max date if today's date is out of range of min or max) when opened. You can change
this behaviour by specifying a date via the initial-date prop. The initial date prop will be used
to determine the calendar month to be initially presented to the user. It does not set the
component's value.
Want a fancy popup with a dark background instead of a light background? Set the dark prop to
true to enable the dark background.
Set the prop show-decade-nav to enable the previous and next decade buttons in the datepicker's
date navigation toolbar.
The props label-prev-decade and label-next-decade props can be used to provide custom label text
for the decade buttons.
For example usage, refer to the Internationalization section below.
<span class="badge badge-info small">v2.7.0+</span>
Fancy just a button that launches the date picker dialog, or want to provide your own optional text
input field? Use the button-only prop to render the datepicker as a dropdown button. The formatted
date label will be rendered with the class sr-only (available only to screen readers).
In the following simple example, we are placing the datepicker (button only mode) as an append to a
<b-input-group>, and we are using the context event to get the formatted date string and value:
<template>
<div>
<label for="example-input">Choose a date</label>
<b-input-group class="mb-3">
<b-form-input
id="example-input"
v-model="value"
type="text"
placeholder="YYYY-MM-DD"
autocomplete="off"
></b-form-input>
<b-input-group-append>
<b-form-datepicker
v-model="value"
button-only
right
locale="en-US"
aria-controls="example-input"
@context="onContext"
></b-form-datepicker>
</b-input-group-append>
</b-input-group>
<p class="mb-1">Value: '{{ value }}'</p>
<p class="mb-1">Selected: '{{ selected }}'</p>
<p>Formatted: '{{ formatted }}'</p>
</div>
</template>
<script>
export default {
data() {
return {
value: '',
formatted: '',
selected: ''
}
},
methods: {
onContext(ctx) {
// The date formatted in the locale, or the `label-no-date-selected` string
this.formatted = ctx.selectedFormatted
// The following will be an empty string until a valid date is entered
this.selected = ctx.selectedYMD
}
}
}
</script>
<!-- b-form-datepicker-button-only.vue -->
Control the size of the button via the size prop, and the button variant via the button-variant
prop.
<span class="badge badge-info small">v2.6.0+</span>
To change format options of the displayed date text inside the component, e.g. in the header or
placeholder, set the date-format-options prop to an object containing the requested format
properties for the Intl.DateTimeFormat object (see also
Internationalization).
<template>
<div>
<label for="datepicker-dateformat1">Custom date format</label>
<b-form-datepicker
id="datepicker-dateformat1"
:date-format-options="{ year: 'numeric', month: 'short', day: '2-digit', weekday: 'short' }"
locale="en"
></b-form-datepicker>
<label class="mt-3" for="datepicker-dateformat2">Short date format</label>
<b-form-datepicker
id="datepicker-dateformat2"
:date-format-options="{ year: 'numeric', month: 'numeric', day: 'numeric' }"
locale="en"
></b-form-datepicker>
</div>
</template>
<!-- b-form-datepicker-dateformat.vue -->
The following table summarizes the valid options for each format property:
| Property | Possible values |
|---|---|
year | 'numeric', or '2-digit' |
month | 'numeric', '2-digit', 'long', 'short', or 'narrow' |
day | 'numeric', or '2-digit' |
weekday | 'long', 'short', or 'narrow' |
Notes:
weekday'narrow' format and will fall back to 'short' or long' (if 'short' is not available)year, month and day will always be shown. If you need to leave out a value, set the property
to undefined, although this is highly discouraged for accessibility reasons<span class="badge badge-info small">2.12.0+</span>
The calendar weekday name header format defaults to 'short', which is typically a three-character
abbreviation of the weekday, although some locales may override this. The
format can be controlled via the prop weekday-header-format and accepts one of three values:
'long' the full weekday name (e.g. <samp>Tuesday</samp>). Handy when using a full width
calendar. Avoid using with the default calendar width.'short' typically is a 2 or 3 letter abbreviation of the weekday name, depending on the selected
locale (e.g. "Tue").'narrow' is typically a single character abbreviation (e.g., <samp>T</samp>). Two weekdays may
have the same narrow style for some locales (e.g. Tuesday and Thursday's narrow style are both
<samp>T</samp>). This can be handy for those locales that do not support the 'short' format,
such as locales 'ar' and 'fa'.<span class="badge badge-info small">2.12.0+</span>
To change the content of the calendar's date navigation buttons, BootstrapVue provides scoped slots for each button:
'nav-prev-decade''nav-prev-year''nav-prev-month''nav-this-month' (the go to selected/today button)'nav-next-month''nav-next-year''nav-next-decade'All seven slots have the same scoped property available:
| Property | Type | Description |
|---|---|---|
isRTL | Boolean | Will be true when the date navigation bar is rendered right-to-left |
You can use the isRTL scoped property to "flip" the prev vs next button content to handle the
left-to-right to right-to-left orientation change — i.e. the previous year button will be on
the right when isRTL is true, instead of the left.
To create a full width calendar dropdown (where the width matches the input width), simply set the
menu-class prop to 'w-100' and set the calendar-width prop to '100%':
<template>
<div>
<label for="datepicker-full-width">Choose a date</label>
<b-form-datepicker
id="datepicker-full-width"
v-model="value"
menu-class="w-100"
calendar-width="100%"
class="mb-2"
></b-form-datepicker>
<p>Value: '{{ value }}'</p>
</div>
</template>
<script>
export default {
data() {
return {
value: ''
}
}
}
</script>
<!-- b-form-datepicker-full-width.vue -->
Internationalization of the date picker's calendar is provided via
Intl.DateTimeFormat,
except for labels applied to elements of the calendar control (aria-labels, selected status, and
help text). You must provide your own translations for these labels. The available locales will be
browser dependent (not all browsers support all locales)
By default <b-form-datepicker> will use the browser's default locale, but you can specify the
locale (or locales) to use via the locale prop. The prop accepts either a single locale string, or
an array of locale strings (listed in order of preferred locale).
The calendar starts the week on Sunday. This can be changed by setting the start-weekday prop to a
number in the range of 0 to 6 where 0 represents Sunday, 1 for Monday, up to 6 for
Saturday.
<template>
<div>
<label for="example-locales">Locale:</label>
<b-form-select id="example-locales" v-model="locale" :options="locales" class="mb-2"></b-form-select>
<label for="example-weekdays">Start weekday:</label>
<b-form-select id="example-weekdays" v-model="weekday" :options="weekdays" class="mb-2"></b-form-select>
<div>
<b-form-checkbox v-model="showDecadeNav" switch inline class="my-2">
Show decade navigation buttons
</b-form-checkbox>
<b-form-checkbox v-model="hideHeader" switch inline class="my-2">
Hide calendar header
</b-form-checkbox>
</div>
<label for="example-i18n-picker">Date picker:</label>
<b-form-datepicker
id="example-i18n-picker"
v-model="value"
v-bind="labels[locale] || {}"
:locale="locale"
:start-weekday="weekday"
:show-decade-nav="showDecadeNav"
:hide-header="hideHeader"
class="mb-2"
></b-form-datepicker>
<p>Value: <b>'{{ value }}'</b></p>
</div>
</template>
<script>
export default {
data() {
return {
value: '',
locale: 'en-US',
showDecadeNav: false,
hideHeader: false,
locales: [
{ value: 'en-US', text: 'English US (en-US)' },
{ value: 'de', text: 'German (de)' },
{ value: 'ar-EG', text: 'Arabic Egyptian (ar-EG)' },
{ value: 'zh', text: 'Chinese (zh)' }
],
weekday: 0,
weekdays: [
{ value: 0, text: 'Sunday' },
{ value: 1, text: 'Monday' },
{ value: 6, text: 'Saturday' }
],
labels: {
de: {
labelPrevDecade: 'Vorheriges Jahrzehnt',
labelPrevYear: 'Vorheriges Jahr',
labelPrevMonth: 'Vorheriger Monat',
labelCurrentMonth: 'Aktueller Monat',
labelNextMonth: 'Nächster Monat',
labelNextYear: 'Nächstes Jahr',
labelNextDecade: 'Nächstes Jahrzehnt',
labelToday: 'Heute',
labelSelected: 'Ausgewähltes Datum',
labelNoDateSelected: 'Kein Datum gewählt',
labelCalendar: 'Kalender',
labelNav: 'Kalendernavigation',
labelHelp: 'Mit den Pfeiltasten durch den Kalender navigieren'
},
'ar-EG': {
weekdayHeaderFormat: 'narrow',
labelPrevDecade: 'العقد السابق',
labelPrevYear: 'العام السابق',
labelPrevMonth: 'الشهر السابق',
labelCurrentMonth: 'الشهر الحالي',
labelNextMonth: 'الشهر المقبل',
labelNextYear: 'العام المقبل',
labelNextDecade: 'العقد القادم',
labelToday: 'اليوم',
labelSelected: 'التاريخ المحدد',
labelNoDateSelected: 'لم يتم اختيار تاريخ',
labelCalendar: 'التقويم',
labelNav: 'الملاحة التقويم',
labelHelp: 'استخدم مفاتيح المؤشر للتنقل في التواريخ'
},
zh: {
weekdayHeaderFormat: 'narrow',
labelPrevDecade: '过去十年',
labelPrevYear: '上一年',
labelPrevMonth: '上个月',
labelCurrentMonth: '当前月份',
labelNextMonth: '下个月',
labelNextYear: '明年',
labelNextDecade: '下一个十年',
labelToday: '今天',
labelSelected: '选定日期',
labelNoDateSelected: '未选择日期',
labelCalendar: '日历',
labelNav: '日历导航',
labelHelp: '使用光标键浏览日期'
}
}
}
}
}
</script>
<!-- b-form-datepicker-i18n.vue -->
You can listen to for the context event to determine the locale and directionality that the
calendar has resolved to.
Refer to the <b-calendar> documentation for
additional details.
The popup calendar supports the same
keyboard controls as <b-calendar>, along with the
following:
When internationalizing the datepicker, it is important to also update the label-* props with
appropriate translated strings, so that international screen reader users will hear the correct
prompts and descriptions.
Refer to the <b-calendar> documentation for additional
details.
<b-form-datepicker> is based upon the components <b-calendar> and
<b-dropdown>.
<b-form-datepicker> uses Bootstrap's border and flex utility classes, along with button (btn-*)
classes, dropdown (dropdown*) classes, and the form-control* (plus validation) classes.
BootstrapVue's Custom SCSS/CSS is also required for proper styling of the date picker and calendar.