dǝɥɔS ʇoıןןƎ
dǝɥɔS ʇoıןןƎ

Reputation: 1830

Material UI Autocomplete custom renderInput

I'm following various examples from https://material-ui.com/components/autocomplete/ to create a custom autocomplete. I'm trying to use the renderInput property to use a custom input component. All of the examples I find use the TextField component, but I'd like to use a regular input component.

Problem is, the options are never displayed. I've created a demonstration here (swap renderInput with renderInputWORKING to see working version):

https://codesandbox.io/s/epic-johnson-oxy7b?file=/src/App.tsx

with the following code in renderInput:

 const renderInput = (params: AutocompleteRenderInputParams) => {
    console.log(params);
    const { InputLabelProps, inputProps, InputProps } = params;
    return (
      <div>
        <label {...InputLabelProps}>foo</label>
        <input {...InputProps} {...inputProps} />
      </div>
    );
  };

How can I use the <input /> component for renderInput prop on <Autocomplete />?

Upvotes: 13

Views: 49417

Answers (3)

Emperor Krauser
Emperor Krauser

Reputation: 259

Material 6.2.0. Just another info if you want other elements other than the list on the autocomplete.

You can do

<Autocomplete 
  options={options.length > 0 ? options : []}
  open={open}
  onOpen={() => setOpen(true)}
  onClose={() => setOpen(false)}
  onChange={handleGetSearchValue} // passed from parent component to get search values
  PaperComponent={(options) => {
    return (
      <Paper>
        <Box>
          <div>Custom Content</div>
        </Box>
        <Box>{options.children}</Box> //containers the list of options
      </Paper>
  )
  }
  renderInput={(params) => (
    <TextField
      {...params}
      onChange={handleSearchChange} // function in the search component to get the searched term
      placeholder="Search here"
    />
  )} />

Upvotes: 0

KARTHIKEYAN.A
KARTHIKEYAN.A

Reputation: 20168

We can able to writed custom renderInput in the following In my case I have writen the custom renderInput to avoide clear icon in the compoenet

<Autocomplete
    fullWidth={true}
    label={props.label}
    margin={'noraml'}
    multiple={false}
    name={props.name}
    isOptionEqualToValue={useCallback((option, value) => option.value === value.value, [])}
    value={props.value}
    options={props.options}
    ref={selectRef}
    id='disable-clearable'
    disableClearable
    renderInput={useCallback(params => (
        <TextField {...params} label='disableClearable' variant='standard' />
    ), [])}
    onChange={useCallback((e, v) => {
        if (typeof v === 'object' && v !== null) {
            _onChange(e, v)
        } else {
            _onChange(e, {label: ''})
        }
    }, [])}
/>

Upvotes: 0

Ryan Cogswell
Ryan Cogswell

Reputation: 81146

UPDATE

The 4.10.1 release of Material-UI (on June 1, 2020) included a new example in the documentation for this exact case: https://material-ui.com/components/autocomplete/#custom-input.

Pull request: https://github.com/mui-org/material-ui/pull/21257


The most useful example to look at in the documentation is the Customized Autocomplete example which uses InputBase instead of TextField. This example contains the following code for renderInput:

         renderInput={(params) => (
            <InputBase
              ref={params.InputProps.ref}
              inputProps={params.inputProps}
              autoFocus
              className={classes.inputBase}
            />
          )}

The InputProps passed to TextField are placed on a div that wraps the <input>, so most of those props are not appropriate to put directly on the <input> element as you were. In the code above from the documentation example, you can see that it only uses one thing from params.InputProps which is the ref. This ref is used for controlling the anchor element for the listbox of options. A ref is also placed on the <input> itself, but that ref is used for very different purposes. With your code, only one of those refs was getting used.

Below is a working example (based on the Combo Box example since your sandbox has a lot of other customizations that aren't directly related to this question) that uses <input> instead of TextField:

import React from "react";
import Autocomplete from "@material-ui/lab/Autocomplete";

export default function ComboBox() {
  return (
    <Autocomplete
      id="combo-box-demo"
      options={top100Films}
      getOptionLabel={option => option.title}
      style={{ width: 300 }}
      renderInput={params => (
        <div ref={params.InputProps.ref}>
          <label {...params.InputLabelProps}>My Label </label>
          <input {...params.inputProps} autoFocus />
        </div>
      )}
    />
  );
}

Edit Autocomplete using input instead of TextField

Upvotes: 25

Related Questions