DatePicker
The DatePicker
component is used to select a date value. At mobile viewports, the browsers native input is used.
Import
- React
- Angular
- Vue.js
// with @dhl-official/react-library:
import { DhlDatePicker } from "@dhl-official/react-library"
// with @dhl-official/ui-libraries/react-library:
import { DhlDatePicker } from "@dhl-official/ui-libraries/react-library"
If the DUIL has been installed, you can use the web component directly:
<dhl-date-picker></dhl-date-picker>
// with @dhl-official/vue-library:
import { DhlDatePicker } from "@dhl-official/vue-library"
// with @dhl-official/ui-libraries/vue-library:
import { DhlDatePicker } from "@dhl-official/ui-libraries/vue-library"
Please ensure all date values are passed in the international ISO-8601 format: YYYY-MM-DD
.
Accessibility
The DatePicker
is built with consideration for accessibility standards and keyboard support.
Choose Date Button
Space, Enter
: Toggles DatePicker visibility and moves focus to month and year text.
DatePicker Dialog
Esc
: Close DatePicker dialog and move focus to "choose date" button.Tab
: Move focus to next focusable element.Shift + Tab
: Move focus to previous focusable element
The calendar used inside DatePicker
uses role="grid"
meaning only one 'day button' is in the tab sequence at any one time.
DatePicker Dialog: Calendar Grid
Space, Enter
: Selects a date, closes the dialog, and moves focus back to the “Choose Date” button.- Additionally updates the value of the Duet Date Picker input with the selected date, and adds selected date to “Choose Date” button label.
Arrow up
: Moves focus to the same day of the previous week.Arrow down
: Moves focus to the same day of the next week.Arrow right
: Moves focus to the next day.Arrow left
: Moves focus to the previous day.Home
: Moves focus to the first day (e.g Monday) of the current week.End
: Moves focus to the last day (e.g. Sunday) of the current week.Page Up
: Changes the grid of dates to the previous month and sets focus on the same day of the same week.Shift + Page Up
: Changes the grid of dates to the previous year and sets focus on the same day of the same week.Page Down
: Changes the grid of dates to the next month and sets focus on the same day of the same week.Shift + Page Down
: Changes the grid of dates to the next year and sets focus on the same day of the same week.
Please ensure the prop localeLabels
is supplied and matches the locale
language. This ensures screen-reader users can
leverage voice-over technology in the context of DatePicker
.
Using Events
The DatePicker
can be used with DOM events and listeners. Additionally, custom events are available (see Events table below)
which include a custom detail
object. This object contains fields designed to increase ease of use. The example below demonstrates
how the detail
object can be used to retrieve the value as a date through the valueAsDate
field.
// Select the DatePicker component
const date = document.querySelector("dhl-date-picker");
// Listen for when date is selected
date.addEventListener("dhlChange", function (e) {
console.log("selected date", e.detail.valueAsDate);
});
With an output:
Tue Feb 14 2023 00:00:00 GMT+0000 (Greenwich Mean Time)
Using Custom Formats
By default, the DatePicker
uses the yyyy-mm-dd
(DE
locale) format.
To use a different format, the prop dateAdapter
is available for use. The example below demonstrates how the prop dateAdapter
can be used with a en-GB
locale format DD-MM-YYYY
.
const picker = document.querySelector("dhl-date-picker");
const DATE_FORMAT = /^(\d{1,2})\.(\d{1,2})\.(\d{4})$/;
picker.dateAdapter = {
parse(value = "", createDate) {
const matches = value.match(DATE_FORMAT);
if (matches) {
return createDate(matches[3], matches[2], matches[1]);
}
},
format(date) {
const day = date.getDate().toString().padStart(2, "0"); // Get the day of the month as a two-digit string
const month = (date.getMonth() + 1).toString().padStart(2, "0"); // Get the month as a two-digit string
const year = date.getFullYear().toString(); // Get the year as a string
return `${day}/${month}/${year}`;
},
};
Known Issues
- Currently, the NVDA screen-reader on the Windows platform does not automatically switch from
browse mode
tofocus mode
within theDatePicker
calendar grid, as they do with native<input type="date" />
elements.
Code
- React
- Angular
- Vue.js
<DhlDatePicker></DhlDatePicker>
<dhl-date-picker></dhl-date-picker>
<dhl-date-picker></dhl-date-picker>
Interactive Demo
Migrating from DUIL 1.0
- Aria labels now passed through required
localeLabels
prop - please see documentation for all available aria fields found within this object. - Rename
firstDayOfTheWeek
tofirstDayOfWeek
- Remove
date
- Remove
externalValidation
- Rename
minDate
tomin
- Rename
maxDate
tomax
- Remove
isBlock
- Remove
variant
- Remove
displayFormat
see new propdateAdapter
for new implementation - Add
dataAriaLabelledby
- Add
inputLabel
- Add
isDisabled
- Add
role
- Add
direction
- Add
dateAdapter
- Add
isDateDisabled
- Add
dhlChange
- Add
dhlBlur
- Add new event
dhlChange
- Add new event
dhlFocus
- Add new event
dhlOpen
- Add new event
dhlClose
- Add public method
setFocus
- Add public method
show
- Add public method
hide
Readme
Usage
Dhl-date-picker
Snippets of code in HTML and JavaScript to show some of the use cases for the component.
The code is not meant to be executed, but to be used as a reference for the usage of the component.
Angular, React and Vue usages are not included in this documentation, but can be easily derived from the html and javascript code.
default usage
<form novalidate>
<dhl-grid-container columns="2">
<dhl-grid-cell span-columns="2">
<dhl-date-picker
name="date-picker-1"
input-label="Example text"
></dhl-date-picker>
</dhl-grid-cell>
<dhl-grid-cell>
<dhl-button
type="reset"
variant="text"
>RESET</dhl-button
>
<dhl-button
type="submit"
variant="primary"
>SUBMIT</dhl-button
>
</dhl-grid-cell>
</dhl-grid-container>
</form>
<script type="module">
const form = document.querySelector("form");
const datePicker = document.querySelector("dhl-date-picker");
form.addEventListener("submit", async (e) => {
e.preventDefault();
console.log("datePicker - isValid", await datePicker.checkValidity());
console.log(Object.fromEntries(new FormData(form)));
return await e.target.checkValidity();
});
</script>
usage with validation (required) and (browser) default validation message
<form novalidate>
<dhl-grid-container columns="2">
<dhl-grid-cell span-columns="2">
<dhl-date-picker
required
name="date-picker-1"
input-label="Example text"
></dhl-date-picker>
</dhl-grid-cell>
<dhl-grid-cell>
<dhl-button
type="reset"
variant="text"
>RESET</dhl-button
>
<dhl-button
type="submit"
variant="primary"
>SUBMIT</dhl-button
>
</dhl-grid-cell>
</dhl-grid-container>
</form>
<script type="module">
const form = document.querySelector("form");
const datePicker = document.querySelector("dhl-date-picker");
form.addEventListener("submit", async (e) => {
e.preventDefault();
console.log("datePicker - isValid", await datePicker.checkValidity());
console.log(Object.fromEntries(new FormData(form)));
return await e.target.checkValidity();
});
</script>
usage with validation (required) and custom validation message
<form novalidate>
<dhl-grid-container columns="2">
<dhl-grid-cell span-columns="2">
<dhl-date-picker
name="date-picker-1"
input-label="Example text"
required
>
</dhl-date-picker>
</dhl-grid-cell>
<dhl-grid-cell>
<dhl-button
type="reset"
variant="text"
>RESET</dhl-button
>
<dhl-button
type="submit"
variant="primary"
>SUBMIT</dhl-button
>
</dhl-grid-cell>
</dhl-grid-container>
</form>
<script type="module">
const form = document.querySelector("form");
const datePicker = document.querySelector("dhl-date-picker");
const validationMessageInvalid = "This field is required";
const validationMessageValid = "This field is valid";
form.addEventListener("submit", async (e) => {
e.preventDefault();
const isValid = await datePicker.checkValidity();
if (isValid) {
datePicker.validation = {
type: "valid",
message: validationMessageValid,
};
} else {
datePicker.validation = {
type: "invalid",
message: validationMessageInvalid,
};
}
return await form.checkValidity();
});
</script>
usage with custom events
<form novalidate>
<dhl-grid-container columns="2">
<dhl-grid-cell span-columns="2">
<dhl-date-picker
required
name="date-picker-1"
input-label="Example text"
>
</dhl-date-picker>
</dhl-grid-cell>
<dhl-grid-cell>
<dhl-button
type="reset"
variant="text"
>RESET</dhl-button
>
<dhl-button
type="submit"
variant="primary"
>SUBMIT</dhl-button
>
</dhl-grid-cell>
</dhl-grid-container>
</form>
<script type="module">
const form = document.querySelector("form");
const datePicker = document.querySelector("dhl-date-picker");
const validationMessageInvalid = "This field is required";
const validationMessageValid = "This field valid";
const text = document.querySelector("dhl-text");
const isElementValid = async () => {
const isValid = await datePicker.checkValidity();
if (isValid) {
datePicker.validation = {
type: "valid",
message: validationMessageValid,
};
} else {
datePicker.validation = {
type: "invalid",
message: validationMessageInvalid,
};
}
return isValid;
};
form.addEventListener("submit", async (e) => {
e.preventDefault();
await isElementValid();
});
datePicker.addEventListener("dhlChange", async (e) => await isElementValid());
datePicker.addEventListener("dhlBlur", async (e) => isElementValid());
</script>
usage with disabling specific dates
<form novalidate>
<dhl-grid-container columns="2">
<dhl-grid-cell span-columns="2">
<dhl-date-picker
name="date-picker-123"
input-label="Example text"
></dhl-date-picker>
</dhl-grid-cell>
</dhl-grid-container>
</form>
<script type="module">
const datePicker = document.querySelector("dhl-date-picker");
const disabledDates = [
1, 2, 10, 11, 12, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
];
datePicker.isDateDisabled = (date) => {
const day = date.getDate();
return disabledDates.includes(day);
};
</script>
Properties
Property | Attribute | Description | Type | Default |
---|---|---|---|---|
dataAriaLabelledby | data-aria-labelledby | An optional ariaLabelledby prop that establishes the relationships between objects and their label(s), and its value should be one or more element IDs, which refer to elements that have the text needed for labelling. List multiple element IDs in a space delimited fashion. | string | undefined |
dataId | data-id | An optional prop. Gives a valid HTML ID attribute value for the component. | string | dhl-date-picker-${getRandomString()} |
dataRole | data-role | An optional prop defining the role attribute of the component. | string | undefined |
dataTestid | data-testid | An optional prop. The test id attached to the component as a data-testid attribute. | string | undefined |
direction | direction | An optional prop which forces the opening direction of the calendar modal to be always left or right. This setting can be useful when the input is smaller than the opening date picker would be as by default the picker always opens towards right. | "left" \| "right" | DHL_DATE_PICKER.DIRECTION.RIGHT |
firstDayOfWeek | first-day-of-week | An optional prop used to set the first day of the week. Sunday is treated as index 0. The default is 1; Monday. | DaysOfWeek.Friday \| DaysOfWeek.Monday \| DaysOfWeek.Saturday \| DaysOfWeek.Sunday \| DaysOfWeek.Thursday \| DaysOfWeek.Tuesday \| DaysOfWeek.Wednesday | DaysOfWeek.Monday |
inputLabel | input-label | An optional prop used to set the label inside the DatePicker inputfield. This is also used as an aria label for the input. Please use the dataAriaLabelledby prop with an associated label should you choose to not supply this prop. | string | undefined |
isDateDisabled | -- | An optional prop used to set which days are disabled and therefore disallowed. For example, this can be used to disallow selection of weekends. | (date: Date) => boolean | () => false |
isDisabled | is-disabled | An optional flag to define if the component is disabled. | boolean | false |
locale | locale | An optional prop used to change the calendar locale - following the the BCP 47 standard Note that localeLabels is provided by default in English en-GB. If you want to use a different locale, you will need to provide your own localeLabels prop. | string | "default" |
localeLabels | -- | An optional prop used to set the DatePicker localization labels and aria labels. Defaults to English en-GB. | { buttonLabel: string; selectedDateMessage: string; selectedDateRangeMessage: string; prevMonthLabel: string; nextMonthLabel: string; prevYearLabel: string; nextYearLabel: string; monthSelectLabel: string; yearSelectLabel: string; closeLabel: string; invalidDateErrorMessage: string; invalidDateRangeErrorMessage: string; } | defaultLocaleLabels |
max | max | An optional prop used to set the maximum date allowed to be picked. Must be in IS0-8601 format: YYYY-MM-DD. This setting can be used alone or together with the min property. | Date \| string | undefined |
min | min | An optional prop used to set the minimum date allowed to be picked. Must be in IS0-8601 format: YYYY-MM-DD. This setting can be used alone or together with the max property. | Date \| string | undefined |
name | name | An optional value to be set to the element HTML name attribute. It takes any valid value that can be used for the name attribute of an HTMLInputElement. | string | ${getRandomString()}-date |
openOnFocus | open-on-focus | An optional prop when set to true, the date picker option list will be shown on input focus. | boolean | false |
required | required | An optional prop to flag the component as required within a form context. | boolean | false |
validation | -- | An optional DatePicker validation prop Required Fields type | { type: Variants.valid \| Variants.invalid \| Variants.note; message?: string; } | undefined |
value | value | An optional DatePicker value. Must be in IS0-8601 format: YYYY-MM-DD. | string | undefined |
Events
Event | Description | Type |
---|---|---|
dhlBlur | Event emitted when the component loses focus. | CustomEvent<{ component: string; componentId: string; }> |
dhlChange | Event emitted when the component changes value. | CustomEvent<{ component: string; componentId: string; value: string; valueAsDate: Date; short: string; long: string; }> |
dhlClose | Event emitted when the component is closed. | CustomEvent<{ component: string; componentId: string; }> |
dhlFocus | Event emitted when the component is focused. | CustomEvent<{ component: string; componentId: string; }> |
dhlOpen | Event emitted when the component is opened. | CustomEvent<{ component: string; componentId: string; }> |
Methods
checkValidity() => Promise<boolean>
Checks the validity of the component.
Returns
Type: Promise<boolean>
A promise that resolves to true if the component is valid, otherwise false.
getInputElement() => Promise<HTMLInputElement>
Retrieves the input element asynchronously.
Returns
Type: Promise<HTMLInputElement>
A promise that resolves to the input element.
getValidationMessage() => Promise<string>
Retrieves the validation message for the component.
Returns
Type: Promise<string>
A promise that resolves to a string representing the validation message.
hide(moveFocusToButton?: boolean) => Promise<void>
Hide the calendar modal. Set moveFocusToButton
to false to prevent focus
returning to the date picker's button. Default is true.
Parameters
Name | Type | Description |
---|---|---|
moveFocusToButton | boolean |
Returns
Type: Promise<void>
reportValidity() => Promise<boolean>
Reports the validity of the component.
Returns
Type: Promise<boolean>
A promise that resolves to a boolean indicating whether the component is valid.
setFocus() => Promise<void>
Sets focus on the date picker's input. Use this method instead of the
global focus()
.
Returns
Type: Promise<void>
setValidity(validity: ValidityState, validationMessage?: string) => Promise<void>
Sets the validity state of the component.
Parameters
Name | Type | Description |
---|---|---|
validity | ValidityState | - The validity state to set. |
validationMessage | string | - An optional validation message to set. |
Returns
Type: Promise<void>
A Promise that resolves when the validity state is set.
show() => Promise<void>
Show the calendar modal, moving focus to the calendar inside.
Returns
Type: Promise<void>
willValidate() => Promise<boolean>
Returns a promise that resolves to true if the element will successfully validate, or false otherwise.
Returns
Type: Promise<boolean>
A promise that resolves to a boolean value indicating whether the element will validate.
Dependencies
Depends on
Graph
Built by DHL User Interface Library Team!