1

I am overriding the Paper component of the Material UI Autocomplete to add a custom search. I don't want the main text area from the auto complete to be the search as I will be constructing a special string there based on what users select. You can see in the image below the chevrons, users can traverse up objects based on relationships.

So, my custom Paper to incorporate a custom search is coded like so:

PaperComponent={({children, ...other}) => {
        return (
            <Paper {...other}>
                <ClickAwayListener onClickAway={closeOptionsList}>
                    <div key="click-away-wrapper">
                        <Input
                            styleInput={{width: '100%'}}
                            value={customFilterString}
                            onChange={handleCustomFilterChange}
                            className="slds-m-horizontal_small slds-m-top_small"
                            iconRight={<InputIcon name="search" category="utility" />}
                        />
                        {children}
                    </div>
                </ClickAwayListener>
            </Paper>
        )}}

As a user types, I filter the available options and change the options of the autocomplete (using hooks).

The problem: After each character typed, the custom search filter loses focus... so I'd have to click into each for each letter I want to type. I tried several things I found as suggestions online like: add a unique key to the input, move the input declaration out of the main component so it won't be rerendered, set autoFocus, etc... Nothing actually fixes this. It always just loses focus after every character when I try to update the options list to appropriate options.

I am pretty much out of ideas on how to stop this and allow users to keep typing in the input to their heart's content to filter. Hopefully someone more knowledgeable with react/material ui might have some suggestions. Or maybe there is some better place to put the search than in the paper of the autocomplete?

Thanks in advance for any suggestions!

enter image description here

Tyler Dahle
  • 817
  • 1
  • 8
  • 37

1 Answers1

1

I was in almost the exact same situation and happened to come across this answer to a related question that led me to the solution: https://stackoverflow.com/a/59578104/8070411

The problem seems to be returning an element rather than a component to the PaperComponent prop.

Something like this worked for me:

PaperComponent={(paperProps) => (
    <CustomPaperComponent
        {...paperProps}
        customFilterString={customFilterString}
        onClickAway={closeOptionsList}
        onInputChange={handleCustomFilterChange}
    />
)}

...

const CustomPaperComponent = (props) => {  
  return (
    <Paper {...other}>
        <ClickAwayListener onClickAway={props.onClickAway}>
            <div key="click-away-wrapper">
                <Input
                    styleInput={{width: '100%'}}
                    value={props.customFilterString}
                    onChange={props.onInputChange}
                    className="slds-m-horizontal_small slds-m-top_small"
                    iconRight={<InputIcon name="search" category="utility" />}
                />
                {props.children}
            </div>
        </ClickAwayListener>
    </Paper>
  );
};

It's worth noting that I also tried just changing it from an anonymous function but that did not work. It has to be a component.

Did not work:

const renderCustomPaper = (paperProps) => {
    const {children, ...other} = paperProps;
    reutrn (
        <Paper {...other}>
            <ClickAwayListener onClickAway={closeOptionsList}>
                <div key="click-away-wrapper">
                    <Input
                        styleInput={{width: '100%'}}
                        value={customFilterString}
                        onChange={handleCustomFilterChange}
                        className="slds-m-horizontal_small slds-m-top_small"
                        iconRight={<InputIcon name="search" category="utility" />}
                    />
                    {children}
                </div>
            </ClickAwayListener>
        </Paper>
    );
}

...

PaperComponent={renderCustomPaper}
xHergz
  • 11
  • 1
  • 1