Piplup
@piplup/rhf-adaptersmui-x-date-pickersHooks

useMuiXMobileDateTimePickerAdapter

Returns adapter props for MUI X MobileDateTimePicker with React Hook Form, including how to validate an earliest allowed date and time.

useMuiXMobileDateTimePickerAdapter returns React Hook Form props for MUI X's MobileDateTimePicker. It's what MuiXMobileDateTimePickerElement uses internally.

Use the element for most forms. Use the hook when you build a touch-first date-time field with rules that depend on the current moment, such as a pickup time that must be at least two hours away.

Import

import { useMuiXMobileDateTimePickerAdapter } from "@piplup/rhf-adapters/mui-x-date-pickers";

Usage

This PickupField rejects anything earlier than two hours from now and only accepts half-hour slots. Open the dialog to see the earlier times greyed out, or submit without a value to see the required message.

MM/DD/YYYY hh:mm

Tap to open the picker

"use client";import { useState } from "react";import dayjs, { type Dayjs } from "dayjs";import Stack from "@mui/material/Stack";import { LocalizationProvider, MobileDateTimePicker } from "@mui/x-date-pickers";import { AdapterDayjs } from "@mui/x-date-pickers/AdapterDayjs";import { MuiButtonElement } from "@piplup/rhf-adapters/mui-material";import { useMuiXMobileDateTimePickerAdapter } from "@piplup/rhf-adapters/mui-x-date-pickers";import { type Control, useForm } from "react-hook-form";type FormValues = { pickup: Dayjs | null };// Orders need two hours to prepare. `disableIgnoringDatePartForTimeValidation`// makes the hook compare `minTime` against the full date and time, so it works as// a "not before this moment" rule instead of a daily opening time. `disablePast`// makes the picker do the same, so the views grey out the right times.function PickupField({ control }: { control: Control<FormValues> }) {  const [earliest] = useState(() => dayjs().add(2, "hour").startOf("minute"));  const adapter = useMuiXMobileDateTimePickerAdapter<Dayjs, FormValues, "pickup", HTMLDivElement>({    control,    name: "pickup",    required: true,    composeHelperText: true,    disablePast: true,    minDate: earliest,    maxDate: earliest.add(30, "day"),    minTime: earliest,    disableIgnoringDatePartForTimeValidation: true,    minutesStep: 30,    messages: {      required: "Choose a pickup time",      minDate: `Pickup can't be before ${earliest.format("ddd D MMM")}`,      minTime: `The earliest pickup is ${earliest.format("ddd HH:mm")}`,      maxDate: "Orders can be placed up to 30 days ahead",      minutesStep: "Pickups are every half hour",    },    slotProps: {      textField: { helperText: "Tap to open the picker" },    },  });  return <MobileDateTimePicker label="Pickup" ampm={false} {...adapter} />;}export default function Page() {  const { control, handleSubmit } = useForm<FormValues>({    defaultValues: { pickup: null },  });  return (    <LocalizationProvider dateAdapter={AdapterDayjs}>      <form        noValidate        onSubmit={handleSubmit((values) =>          alert(values.pickup?.format("ddd D MMM, HH:mm")),        )}      >        <Stack direction="column" spacing={2}>          <PickupField control={control} />          <div>            <MuiButtonElement control={control} variant="contained" type="submit">              Place order            </MuiButtonElement>          </div>        </Stack>      </form>    </LocalizationProvider>  );}

How it works

This hook calls useMuiXDateTimePickerAdapter with the same props and returns its result unchanged. The validation keys and default messages are listed there.

The difference is the component. DateTimePicker switches between layouts with a media query. MobileDateTimePicker always opens the date and time views in a modal dialog with its own action buttons.

An earliest date and time. The hook does not read minDateTime. To validate "not before this moment", the example passes the same value to minDate and minTime and sets disableIgnoringDatePartForTimeValidation: true:

  • minDate rejects earlier days with the minDate message.
  • minTime with the flag compares the full date and time, so an earlier time on the same day fails with the minTime message. Without the flag, minTime would act as a daily opening time: a limit of 14:30 would also reject 09:00 tomorrow.
  • disablePast is set as well. MUI X's picker ignores the flag you pass and only compares full dates when disablePast, disableFuture, minDateTime or maxDateTime is set. With disablePast, the dialog greys out the same times the form rejects.

Create the limit once, for example with useState(() => dayjs().add(2, "hour")). A new dayjs() on every render moves the limit forward while the user fills the form, so a value that passed a moment ago can fail on submit.

Errors and blur. The text field gets error, helperText and onBlur through slotProps.textField. The hook also wraps onClose, so closing the dialog marks the field as touched, whether the user confirms or cancels. With mode: "onTouched", opening and cancelling the dialog on an empty required field shows the required message straight away.

Props

Prop

Type

Return value

Prop

Type

On this page