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
- HTML
- React
- Angular
<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>
<OntarioDateInput
placeholder={{
day: 'DD',
month: 'MM',
year: 'YYYY',
}}
minYear={500}
maxYear={1000}
required={true}
dateOptions={['day', 'month', 'year']}
hintText="For example 2000 03 01"
caption={{
captionText: 'Exact Date',
captionType: 'default',
}}
/>
<ontario-date-input
[placeholder]="{ day: 'DD', month: 'MM', year: 'YYYY' }"
[minYear]="500"
[maxYear]="1000"
required="true"
[dateOptions]="['day', 'month', 'year']"
[hintText]="'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.
- HTML
- React
- Angular
<ontario-date-input value="2024-02-20" caption="Exact date" hint-text="For example 2000 03 01"></ontario-date-input>
<OntarioDateInput value="2024-02-20" caption="Exact date" hintText="For example 2000 03 01" />
<ontario-date-input
[value]="'2024-02-20'"
[caption]="'Exact date'"
[hintText]="'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:
- React
- Angular
<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);
}}
/>
<ontario-date-input
[value]="'2024-02-20'"
[caption]="'Exact date'"
(input)="handleDateInput($event)"
(change)="handleDateChange($event)"
></ontario-date-input>
handleDateInput(event: Event) {
console.log((event.target as HTMLOntarioDateInputElement).value);
}
handleDateChange(event: 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.
- HTML
- React
- Angular
<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>
<OntarioDateInput
elementId="date-of-birth"
caption="Date of birth"
required
dateValidator={(day, month, year) => {
const allPartsPresent = !!day && !!month && !!year;
return {
errorMessage: allPartsPresent ? '' : 'Enter a complete date of birth.',
dayInvalid: !day,
monthInvalid: !month,
yearInvalid: !year,
};
}}
/>
<ontario-date-input
[elementId]="'date-of-birth'"
[caption]="'Date of birth'"
[required]="true"
[dateValidator]="validateDateOfBirth"
></ontario-date-input>
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>
| Property | Type | Description | Required |
|---|---|---|---|
errorMessage | string | Error message to display for invalid date. | NO |
dayInvalid | boolean | Indicate if day is invalid | YES |
monthInvalid | boolean | Indicate if month is invalid | YES |
yearInvalid | boolean | Indicate if year is invalid | YES |
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
languageexplicitly as a prop. - Dynamic ID generation: If
elementIdis not passed, a UUID is generated at runtime. To prevent hydration mismatches between server and client, explicitly pass a stableelementId. - 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 hostinputandchangeevents, 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:
- https://designsystem.ontario.ca/components/detail/dates.html
- https://designsystem.ontario.ca/developer-docs/components/ontario-date-input/
Disabled/read-only policy source:
Properties
| Property | Attribute | Description | Type | Default |
|---|---|---|---|---|
caption | caption | The text to display as the input label | Caption | string | undefined |
dateOptions | date-options | An 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'] |
dateValidator | date-validator | A 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) | undefined | undefined |
elementId | element-id | The unique identifier of the input. This is optional - if no ID is passed, one will be generated. | string | undefined | undefined |
hintText | hint-text | Used to include the ontario-hint-text component for the date input group. This is optional. | string | undefined | undefined |
language | language | The 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" | undefined | undefined |
maxYear | max-year | A 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 | undefined | undefined |
minYear | min-year | A 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 | undefined | undefined |
placeholder | placeholder | An 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 |
required | required | A 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 | undefined | false |
value | value | The 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 | undefined | undefined |
Events
| Event | Description | Type |
|---|---|---|
inputErrorOccurred | Emitted when an error message is reported to the component. | CustomEvent<{ inputId: string; errorMessage: string; }> |
inputOnBlur | Emitted when a keyboard input event occurs when an input has lost focus. | CustomEvent<"day" | "month" | "year"> |
inputOnChange | Emitted when a change event occurs within the component. | CustomEvent<{ value: string; fieldType: "day" | "month" | "year"; }> |
inputOnFocus | Emitted when a keyboard input event occurs when an input has gained focus. | CustomEvent<"day" | "month" | "year"> |
inputOnInput | Emitted when an input event occurs within the component. | CustomEvent<{ value: string; fieldType: "day" | "month" | "year"; }> |
Dependencies
Depends on
Graph
Built with StencilJS