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

useMuiXMobileDatePickerAdapter

Returns adapter props for MUI X MobileDatePicker with React Hook Form, with month-level rules through shouldDisableMonth.

useMuiXMobileDatePickerAdapter returns React Hook Form props for MUI X's MobileDatePicker. It's what MuiXMobileDatePickerElement uses internally.

Use the element for most forms. Use the hook when you build a touch-first date field with your own rules, for example a booking field for a service that only runs in certain months.

Import

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

Usage

This FerryDateField opens on the month view and only accepts April to October, up to the end of next year. Open the dialog to see the closed months greyed out, or submit empty to see the required message.

MM/DD/YYYY

Season: April to October

"use client";import dayjs, { type Dayjs } from "dayjs";import Stack from "@mui/material/Stack";import { LocalizationProvider, MobileDatePicker } from "@mui/x-date-pickers";import { AdapterDayjs } from "@mui/x-date-pickers/AdapterDayjs";import { MuiButtonElement } from "@piplup/rhf-adapters/mui-material";import { useMuiXMobileDatePickerAdapter } from "@piplup/rhf-adapters/mui-x-date-pickers";import { type Control, useForm } from "react-hook-form";type FormValues = { crossing: Dayjs | null };// The ferry runs April to October (months 3 to 9 in dayjs), up to next year.function isOffSeason(date: Dayjs) {  return date.month() < 3 || date.month() > 9;}function FerryDateField({ control }: { control: Control<FormValues> }) {  const adapter = useMuiXMobileDatePickerAdapter<Dayjs, FormValues, "crossing", HTMLDivElement>({    control,    name: "crossing",    required: true,    composeHelperText: true,    disablePast: true,    maxDate: dayjs().add(1, "year").endOf("year"),    shouldDisableMonth: isOffSeason,    messages: {      required: "Choose a crossing date",      disablePast: "That crossing has already sailed",      shouldDisableMonth: "The ferry only runs from April to October",      maxDate: "Bookings open one season ahead",    },    slotProps: {      textField: { helperText: "Season: April to October" },    },  });  return (    <MobileDatePicker      label="Crossing date"      views={["year", "month", "day"]}      openTo="month"      {...adapter}    />  );}export default function Page() {  const { control, handleSubmit } = useForm<FormValues>({    defaultValues: { crossing: null },  });  return (    <LocalizationProvider dateAdapter={AdapterDayjs}>      <form        noValidate        onSubmit={handleSubmit((values) =>          alert(values.crossing?.format("dddd, D MMMM YYYY")),        )}      >        <Stack direction="column" spacing={2}>          <FerryDateField control={control} />          <div>            <MuiButtonElement control={control} variant="contained" type="submit">              Book crossing            </MuiButtonElement>          </div>        </Stack>      </form>    </LocalizationProvider>  );}

How it works

This hook calls useMuiXDatePickerAdapter with the same props and returns its result unchanged. Value handling, the full list of validation messages and the text field wiring are documented there.

The difference is the component. DatePicker picks a layout with a media query. MobileDatePicker always opens the calendar in a modal dialog with action buttons, whatever the device.

Month and year rules. shouldDisableMonth and shouldDisableYear receive the full selected date during validation, and fail with their own keys (shouldDisableMonth, shouldDisableYear). The same functions grey out months and years in the dialog's month and year views. Checks run in a fixed order, shouldDisableDate, shouldDisableMonth, shouldDisableYear, then disablePast/disableFuture, minDate and maxDate, and only the first failure is reported. A past date in January shows the shouldDisableMonth message in the example, not the disablePast one.

Errors and blur. The text field gets error, helperText and onBlur through slotProps.textField. The hook also wraps onClose, so closing the dialog with either action button marks the field as touched. In onTouched mode, opening and cancelling the dialog on an empty required field shows the required message.

Props

Prop

Type

Return value

Prop

Type

On this page