Piplup
@piplup/rhf-adaptersmui-tel-inputComponents

MuiTelInputElement

A mui-tel-input field connected to React Hook Form that stores the international phone number string and validates it with matchIsValidTel.

MuiTelInputElement renders MuiTelInput from mui-tel-input, with its country selector, and stores the phone number in React Hook Form as a string. It accepts all MuiTelInput props, such as defaultCountry, onlyCountries and forceCallingCode. To build your own phone field, use useMuiTelInputAdapter.

Import

import { MuiTelInputElement } from "@piplup/rhf-adapters/mui-tel-input";

Usage

"use client";import Stack from "@mui/material/Stack";import { MuiTelInputElement } from "@piplup/rhf-adapters/mui-tel-input";import { MuiButtonElement } from "@piplup/rhf-adapters/mui-material";import { useForm } from "react-hook-form";export default function Page() {  const { control, handleSubmit } = useForm({    defaultValues: { phone: "+1 555 123 4567" },  });  return (    <form      onSubmit={handleSubmit((values) =>        alert(JSON.stringify(values, null, 2)),      )}    >      <Stack direction="column" spacing={2}>        <MuiTelInputElement          control={control}          name="phone"          label="Phone number"        />        <div>          <MuiButtonElement control={control} type="submit" variant="contained">            Submit          </MuiButtonElement>        </div>      </Stack>    </form>  );}

Validating phone numbers

The element doesn't check whether a number is real. Use matchIsValidTel from mui-tel-input in rules.validate. It accepts the same onlyCountries, excludedCountries and continents options as the input, so the rule can match what the country menu offers. This demo starts on the UK, allows three countries, and rejects incomplete numbers.

"use client";import Stack from "@mui/material/Stack";import { MuiButtonElement } from "@piplup/rhf-adapters/mui-material";import { MuiTelInputElement } from "@piplup/rhf-adapters/mui-tel-input";import { type MuiTelInputCountry, matchIsValidTel } from "mui-tel-input";import { useForm } from "react-hook-form";const COUNTRIES: MuiTelInputCountry[] = ["GB", "IE", "US"];export default function Page() {  const { control, handleSubmit } = useForm({ defaultValues: { phone: "" } });  return (    <form      noValidate      onSubmit={handleSubmit((values) => alert(JSON.stringify(values, null, 2)))}    >      <Stack direction="column" spacing={2}>        <MuiTelInputElement          control={control}          name="phone"          label="Mobile number"          defaultCountry="GB"          onlyCountries={COUNTRIES}          required          messages={{ required: "Enter a phone number" }}          rules={{            validate: (value) =>              matchIsValidTel(value, { onlyCountries: COUNTRIES }) ||              "Enter a valid UK, Irish or US number",          }}        />        <div>          <MuiButtonElement control={control} variant="contained" type="submit">            Submit          </MuiButtonElement>        </div>      </Stack>    </form>  );}

With onlyCountries, matchIsValidTel checks the country it detects from the number, not the one picked in the menu. Numbers that share a calling code with other territories can be detected as one of those. For example, +44 7911 123456 is a valid number but is not detected as GB, so the rule above rejects it while +44 7400 123456 passes.

How it works

Stored value. The form stores the text shown in the input: the full international number, formatted with spaces, e.g. "+44 7400 123456". With disableFormatting, it stores the number without spaces ("+447400123456"). defaultValues can use either form.

Default country. defaultCountry only changes what the input shows. With an empty value and defaultCountry="GB", the input displays +44, but the form value stays "" until the user types. Submitting at that point fails required.

Country menu. Choosing a country from the menu stores its calling code right away, e.g. "+33". That passes required, so pair required with a matchIsValidTel rule as in the demo.

Extra details. onChange and onBlur on the element receive a second argument with numberValue (E.164, such as "+447400123456"), countryCode, nationalNumber and more. The form itself only stores the string.

Focus. React Hook Form's ref is merged with your inputRef and attached to the <input>, so setFocus and focus-on-error work. A ref on the element goes to the root.

Errors and helper text. While the field is invalid, its error message replaces helperText. The default required message is "Please fill out this field."

Props

Prop

Type

On this page