Skip to content

Date Time Picker Form Cell

The date-time picker form cell lets users select a date, a time, or both.

Date Picker Form Cell:

Date Picker Form Cell

Time Picker Form Cell:

Time Picker Form Cell

Date Time Picker Form Cell:

Date Time Picker Form Cell

Using the DateTimePickerFormCell

The DateTimePickerFormCell composable function displays a form cell. When clicked, it opens a dialog to select the date and/or time. The API includes the following:

@Composable
fun DateTimePickerFormCell(
    modifier: Modifier = Modifier,
    mode: DateTimePickerMode = DateTimePickerMode.DATE_PICKER,
    label: String,
    required: Boolean = false,
    helperText: String = "",
    errorMessage: String = "",
    dateValueFormatter: String = "MMM d, y",
    timeValueFormatter: String = "h:mm a",
    pickerFormatter: String = "E, MMM d",
    rangeFormatter: String = "MMM d",
    datePickerState: FioriDatePickerState = rememberFioriDatePickerState(),
    timePickerState: TimePickerState = rememberTimePickerState(),
    dateSupportText: String = stringResource(R.string.date_picker_support),
    rangeSupportText: String = stringResource(R.string.date_picker_range_support),
    timeSupportText: String = stringResource(R.string.time_picker_support),
    useDateInput: Boolean = false,
    useTimeInput: Boolean = false,
    initialTimeCleared: Boolean = true,
    isError: Boolean = false,
    enabled: Boolean = true,
    onDateClicked: ((Date, FioriDatePickerState, FioriCalendarState) -> Unit)? = null,
    onDateCleared: ((FioriDatePickerState) -> Unit)? = null,
    onDateNegativeButtonClicked: ((FioriDatePickerState) -> Unit)? = null,
    onDatePositiveButtonClicked: ((FioriDatePickerState) -> Unit)? = null,
    onDateCancel: ((FioriDatePickerState) -> Unit)? = null,
    onTimeNegativeButtonClicked: ((TimePickerState) -> Unit)? = null,
    onTimePositiveButtonClicked: ((TimePickerState) -> Unit)? = null,
    dateColors: DatePickerColors = DatePickerDefaults.colors(),
    dateTextStyles: DatePickerTextStyles = DatePickerDefaults.textStyles(),
    dateStyles: DatePickerStyles = DatePickerDefaults.styles(),
    timeColors: TimePickerColors = FioriTimePickerDefaults.colors(),
    timeTextStyles: TimePickerTextStyles = FioriTimePickerDefaults.textStyles(),
    timeStyles: TimePickerStyles = FioriTimePickerDefaults.styles()
)

API Parameters

Below, you'll find more detailed explanations of some of the parameters.

Date Time Picker Mode

The mode parameter specifies the type of date and time picker to use. The available modes are: DATE_PICKER, TIME_PICKER, DATE_TIME_PICKER, and RANGE_PICKER. The default mode is DATE_PICKER.

Label

The label parameter sets the label at the top of the form cell. This parameter is required.

Required Field

The required parameter indicates if the cell should be marked as required. If set to true, an asterisk appears next to the label. The default value is false.

Helper Text

The helperText parameter displays text at the bottom of form cells. If a cell is in an error state, the error message replaces this text.

Error Message

Use the errorMessage parameter to display an error message at the bottom of the form cell when the isError parameter is set to true. This message replaces the helper text.

Format

Use the dateValueFormatter and timeValueFormatter parameters to format date and time values in the form cell. The pickerFormatter parameter formats the date in the date picker dialog. The rangeFormatter parameter formats the dates in the range picker dialog.

States

The datePickerState and timePickerState parameters let application developers modify the default values. Developers can also configure the picker dialogs according to their specific needs.

Support Text

You can use the dateSupportText, rangeSupportText, and timeSupportText parameters to set the support text displayed in the picker dialogs.

Input Mode

The useDateInput and useTimeInput parameters let you set whether the dialogs open in input mode. By default, both parameters are set to false.

Initial Time Cleared

Use the initialTimeCleared parameter to determine if the time picker starts with no time selected. By default, this parameter is set to true.

Error State

The isError parameter sets the error state of form cells. When set to true, the error message appears at the bottom of the form cell, replacing the helper text. The default value is false.

Enabled State

The enabled parameter sets whether form cells are enabled or disabled. If set to false, the form cells are disabled, preventing user interaction. The default value is true.

Callbacks

The following parameters are callback functions used to handle various events:

  • onDateClicked: This function is called when users click a date in the date picker dialog.
  • onDateCleared: This function is called when users clear the date in the date picker dialog.
  • onDateNegativeButtonClicked: This function is called when users click the negative button in the date picker dialog.
  • onDatePositiveButtonClicked: This function is called when users click the positive button in the date picker dialog.
  • onDateCancel: This function is called when users click the cancel button in the date range picker dialog.
  • onTimeNegativeButtonClicked: This function is called when users click the negative button in the time picker dialog.
  • onTimePositiveButtonClicked: This function is called when users click the positive button in the time picker dialog.

