Skip to main content
Version: v8.1.0-alpha.2

ontario-date-input

Use this component for user-friendly date input and display.

Usage guidance

Please refer to the Ontario Design System for current documentation guidance.

Disabled and read-only states

This component intentionally does not provide readOnly or disabled props.

Disabling form controls can create accessibility and usability barriers, and often does not explain what the user needs to fix.

Instead:

  • keep controls and submission actions available
  • use validation and error messaging to clearly identify missing or invalid input

For implementation examples, see Error messaging.

Source: https://designsystem.ontario.ca/components/detail/buttons.html#disabled-buttons

Configuration

Once the component package has been installed (see Ontario Design System Component Library for installation instructions), the date input component can be added directly into the project's code, and can be customized by updating the properties outlined here. Additional information on custom types for the date input properties are outlined here. Please see the examples below for how to configure the component.

Examples

Example of date input component

<ontario-date-input
placeholder='{
"day": "DD",
"month": "MM",
"year": "YYYY"
}'
min-year="500"
max-year="1000"
required="true"
date-options='["day", "month", "year"]'
hint-text="For example 2000 03 01"
caption='{
"captionText": "Exact Date",
"captionType": "default"
}'
></ontario-date-input>

Example of passing custom date validation function to modify validation logic or providing custom error strings.

<ontario-date-input></ontario-date-input>

<script>
function handleDateValidation(day, month, year) {
let error = '';
let dayInvalid = false;
let monthInvalid = false;
let yearInvalid = false;

if (day <= 0) {
dayInvalid = true;
}

if (month <= 0) {
monthInvalid = true;
}

if (year <= 0) {
yearInvalid = true;
}

if (dayInvalid || monthInvalid || yearInvalid) {
error = 'Invalid date.';
}

// add more logic here

return { errorMessage: error, dayInvalid, monthInvalid, yearInvalid };
}

document.querySelector('ontario-date-input').dateValidator = handleDateValidation;
</script>

Example of prefilling the component with an aggregate value for edit or resume flows.

<ontario-date-input value="2024-02-20" caption="Exact date" hint-text="For example 2000 03 01"></ontario-date-input>

The value prop accepts either:

  • a plain ISO date such as 2024-02-20
  • a full ISO 8601 timestamp such as 2024-02-20T15:30:00.000Z

When a valid value is provided, the component hydrates the internal year, month, and day fields and normalizes its aggregate value to a full UTC ISO timestamp.

When the aggregate value changes, listen for the component input and change events and read the normalized value from event.target.value, similar to a native form control. For convenience, the same aggregate value is also available in event.detail.value. The existing inputOnInput and inputOnChange custom events remain available if you need the field-level detail.

Forms

The ontario-date-input supports integration with native HTML <form> elements. This element integrates with the underlying browser form API.

The ontario-date-input returns an ISO 8601 formatted date with a time component of 00:00:00Z, or midnight UTC, eg. 2024-02-20T00:00:00.000Z, combining the year, month, and day fields together. It has to be noted that the input only supports numerical values within any of the fields.

The aggregate value property on the component follows the same normalized full ISO format. This means:

  • incoming plain ISO dates are accepted and normalized
  • incoming full ISO timestamps are accepted and normalized to midnight UTC for the same calendar date
  • incomplete or invalid field combinations do not produce an aggregate value for form submission

If you are listening for changes on the component, read the normalized aggregate value from the component instance:

document.querySelector('ontario-date-input').addEventListener('change', (event) => {
console.log(event.target.value);
console.log(event.detail.value);
});

The same pattern works in framework wrappers:

<OntarioDateInput
value="2024-02-20"
caption="Exact date"
onInput={(event) => {
console.log((event.target as HTMLOntarioDateInputElement).value);
}}
onChange={(event) => {
console.log((event.target as HTMLOntarioDateInputElement).value);
}}
/>
<form>
<!-- Add an ontario-date-input -->
<ontario-date-input
element-id="date-input-1"
name="date-input-1"
placeholder='{
"day": "DD",
"month": "MM",
"year": "YYYY"
}'
min-year="999"
max-year="9999"
required
date-options='["day", "month", "year"]'
hint-text="For example 2000 03 01"
caption="Enter a date"
></ontario-date-input>

