Search code examples
comboboxreact-widgets

React widgets combobox; how to clear input or prevent selection


I'm using the combobox from React Widgets as a search UI component.

I've put in a custom render item so that when you click a search result in the dropdown, you navigate to the relevant page.

However when you select a result, the name of the selected item goes into the text input, which isn't what a user will expect when they select a search result. I think they'd expect the search term to remain, or perhaps the input to be cleared.

I like the Combobox component and haven't found another UI widget that would do what I want, so I'd like to find a solution.

Is there some way to override the selection behaviour so that clicking a list item doesn't select it? I've tried setting the 'onSelect' property but this doesn't suppress the default selection behaviour, it just adds extra functionality.

Alternatively is there a way to manually set the selection to null? The docs don't seem to show anything. I tried getting the input node's value manually to '' with reactDOM, but the value didn't change. I would guess that the component controls it.

I've wrapped the Combobox in a functional component:

function Search(props) {
...

const onSelect = (value) => {
    const node = ReactDOM.findDOMNode(Search._combobox);
    const input = node.getElementsByTagName('input')[0];
    input.value = '';
}

return (
<Combobox
    ref={(c) => Search._combobox = c}
    onSelect={onSelect}
    textField="name"
    valueField="_id"
/>
);
}

If I set the value prop of the Combobox then it is impossible to type into it.

Any suggestions? Thank you.


Solution

  • The solution I found is to create my own search controls using an input and a button, and hide the native input and button with display: none. "componentDidUpdate" detects when new search results arrive and opens the dropdown to show them.

    There is a manually-added 'show more...' entry at the end of search results. Clicking this increases the search limit for that group. That's the main reason I wanted to avoid showing the clicked result in the text input. The custom input is not affected by the user's selection, it always shows the search term.

    My search component now looks something like this:

    <div className="search">
        <div className="search-controls">
            <Input
                onChange={this.onChangeInput}
                type="text"
            />
            <Button
                onClick={this.toggleOpen}
                title="toggle results"
            >
                <FontAwesomeIcon icon={['fas', 'search']} style={{ 'color': iconColors.default }} size="1x" />
            </Button>
        </div>
        <Combobox
            busy={isSearching}
            data={searchResults}
            onChange={() => {}}
            open={open}
            onSelect={this.onSelect}
            textField="name"
            valueField="_id"
        />
    </div>