useMuiFilledInputAdapter
Returns adapter props for building custom MUI FilledInput fields with React Hook Form.
useMuiFilledInputAdapter connects a field to React Hook Form and returns props you spread onto MUI's FilledInput. It's what MuiFilledInputElement uses internally.
Use it when you build a filled field from FormControl variant="filled", InputLabel, FilledInput and FormHelperText yourself, for example to add a placeholder that sits under the floating label, or to keep a URL or handle field's rules in one component.
Import
import { useMuiFilledInputAdapter } from "@piplup/rhf-adapters/mui-material";Usage
This optional WebsiteField must hold an https:// address when filled in. Leading and trailing spaces are removed as you type. Submit example.com to see the error.
"use client";import { type ChangeEvent, useId } from "react";import Stack from "@mui/material/Stack";import FormControl from "@mui/material/FormControl";import FormHelperText from "@mui/material/FormHelperText";import FilledInput from "@mui/material/FilledInput";import InputLabel from "@mui/material/InputLabel";import { MuiButtonElement, useMuiFilledInputAdapter,} from "@piplup/rhf-adapters/mui-material";import { type Control, useForm } from "react-hook-form";type FormValues = { website: string };// type="url" alone does not validate anything. The pattern does, and the// message has to be set explicitly once a pattern is passed.function WebsiteField({ control }: { control: Control<FormValues> }) { const id = useId(); const { ref, helperText, ...adapter } = useMuiFilledInputAdapter({ control, name: "website", type: "url", pattern: /^https:\/\/\S+\.\S+$/, composeHelperText: true, helperText: "Optional. Must start with https://", messages: { pattern: "Enter a full https:// address", }, transform: { output: (event: ChangeEvent<HTMLInputElement>) => event.target.value.trim(), }, }); return ( <FormControl variant="filled" error={adapter.error}> <InputLabel htmlFor={id}>Website</InputLabel> <FilledInput {...adapter} id={id} inputRef={ref} placeholder="https://example.com" /> <FormHelperText>{helperText}</FormHelperText> </FormControl> );}export default function Page() { const { control, handleSubmit } = useForm<FormValues>({ defaultValues: { website: "" }, }); return ( <form noValidate onSubmit={handleSubmit((values) => alert(JSON.stringify(values, null, 2)), )} > <Stack direction="column" spacing={2}> <WebsiteField control={control} /> <div> <MuiButtonElement control={control} variant="contained" type="submit"> Save profile </MuiButtonElement> </div> </Stack> </form> );}How it works
The hook has the same logic as useMuiInputAdapterProps: it falls back to a surrounding FormControl for required and disabled, and you should pass the returned ref to inputRef. Value handling, transforms and the validation rules are described on useMuiInputBaseAdapter.
Error state in the FormControl. The demo calls the hook in the same component that renders the FormControl, so it can pass error={adapter.error} to the control. InputLabel and FormHelperText then follow the field's error state without extra props. The trade-off is that the hook runs outside the FormControl and can't read its required or disabled. Pass those to the hook directly in this layout.
URL fields. type: "url" gives you the browser's URL keyboard on mobile, but it doesn't validate anything on its own. It only sets a default pattern message, "Please enter a valid url.", for a pattern you haven't passed. Once you pass pattern, that default is not used and the generic "Please match the requested format." shows instead. Set messages.pattern as the demo does.
Empty values pass pattern, so an optional field like this one needs no extra handling. Add required to make it mandatory.
Props
Prop
Type
Return value
Prop
Type