<!-- Submit the form with a submit button -->
<ontario-button type="primary" html-type="submit">Submit</ontario-button>
</form>

Remember to set the name attribute as this is used to identify the field when submitting the form.

Event model

Each event emitted by the component uses the CustomEvent type to emit a custom event to help communicate what the component is doing. To access the data emitted by the component within the CustomEvent type use the CustomEvent.detail property.

Eg. To access the value of any change made to this component from the inputOnInput event, use the following code to wire up to listen for the the inputOnInput event.

<ontario-date-input
element-id="date-input-example-id"
id="date-input-1"
placeholder='{
"day": "DD",
"month": "MM",
"year": "YYYY"
}'
min-year="999"
max-year="9999"
required="true"
date-options='["day", "month", "year"]'
hint-text="For example 2000 03 01"
caption='{
"captionText": "Exact Date",
"captionType": "default"
}'
></ontario-date-input>
<script>
// Note: this waits for the page and components to load before
// locating the component.
window.onload = () => {
const dateInput1 = document.getElementById('date-input-1');
dateInput1.addEventListener('inputOnInput', (event) => {
console.log('OnInput detail:', event.detail);
});
};
</script>

If the number 2 is entered into the year input within date-input-1, the value of event.detail is the object emitted along with the inputOnInput event.

{ value: "2", fieldType: "year" }

See the Events table to learn more about the available custom events from the component and what the type of CustomEvent.detail will be.

Native input and change events

The component uses a ShadowDOM to maintain encapsulation, however, this changes how the events flow from the inside of the component to the outside in the DOM.

The component emits input and change events when the aggregate date value changes so consumers can respond to updates using the familiar native event names. Read the aggregate ISO value from event.target.value.

The same aggregate value is also included in event.detail.value for consumers that prefer event payloads.

The field-level inputOnInput and inputOnChange custom events remain available when you need to know which sub-field changed.

When using libraries that listen for events, this process may not work with them and a workaround might be required depending on the framework or library in use.

Error messaging

Use validation and error messaging to help users understand what needs to be corrected.

Setting an error message

Use dateValidator to return contextual errors (DateValidatorReturnType) and surface message text through errorMessage.

Static vs live validation

Use a static errorMessage when validation happens on submit (for example, after a form post or submit handler check).

Use live validation when you want real-time feedback as users interact (for example, on change or blur).

For more guidance, visit the Error messaging guidance page.

<ontario-date-input id="date-of-birth" caption="Date of birth" required></ontario-date-input>
<script>
window.addEventListener('load', () => {
const dateInput = document.getElementById('date-of-birth');
dateInput.dateValidator = (day, month, year) => {
const allPartsPresent = !!day && !!month && !!year;
return {
errorMessage: allPartsPresent ? '' : 'Enter a complete date of birth.',
dayInvalid: !day,
monthInvalid: !month,
yearInvalid: !year,
};
};
});
</script>

Live validation

Keep the control available and validate date fields on interaction (for example, on blur or submit). Return contextual error guidance from dateValidator so users can correct incomplete or invalid values.

Custom property types

DateValidatorReturnType

The dateValidator function returns DateValidatorReturnType for custom date input validation. Below is example of dateValidator function.

<script>
function handleDateValidation(day, month, year) {
return {
errorMessage: 'Invalid Error',
dayInvalid: true,
monthInvalid: false,
yearInvalid: false,
};
}
</script>
PropertyTypeDescriptionRequired
errorMessagestringError message to display for invalid date.NO
dayInvalidbooleanIndicate if day is invalidYES
monthInvalidbooleanIndicate if month is invalidYES
yearInvalidbooleanIndicate if year is invalidYES

caption

The caption property is used to render the label for the ontario-input. It can be passed either a string or an object. If no captionType needs to be specified, it can be passed as a string.

caption='{ "captionText": "Exact Date", "captionType": "heading" }'

Technical Note: SSR (Server-Side Rendering) Considerations

