ReactDatePicker with MUI TextField not working when validation rule provide error elm.focus

24 Views Asked by At

I make React datetime picker with MUI TextField every thing work properly but when I provide validation rule It's can not focus and highlight element with red border and I got error like image below

enter image description here

here is my custom component datetime picker

import { Controller, useForm, FieldValues, RegisterOptions, UseFormStateReturn } from 'react-hook-form'
import { IconButton, InputAdornment, TextField, useTheme } from '@mui/material'
import DatePicker, { ReactDatePickerProps, registerLocale } from 'react-datepicker'
import DatePickerWrapper from 'src/@core/styles/libs/react-datepicker'
import moment from 'moment'
import Icon from 'src/@core/components/icon'
import th from 'date-fns/locale/th'

registerLocale('th', th)

export const DateFormatSQL = `DD-MMM-YYYY`
export const DateFormatInput = `dd/MM/yyyy`
export const TimeFormat = `HH:mm:ss`
export enum DatetimeMode {
  DATE,
  DATETIME,
  TIME
}

type Props = {
  name: string
  control?: any
  label: string
  id?: string
  onChange?: (value: Date | null | string) => void
  isClearAble?: boolean
  mode?: DatetimeMode
  popperPlacement?: ReactDatePickerProps['popperPlacement'] // Add this line
  value?: Date
  isReadOnly?: boolean
  formState?: UseFormStateReturn<FieldValues>
  validationRules?: RegisterOptions
  disableValidate?: boolean
}

const DatetimePickerInput: React.FC<Props> = ({
  label,
  name,
  control,
  id = 'datePicker-controller',
  isClearAble = false,
  isReadOnly = false,
  mode = DatetimeMode.DATE,
  popperPlacement, // Add this prop
  value = null,
  onChange,
  formState,
  validationRules = null,
  disableValidate = false
}) => {
  const { control: formControl } = useForm()

  const theme = useTheme()
  const { direction } = theme
  const _popperPlacement: ReactDatePickerProps['popperPlacement'] = direction === 'ltr' ? 'bottom-start' : 'bottom-end'

  const timeFormat = ` ${TimeFormat}`
  const formatSql = `${DateFormatSQL}${mode === DatetimeMode.DATETIME ? timeFormat : ''}`
  const formatInput = `${DateFormatInput}${mode === DatetimeMode.DATETIME ? timeFormat : ''}`

  const isRequiredValue = () => (validationRules?.required && !isReadOnly ? true : false)

  const customTextFieldLabel = () => {
    return (
      <span>
        {label}{' '}
        {isRequiredValue() ? (

          // <span
          //   style={{
          //     color: 'red',
          //     fontWeight: 'bold',
          //     verticalAlign: 'middle' // Align the asterisk in the middle vertically
          //   }}
          // >
          //   **
          // </span>
          <></>
        ) : null}
      </span>
    )
  }

  return (
    <DatePickerWrapper>
      <Controller
        name={name}
        control={control || formControl}
        defaultValue={''}
        rules={validationRules && !disableValidate ? validationRules : {}}
        render={({ field }) => {
          return (
            <DatePicker
              {...field}
              locale={'th'}
              dateFormat={formatInput}
              showTimeSelect={mode === DatetimeMode.DATETIME}
              showTimeSelectOnly={mode === DatetimeMode.TIME}
              timeIntervals={1}
              timeFormat={timeFormat}
              selected={field.value ? moment(field.value).toDate() : null}
              isClearable={isClearAble}
              readOnly={isReadOnly}
              id={id}
              popperPlacement={popperPlacement ?? _popperPlacement} // Pass down the prop
              customInput={
                <TextField
                  fullWidth
                  variant='outlined'
                  label={customTextFieldLabel()}
                  InputProps={{
                    size: 'small',
                    readOnly: true,
                    endAdornment: (
                      <InputAdornment position='end'>
                        <IconButton edge='end' onMouseDown={e => e.preventDefault()}>
                          <Icon icon={'tabler:calendar'} fontSize={20} />
                        </IconButton>
                      </InputAdornment>
                    )
                  }}
                  InputLabelProps={{
                    size: 'small'
                  }}
                  value={field.value ?? ''}
                  error={Boolean(formState?.errors[name])}
                  FormHelperTextProps={
                    formState && formState.errors[name] ? { style: { color: 'red', fontWeight: 'bold' } } : {}
                  }
                  helperText={formState && formState.errors[name] ? (formState!.errors[name]!.message as string) : ''}
                />
              }
              onChange={(date: Date) => {
                const dateStr = moment(date).format(formatSql)
                field.onChange(date ? dateStr : null)
                if (onChange) onChange(dateStr ?? null)
              }}
            />
          )
        }}
      />
    </DatePickerWrapper>
  )
}

export default DatetimePickerInput

It's seem Control can't pass ref to custiom element

anyone can help to fix this problem

thank you

here is how I user this component

<DatetimePickerInput
                  control={control}
                  name={propertyOf<ExpenseMemoForm>('useDate')}
                  label={'Date to use'}
                  formState={formState}
                  validationRules={{
                    required: 'requiered value'
                  }}
                />
0

There are 0 best solutions below