В MUI компонентах мне не хватало поддержки ввода с маской. Давайте подключим библиотеку imask к mui компоненту TextField для ликвидации этого пробела.
Установите в ваш проект библиотеку imask (https://imask.js.org/), и сам материал https://mui.com.
1 |
npm i @mui/material imask |
Я буду делать управляемый извне компонент, потому ему понадобится свойство onSave: функция, куда будет возвращаться новое состояние (значение) компонента. Также мы будет передавать в компонент mask — собственно саму маску.
Понадобится также начальное значение — value и метка (title) для текстового поля, упакуем это в свойство data.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
import React, { useEffect, useRef } from 'react'; import { TextField } from '@mui/material'; import IMask from 'imask'; interface IProps { data: { title: string, value: string } mask: string onSave: (value: string) => void } export const Masked = ({ data, mask, onSave }: IProps): React.ReactElement => { const ref = useRef(null); let maskObj: any | null = null const handleBlur = (event: React.FocusEvent<HTMLInputElement>): void => { onSave(maskObj === null ? '' : maskObj.unmaskedValue); }; useEffect(() => { if (ref.current !== null) { maskObj = IMask(ref.current, { mask, lazy: false }); maskObj.unmaskedValue = data.value } }); return ( <TextField fullWidth onBlur={handleBlur} label={data.label} value={maskObj?.value} variant='standard' inputRef={ref} ); }; |
При потере фокуса мы отправляем новое значение в родительский компонент, где реализованы сохранение/верификация данных поля в общем состоянии приложения.
useEffect помогает с инициализацией IMask и привязкой к компоненту.
Пример использования:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
// handleSave // зависит от архитектуры вашего приложения. // Идея в том, чтобы обновить состояние приложения, // на основе новых данных const handleSave = (value: string): void => { const newField = Object.assign({}, field) newField.value = value; dispatch(pendingUpdateFields( newField )) } // компонент ввода номера телефона const componentTel = <Masked data={field} mask={'+7 (000) 00-00-000'} onSave={handleSave} /> |