The Ontario Date Input component is compatible with server-side rendering, with a few additional considerations:

  • Language prop: Language change events only fire in the browser after hydration. To ensure the correct language is rendered during SSR, pass the desired language explicitly as a prop.
  • Dynamic ID generation: If elementId is not passed, a UUID is generated at runtime. To prevent hydration mismatches between server and client, explicitly pass a stable elementId.
  • Rendered structure vs submitted value: During SSR, the component renders the expected day, month, and year inputs. The aggregated ISO 8601 value is assembled after hydration, so do not assume that aggregate value will participate in native form submission before hydration.
  • Form participation: This component uses the Form-Associated Custom Elements API (@AttachInternals) to participate in native form submission. Full date normalization, aggregate host input and change events, and component-managed date validation become available after hydration.
  • No-JavaScript fallback: If a flow must submit before hydration or without JavaScript, provide explicit native fallback markup in the consuming application.
  • Framework guidance: Use the HTML <form> example above for native submit or progressive-enhancement flows once hydrated. For client-managed integrations, use the event examples below. For App Router setup details, follow the Next.js integration guide.

Recommended for SSR:

<OntarioDateInput elementId="my-date-input" language="en"></OntarioDateInput>

Overview

Ontario Date Input captures day, month, and year values as a single date field.

This component intentionally does not expose readOnly or disabled props.

To support accessible and understandable form completion:

  • keep form fields and submission actions available
  • use validation and error messaging to guide corrections

For component guidance, see:

Disabled/read-only policy source:

Properties

PropertyAttributeDescriptionTypeDefault
captioncaptionThe text to display as the input labelCaption | stringundefined
dateOptionsdate-optionsAn array value used to display date options. For example, only the day and month fields can be displayed by specifying the dateOptions as ["day", "month"], etc. This is optional. If no prop for dateOptions is passed, it will default to ["day", "month", "year"].DateInputFieldType[] | string | undefined['day', 'month', 'year']
dateValidatordate-validatorA function used to override internal date validation logic, which takes three arguments (i.e day, month and year) and returns an object of type DateValidatorReturnType This is optional. If no prop for dateValidator is passed, it will default to internal validation function to validate the date input.((day: string, month: string, year: string) => DateValidatorReturnType) | undefinedundefined
elementIdelement-idThe unique identifier of the input. This is optional - if no ID is passed, one will be generated.string | undefinedundefined
hintTexthint-textUsed to include the ontario-hint-text component for the date input group. This is optional.string | undefinedundefined
languagelanguageThe language of the component. This is used for translations, and is by default set through event listeners checking for a language property from the header. If none are passed, it will default to English."en" | "fr" | undefinedundefined
maxYearmax-yearA number value indicating maximum value allowed for year input field of the date component. This is optional. If no prop is passed, it will default to 9999.number | undefinedundefined
minYearmin-yearA number value indicating minimum value allowed for year input field of the date component. This is optional. If no prop is passed, it will default to 999.number | undefinedundefined
placeholderplaceholderAn object value used to set the placeholder text for the day, month and year input fields. Any combination of the three input fields (i.e day, month, year) of the date component can be overridden. This is optional. If no prop is passed, it will not display any placeholder text.string | undefined | { day?: string | undefined; month?: string | undefined; year?: string | undefined; }undefined
requiredrequiredA boolean value to determine whether or not the date input is required. This is optional. If no prop is passed, it will default to false.boolean | undefinedfalse
valuevalueThe aggregate date value for the component. Accepts either a plain ISO date (YYYY-MM-DD) or a full ISO 8601 timestamp. When a valid value is provided, the component hydrates the internal day, month, and year fields and normalizes the stored form value to a full UTC ISO timestamp (YYYY-MM-DDT00:00:00.000Z).string | undefinedundefined

Events

EventDescriptionType
inputErrorOccurredEmitted when an error message is reported to the component.CustomEvent<{ inputId: string; errorMessage: string; }>
inputOnBlurEmitted when a keyboard input event occurs when an input has lost focus.CustomEvent<"day" | "month" | "year">
inputOnChangeEmitted when a change event occurs within the component.CustomEvent<{ value: string; fieldType: "day" | "month" | "year"; }>
inputOnFocusEmitted when a keyboard input event occurs when an input has gained focus.CustomEvent<"day" | "month" | "year">
inputOnInputEmitted when an input event occurs within the component.CustomEvent<{ value: string; fieldType: "day" | "month" | "year"; }>

Dependencies

Depends on

Graph


Built with StencilJS