Roshan Ojha
Roshan Ojha

Reputation: 153

Generic AutoComplete erasing entire text on backspace

import TWTextField from "@/components/form-components/TWTextField/TWTextField";
import { Autocomplete } from "@mui/material";
import React from "react";
import { FieldValues, Path, Control, Controller } from "react-hook-form";
import ExpandMoreIcon from "@mui/icons-material/ExpandMoreRounded";

type OptionType<M extends Record<string, unknown> = Record<string, unknown>> = {
  value: string | number;
  label: string | number;
  key: string | number;
  meta?: M;
};

interface TWAutoCompleteInterface<T extends FieldValues> {
  disableClearable: boolean;
  placeholder: string;
  options: OptionType[];
  control: Control<T>;
  name: Path<T>;
}

const TWAutoComplete = <T extends FieldValues>({
  disableClearable,
  placeholder,
  options,
  name,
  control,
}: TWAutoCompleteInterface<T>) => {
  return (
    <Controller
      name={name}
      control={control}
      render={({ field: { onChange, value }, fieldState: { error } }) => {
        const currentOption =
          value && typeof value === "object"
            ? value
            : options.find(option => option.value === value) || null;

        return (
          <Autocomplete
            autoFocus={false}
            autoHighlight
            disableClearable={disableClearable}
            value={currentOption}
            onChange={(event, newValue) => {
              onChange(newValue);
            }}
            options={options}
            fullWidth
            getOptionLabel={(option: OptionType) =>
              option.label ? String(option.label) : ""
            }
            isOptionEqualToValue={(
              option: OptionType,
              selectedValue: OptionType
            ) => option.value === selectedValue.value}
            popupIcon={<ExpandMoreIcon />}
            size="small"
            renderInput={params => (
              <TWTextField
                register={control.register}
                name={name}
                {...params}
                placeholder={placeholder}
                errors={error}
              />
            )}
          />
        );
      }}
    />
  );
};

export default TWAutoComplete;

I tried to create a generic AutoComplete component that utilizes react-hook-from, but I ran into a issue. When I type something in the input field and press 'BackSpace', it deletes one character at a time. However, when I select and option from the dropdown and then press 'BackSpace', the entire text is cleared instead of deleting one character at a time. Even if I press any other key after selecting option, the entire text from the dropdown gets cleared.

FreeSolo solves this problem to some extent, but I think it's not suitable here

My TWTextField looks like

import { TextField, TextFieldProps } from "@mui/material";
import React from "react";
import {
  UseFormRegister,
  FieldValues,
  FieldErrors,
  Path,
  get,
  FieldError,
} from "react-hook-form";

type TWTextFieldProps<T extends FieldValues> = {
  label?: string;
  required?: boolean;
  placeholder?: string;
  multiline?: boolean;
  rows?: number;
  register: UseFormRegister<T>;
  name: Path<T>;
  errors: FieldErrors | FieldError | undefined;
} & TextFieldProps;

const TWTextField = <T extends FieldValues>({
  label,
  register,
  name,
  errors,
  placeholder,
  required = false,
  multiline,
  rows,
  ...props
}: TWTextFieldProps<T>) => {
  return (
    <TextField
      {...register(name)}
      required={required}
      label={label}
      placeholder={placeholder}
      error={!!get(errors, name)}
      helperText={get(errors, `${name}.message`)}
      multiline={multiline}
      rows={rows}
      {...props}
    />
  );
};

export default TWTextField;

Upvotes: 0

Views: 13

Answers (0)

Related Questions