Components
customdatepicker
A date-only picker. Use when the user selects a calendar date with no time component.
A date-only picker. Use when the user selects a calendar date with no time component.
Read Form Rules before using this component — keys, labels, required fields, expressions, visibility, and validation all follow shared conventions.
When to use
- Date of birth, issue date, expiry date, appointment date — any single calendar date
When NOT to use
Instead of customdatepicker, use… | For… |
|---|---|
customdatetimepicker | Date AND time selection |
customtimepicker | Time only |
Props
| Prop | Type | Required? | Description |
|---|---|---|---|
label | string | required | Visible label. Must be unique across the form. |
required | boolean | required | Always false. The expression controls the runtime value. |
defaultRequired | boolean | required | true for required fields, false for optional ones. |
placeholder | string | optional | Ghost text shown before a date is selected. |
minDate | object | optional | Earliest selectable date as { "year": N, "month": N, "day": N }. Not a string or ISO date. |
maxDate | object | optional | Latest selectable date as { "year": N, "month": N, "day": N }. Not a string or ISO date. |
addRemoveTimeMinDate | string | optional | Runtime offset applied to today for minDate. Format: "N:d" where N is days (negative = past, positive = future). e.g. "0:d" = today, "-30:d" = 30 days ago. |
addRemoveTimeMaxDate | string | optional | Runtime offset applied to today for maxDate. Same format as addRemoveTimeMinDate. |
dateFormat | string | optional | Display format, e.g. "DD MM YYYY", "MM DD YYYY". |
delimeter | string | optional | Date part separator, e.g. "/", "-". |
allowedDaysOfTheWeek | number[] | optional | Days the user may select. 1 = Monday … 7 = Sunday. Omit to allow all days. |
eventCode | string | optional | Event code for loading available booking dates from the backend. |
eventDatesMaxSize | string | optional | Maximum number of event dates to load. Must be a string, e.g. "5". |
tooltip | string | optional | Help text shown as an icon tooltip next to the label. |
hint | string | optional | Help text rendered below the field, always visible. |
hideField | boolean | optional | Hides the field and excludes its value from submission. Toggle via expressions["props.hideField"]. |
Validation messages
| Key | When shown |
|---|---|
required | Field is empty and required |
invalid | Value is not a valid date |
minDate | Selected date is before minDate |
maxDate | Selected date is after maxDate |
dayOfWeekIsNotAllowed | Selected day is not in allowedDaysOfTheWeek |
unavailableSlots | Selected date has no available slots (used with eventCode) |
Examples
Required date field — no future dates
addRemoveTimeMaxDate: "0:d" limits selection to today or earlier.
{
"key": "DATE_OF_BIRTH",
"type": "customdatepicker",
"props": {
"label": "Date of Birth",
"placeholder": "Select date",
"required": false,
"defaultRequired": true,
"addRemoveTimeMaxDate": "0:d"
},
"expressions": {
"props.required": "!(field?.props?.hideField || field?.hide) && field?.props?.defaultRequired"
},
"validation": {
"messages": {
"required": "Date of Birth is required.",
"invalid": "Please enter a valid date."
}
}
}Appointment date — future only, weekdays only
{
"key": "APPOINTMENT_DATE",
"type": "customdatepicker",
"props": {
"label": "Appointment Date",
"placeholder": "Select appointment date",
"required": false,
"defaultRequired": true,
"addRemoveTimeMinDate": "1:d",
"addRemoveTimeMaxDate": "30:d",
"allowedDaysOfTheWeek": [1, 2, 3, 4, 5],
"dateFormat": "DD MM YYYY",
"delimeter": "/"
},
"expressions": {
"props.required": "!(field?.props?.hideField || field?.hide) && field?.props?.defaultRequired"
},
"validation": {
"messages": {
"required": "Appointment Date is required.",
"invalid": "Please enter a valid date.",
"minDate": "Appointment date cannot be in the past.",
"maxDate": "Appointment date cannot exceed 30 days from today.",
"dayOfWeekIsNotAllowed": "Appointments are only available on weekdays."
}
}
}Fixed date range
Use minDate/maxDate objects (not strings) for hardcoded bounds.
{
"key": "ISSUE_DATE",
"type": "customdatepicker",
"props": {
"label": "Issue Date",
"placeholder": "Select issue date",
"required": false,
"defaultRequired": true,
"minDate": { "year": 2020, "month": 1, "day": 1 },
"maxDate": { "year": 2030, "month": 12, "day": 31 }
},
"expressions": {
"props.required": "!(field?.props?.hideField || field?.hide) && field?.props?.defaultRequired"
},
"validation": {
"messages": {
"required": "Issue Date is required.",
"invalid": "Please enter a valid date.",
"minDate": "Issue date cannot be before 2020.",
"maxDate": "Issue date cannot be after 2030."
}
}
}Common mistakes
- Setting
minDate/maxDateas ISO strings (e.g."2024-01-01") — they must be objects:{ "year": 2024, "month": 1, "day": 1 }. - Setting
addRemoveTimeMinDate/addRemoveTimeMaxDateas plain numbers — they must be strings in"N:d"format. - Setting
eventDatesMaxSizeas a number — it must be a string (e.g."5"). - Setting
allowedDaysOfTheWeekwith day names (e.g."Monday") — it must be an array of numbers (1–7). - Using
customdatepickerwhen a time component is also needed — usecustomdatetimepickerinstead. - Setting
props.required: truedirectly — always usedefaultRequired+ the expression.
Checklist
-
keyisUPPER_SNAKE_CASEand unique across the entire form -
props.labelis present, unique, and correctly cased - Field is nested at the correct depth:
sections > formly-group > block > customdatepicker -
required: falseis set (nevertrue) -
defaultRequiredis set -
expressions["props.required"]is present with the exact required expression -
validation.messages.requiredis present -
minDate/maxDate, if used, are objects not strings -
addRemoveTimeMinDate/addRemoveTimeMaxDate, if used, are"N:d"strings not numbers -
allowedDaysOfTheWeek, if used, is an array of integers 1–7 - Validation messages present for all active constraints (minDate, maxDate, dayOfWeekIsNotAllowed, etc.)