Colors and Styles

You can use the dateColors, dateTextStyles, and dateStyles parameters to customize the colors and styles of the date picker dialog. Similarly, the timeColors, timeTextStyles, and timeStyles parameters allow customization of the colors and styles in the time picker dialog.

Code Samples

Custom Range Selection Behavior

This code snippet shows how to create a date range picker form cell with custom behavior. The picker includes disabled dates that users can't select. Users must choose a range that doesn't cross any disabled dates.

var endDate by rememberSaveable { mutableStateOf(getDefaultStartEndDate(getCurrentLocale(), false)) }

val isDateDisabled: (Date) -> Boolean = {
    var isDisabled = false
    val currentCal = getCalendar(getCurrentLocale(), CalendarType.GREGORIAN)
    currentCal.time = it
    val disabledCal = getCalendar(getCurrentLocale(), CalendarType.GREGORIAN)
    for (date in disabledDates) {
        disabledCal.time = date
        if (isSameDate(currentCal, disabledCal)) {
            isDisabled = true
        }
    }
    isDisabled || it > endDate
}

DateTimePickerFormCell(
    mode = DateTimePicker.DateTimePickerMode.RANGE_PICKER,
    label = "Custom Range Selection Behavior",
    helperText = "Please select a range",
    errorMessage = "Range should be multiple days",
    datePickerState = FioriDatePickerState(
        FioriCalendarData(
            useRangeSelection = true,
            isDateDisabled = isDateDisabled
        )
    ),
    rangeSupportText = "Select range without crossing disabled dates",
    isError = isError,
    onDateClicked = { date, state, _ ->
        val nextDisabledDateIndex = findNextDisabledDateIndex(date, disabledDates)
        endDate = if (state.rangePickOn.value) {
            getDefaultStartEndDate(getCurrentLocale(), false)
        } else {
            if (nextDisabledDateIndex >= 0) {
                disabledDates[nextDisabledDateIndex]
            } else {
                getDefaultStartEndDate(getCurrentLocale(), false)
            }
        }
    },
    onDateCleared = { state ->
        endDate = getDefaultStartEndDate(state.data.locale, false)
        scope.launch {
            snackbarHostState.showSnackbar("Selection cleared")
        }
    },
    onDateNegativeButtonClicked = { state ->
        endDate = getDefaultStartEndDate(state.data.locale, false)
        scope.launch {
            snackbarHostState.showSnackbar("Selection canceled")
        }
    },
    onDatePositiveButtonClicked = { state ->
        endDate = getDefaultStartEndDate(state.data.locale, false)
        helperText = if (state.selectedDateCleared.value) {
            "Please select a date"
        } else {
            ""
        }
        isError = state.selectedRange.value.size == 1
        scope.launch {
            snackbarHostState.showSnackbar("Selection saved")
        }
    },
    onDateCancel = { state ->
        endDate = getDefaultStartEndDate(state.data.locale, false)
        scope.launch {
            snackbarHostState.showSnackbar("Exiting picker")
        }
    }
)

fun findNextDisabledDateIndex(date: Date, disabledDates: List<Date>): Int {
    if (disabledDates.isNotEmpty()) {
        val cal = getCalendar(getCurrentLocale(), CalendarType.GREGORIAN)
        cal.time = date
        var low = 0
        var mid = 0
        var high = disabledDates.size - 1
        while (low <= high) {
            mid = (low + high) / 2
            if (cal.time.after(disabledDates[mid])) {
                low = mid + 1
            } else if (cal.time.before(disabledDates[mid])) {
                high = mid - 1
            } else {
                return mid
            }
        }
        return if (cal.time.before(disabledDates[mid])) {
            mid
        } else {
            if (mid + 1 < disabledDates.size) {
                mid + 1
            } else {
                -1
            }
        }
    } else {
        return -1
    }
}

Required Date Time Picker Form Cell

This code snippet shows how to create a date-time picker form cell. The cell is required and displays an error message if users don't select a date or time.

var isError by rememberSaveable { mutableStateOf(true) }
var isError2 by rememberSaveable { mutableStateOf(true) }

DateTimePickerFormCell(
    mode = DateTimePicker.DateTimePickerMode.DATE_TIME_PICKER,
    label = "Date Time Picker with Error Message",
    required = true,
    errorMessage = "Please make sure both date and time are selected",
    isError = isError || isError2,
    onDatePositiveButtonClicked = { state ->
        isError = state.selectedDateCleared.value
    },
    onTimePositiveButtonClicked = {
        isError2 = false
    }
)

Last update: August 8, 2025