Components

customtimepicker

A time-of-day picker with no calendar component. Use when the user picks only an hour and minute.

A time-of-day picker with no calendar component. Use when the user picks only an hour and minute.

Read Form Rules before using this component — keys, labels, required fields, expressions, visibility, and validation all follow shared conventions.

When to use

  • Preferred contact time
  • Daily operating hours, opening/closing times
  • Reminder time, alarm time
  • Any value that is just a time of day, not bound to a specific date

When NOT to use

Instead of customtimepicker, use…For…
customdatepickerA calendar date with no time component
customdatetimepickerA combined date-and-time value
input with patternA free-text duration like "2h30m" (not a clock time)

Props

PropTypeRequired?Description
labelstringrequiredVisible label. Must be unique across the form.
requiredbooleanrequiredAlways false. The expression controls the runtime value.
defaultRequiredbooleanrequiredtrue for required fields, false for optional ones.
placeholderstringoptionalGhost text shown before a value is selected.
startHournumberoptionalEarliest selectable hour in 24h format (e.g. 8 for 08:00).
endHournumberoptionalLatest selectable hour in 24h format (e.g. 18 for 18:00).
intervalnumberoptionalMinute interval between time slots (e.g. 15 for quarter-hour steps).
disabledbooleanoptionalDefault false. Disables the picker.
readonlybooleanoptionalDefault false. Renders the field as read-only.
tooltipstringoptionalHelp text shown as an icon tooltip next to the label.
hintstringoptionalHelp text rendered below the field, always visible.
internalDescriptionstringoptionalInternal note; not rendered to end users.
hideFieldbooleanoptionalHides the field and excludes its value from submission. Toggle via expressions["props.hideField"].
classNamestringoptionalCSS class applied to the field wrapper.

The required mechanism

Every customtimepicker field must include this exact expression, regardless of whether the field is required or optional.

"expressions": {
  "props.required": "!(field?.props?.hideField || field?.hide) && field?.props?.defaultRequired"
}
  • To make a field required: set defaultRequired: true.
  • To make a field optional: set defaultRequired: false.

Examples

Minimal — optional time

{
  "key": "PREFERRED_CONTACT_TIME",
  "type": "customtimepicker",
  "props": {
    "label": "Preferred Contact Time",
    "required": false,
    "defaultRequired": false
  },
  "expressions": {
    "props.required": "!(field?.props?.hideField || field?.hide) && field?.props?.defaultRequired"
  },
  "validation": {
    "messages": {}
  }
}

Required time field

{
  "key": "PREFERRED_CONTACT_TIME",
  "type": "customtimepicker",
  "props": {
    "label": "Preferred Contact Time",
    "placeholder": "Select a time",
    "required": false,
    "defaultRequired": true
  },
  "expressions": {
    "props.required": "!(field?.props?.hideField || field?.hide) && field?.props?.defaultRequired"
  },
  "validation": {
    "messages": {
      "required": "Preferred Contact Time is required."
    }
  }
}

Full example — working-hours window with half-hour intervals

{
  "key": "PREFERRED_CONTACT_TIME",
  "type": "customtimepicker",
  "props": {
    "label": "Preferred Contact Time",
    "placeholder": "Select a time",
    "required": false,
    "defaultRequired": true,
    "startHour": 8,
    "endHour": 18,
    "interval": 30
  },
  "expressions": {
    "props.required": "!(field?.props?.hideField || field?.hide) && field?.props?.defaultRequired"
  },
  "validation": {
    "messages": {
      "required": "Preferred Contact Time is required."
    }
  }
}

Common mistakes

  • Using customtimepicker when a date component is also needed — use customdatetimepicker instead.
  • Using customtimepicker for a date-of-birth or calendar date — use customdatepicker.
  • Setting props.required: true directly — always use defaultRequired: true with the standard expression.
  • Using validators: { validation: [...] } instead of validation: { messages: {} } for required messages.
  • Setting startHour/endHour/interval as strings — they must be numbers.
  • Using disabled to gate input — prefer readonly and toggle it via expressions["props.readonly"].

Checklist

  • key is UPPER_SNAKE_CASE and unique across the entire form
  • props.label is present, unique, and correctly cased
  • Field is nested at the correct depth: sections > formly-group > block > customtimepicker
  • required: false is set (never true)
  • defaultRequired is set
  • expressions["props.required"] is present with the exact required expression
  • validation.messages.required is present when defaultRequired: true
  • startHour, endHour, and interval are numbers, not strings
  • Not using customtimepicker for date or date-and-time values

On this page