Material UI React Autocomplete Component

I'm currently working on integrating an Autocomplete component using the Material UI library.

However, I've encountered a challenge - I'm unsure of how to properly pass the value and onChange functions, especially since I have a custom TextField implementation that also requires these parameters. Should I duplicate the value and onChange props for both Autocomplete and TextField components? Or is there a more efficient solution available? Any assistance would be greatly appreciated! Below is my code snippet:

import { Autocomplete as MuiAutocomplete } from '@material-ui/lab'
import { FormControl } from 'components/_helpers/FormControl'
import { useStyles } from 'components/Select/styles'
import { Props as TextFieldProps, TextField } from 'components/TextField'

export type Props = Omit<TextFieldProps, 'children'> & {
  options: Array<any>
  value: string
  onChange: (value: string) => void

  disabled?: boolean
}

export const Autocomplete = (props: Props) => {
  const classes = useStyles()

  return (
    <FormControl
      label={props.label}
      error={props.error}
      helperText={props.helperText}
    >
      <MuiAutocomplete
        options={props.options}
        // value={props.value}
        // onChange={event =>
        //   props.onChange((event.target as HTMLInputElement).value as string)
        // }
        classes={{
          option: classes.menuItem,
        }}
        disabled={props.disabled}
        getOptionLabel={option => option.label}
        renderInput={params => (
          <TextField
            {...params}
            placeholder={props.placeholder}
            value={props.value}
            onChange={props.onChange}
          />
        )}
        renderOption={option => {
          return <Typography>{option.label}</Typography>
        }}
      />
    </FormControl>
  )
}

Answer №1

If you're working with Material UI, there are handy props available to manage the state of Autocomplete compared to input values.

For a detailed look at these props in action, you can check out the documentation here: https://material-ui.com/components/autocomplete/#controllable-states

In your specific case, make sure to include the inputChange and onInputChange props when using the Autocomplete component. These will be passed down to your TextField through parameters provided to the renderInput function.

Your final code should resemble something along the lines of the snippet below taken from the linked documentation:

<Autocomplete
  value={value}
  onChange={(event, newValue) => {
    setValue(newValue);
  }}
  inputValue={inputValue}
  onInputChange={(event, newInputValue) => {
    setInputValue(newInputValue);
  }}
  id="controllable-states-demo"
  options={options}
  style={{ width: 300 }}
  renderInput={(params) => <TextField {...params} label="Controllable" variant="outlined" />}
/>

Answer №2

import React, { useEffect, useState } from "react";
import { Autocomplete } from "@mui/material/node";
import { Controller, useFormContext } from "react-hook-form";
import { TextField } from "@mui/material";
import PropTypes from "prop-types";

 const valueFunction = (array, identifier) => {
  const temporary = array.length > 0 && array?.find((element) => element.id === identifier);
  return temporary;
};

AutocompleteSearch.propTypes = {
  options: PropTypes.arrayOf({
    title: PropTypes.string,
    id: PropTypes.string,
  }),
  name: PropTypes.string,
};

export default function AutoCompleteSearch({
  name,
  options,
  label,
  id,
  ...other
}) {
  const [temporaryValue, setTemporaryValue] = useState({});
  const { control, setValue } = useFormContext();

  useEffect(async () => {
    const foundItem = valueFunction(options, id);
    await setTemporaryValue(foundItem);
  }, [options, id]);

  return (
    <Controller
      control={control}
      name={name}
      rules={{ required: true }}
      render={({ fieldState: { error } }) => (
        <>
          <div >
            <Autocomplete
              id="controllable-states-demo"
              onChange={(_, val) => {
                setValue(name, val?.id);
                setTemporaryValue(val);
              }}
              onBlur={(elem) => {
                elem.target.value == "" && setValue(name, "");
              }}
              value={temporaryValue}
              options={options}
              getOptionLabel={(item) => (item.title ? item.title : "")}
              renderInput={(parameters) => (
                <>
                  <TextField
                    {...parameters}
                    label={label}
                    InputLabelProps={{
                      style: {
                        fontSize: "14px",
                        fontWeight: "400",
                        color: "#FF5B00",
                      },
                    }}
                 
                    size="small"
                    error={temporaryValue === null && !!error}
                    helperText={temporaryValue === null && error?.message}
                    {...other}
                  />
                </>
              )}
            />
          </div>
        </>
      )}
    />
  );
}
 <AutoCompleteSearch
   name="pharmacy_group_title"
   label="Pharmacy Group" 
   options={pharmacyGroups}                           // Array  {id , title}   
   id={defaultValues?.pharmacy_group_title}           // ID
  />

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Submitting multiple values in React-PDF

I've been working on a form that allows users to input their name and surname, and then generate a pdf document from the entered information. To achieve this, I'm utilizing . However, I've encountered an issue where I can only submit one va ...

I desire for it to effortlessly unlock within my matmenu as soon as the webpage loads

Upon opening my page, I want the material menu to automatically open. However, since there is no click action, I am encountering an error stating that "trigger" is undefined. An error occurred: TypeError: Cannot read properties of undefined (reading &apo ...

Ways to organize backbone models, views, and collections using vim?

I am a fan of vim's folding feature, but I have encountered some challenges when trying to fold backbone models, views, and collections. This is because backbone does not follow the traditional prototype syntax, but instead uses a .extend() based synt ...

Issue with URL parameter in React when using React Router

Initially, everything was running smoothly in my React project using react-router-dom. However, once I added another Route like so: <Route path="/edit/:id" component={EditPage}/> and tried changing the URL in the browser to http://localhos ...

How can I set a background image to automatically adjust to the width of the window, be full height, allow for vertical scrolling, and

How can I set a full-screen background image that adjusts to the body width without horizontal scrolling, maintains height proportionate to width, and allows for vertical scrolling? Here is my current code: html, body { margin: 0px; padding: 0px; } bo ...

Changing buffer from base64 to UTF-8 encoding in Node.js

My application imports messages from the Notes folder of Gmail using the imap npm module. When following the example on their GitHub page, all message contents are read into a buffer: stream.on('data', function(chunk) { count += chunk.len ...

Issue with ReduxForm - The onSubmit method does not execute when using the submit() function

I'm having a problem with the onSubmit method when it's triggered by the onChange event. If the form below is submitted using a submit button, the function buttonOnSubmit is called. However, if the form is submitted through the function props.s ...

Ways to bypass HostListener in Angular 2

In the process of developing a page with animations triggered on scroll, I encountered the challenge of ensuring that the animations only occur when the corresponding element is visible on the viewport. Utilizing Angular2 for this task led me to investigat ...

What is the best way to configure eslint or implement tslint and prettier for typescript?

In my React/Redux project, I recently started integrating TypeScript into my workflow. The eslint configuration for the project is set up to extend the airbnb eslint configurations. Here's a snippet of my current eslint setup: module.exports = { // ...

Endless loop caused by Angular UI-router's promise resolving

I'm attempting to retrieve data from my SQLite database before loading a view using resolve when defining the state in ui-router. Currently, this is how I've set up the state: .state("menu", { templateUrl: "templates/menu.html", control ...

Utilizing Protractor, TypeScript, and Jasmine for Automated Testing

Just landed a new job at a company that uses protractor, jasmine, and Type Script for automation testing. While I have experience with selenium and Java, I'm unfamiliar with protractor. Can someone guide me on how to start protractor testing? Is there ...

Issues with the functionality of react-native-keyboard-aware-scroll-view are causing it to not

I've been experimenting with the react-native-keyboard-aware-scroll-view in order to prevent my inputs from being covered by the keyboard. However, I'm encountering an issue where it constantly assumes that there's an active keyboard, leadin ...

Conditional ngOptions in AngularJS allows you to dynamically update the options

Currently, I am working with a select box that iterates through an array of departments to identify eligible parent departments. <select class="editSelectBox" ng-model="dept.parentDepartment" ng-options="dept as dept.name for dept in depts track by de ...

Cleve js does not include delimiters in its date output

In my Vue.js project, I decided to implement a date input field using cleave.js. After passing the following options: options="{date: true, delimiter: '/', datePattern: ['m', 'd', 'Y']}" I encountered an issue wh ...

There seems to be a discrepancy where the page content is not appearing within the

I'm currently working on a project where I need to fetch content from an API and display it on a webpage. The fetching process is working well, but I've encountered an issue when trying to view the page source code. It seems that the content retr ...

create new Exception( "Invalid syntax, expression not recognized: " msg );

Can someone assist me in identifying the issue at hand? Error: There seems to be a syntax error, and the expression #save_property_#{result.id} is unrecognized. throw new Error( "Syntax error, unrecognized expression: " msg ); Here is the c ...

Avoid utilizing <Route> or withRouter() in instances where a <Router> is not present in React

Why am I encountering this error message? It says not to use withRouter() outside a component, but I do not have withRouter in my code. const AppWrapper = () => { return ( <Provider store={store}> <BrowserRouter> ...

Displaying AngularJS content as text in an HTML file

I have been learning from the AngularJS Tutorial on Code School, but I'm experiencing an issue where my JavaScript code is not rendering properly in the HTML. Below is the snippet of HTML code: <html ng-controller="StoreController as store"> & ...

"Interactive User Interface: Material Design inspired React cards with pop-up mod

Currently, I am working on configuring a React JS / Material UI modal dialog feature in my project. The goal is to make it so that when a user clicks on a card, a corresponding full-sized image with title and subtitle pops up. Each card's data is fetc ...

React with custom classes for Material UI Switch

I'm attempting to personalize the color of the toggle switch in Material UI using their classes props. I prefer not to use withStyles HOC because I am developing a customized Formik switch that can be utilized throughout my entire application. Howeve ...