react-autosuggest icon indicating copy to clipboard operation
react-autosuggest copied to clipboard

Allow blur() on component

Open felixhammerl opened this issue 8 years ago • 15 comments

As a developer, I want to call blur() on the component so that I can close the suggestions and remove focus from the input.

There has been a workaround in https://github.com/moroshko/react-autosuggest/issues/158 but this breaks encapsulation as it makes a parent component reach into a child component. Being able to blur() the component would solve this nicely.

felixhammerl avatar May 23 '17 14:05 felixhammerl

Could you describe your use case? Why would you want to blur programatically?

moroshko avatar May 23 '17 15:05 moroshko

I am a user on a mobile device. When I am done writing into the corrections field (which I did by tapping the bottom-right return/submit button), I want to remove focus from the input field so that the keyboard disappears and I have my screen real estate back.

Does that make sense?

felixhammerl avatar May 24 '17 09:05 felixhammerl

which I did by tapping the bottom-right return/submit button

Is this button part of the keyboard? Isn't the input loses focus when you tap this button? Maybe you could attach a screenshot to clarify?

If you would like to blur the input when suggestion is tapped, you can set focusInputOnSuggestionClick={false}.

moroshko avatar May 24 '17 16:05 moroshko

Yes, the button is part of the keyboard.

Here's what I'm able to do:

<form className='...' onSubmit={this.onSubmit}>
  <Autosuggest
    ref={autosuggest => {
      if (autosuggest !== null) {
        this.input = autosuggest.input
      }
    }}
    name='...'
    focusInputOnSuggestionClick={false}
    theme={suggestionsTheme}
    suggestions={suggestions}
    onSuggestionSelected={this.onSuggestionSelected}
    onSuggestionsFetchRequested={this.onSuggestionsFetchRequested}
    onSuggestionsClearRequested={this.onSuggestionsClearRequested}
    getSuggestionValue={i => i}
    renderSuggestion={getSuggestionComponent}
    inputProps={inputProps} />
</form>

The handlers are doing the following:

  onSuggestionsClearRequested () {
    this.setState({ suggestions: [] })
  },

  onSuggestionSelected (e, {suggestion}) {
    ...
    this.onSuggestionsClearRequested()
  },

  onSubmit (event) {
    event.preventDefault()
    this.input.blur()
  },

The user is starting to write a name that's not part of the suggestions list. When they're done, they hit the "submit" button (or enter, if you're on a desktop). At that point, I'd like to blur the input field, which I can do from the form handler. Except that my current solution completely breaks encapsulation.

felixhammerl avatar May 29 '17 12:05 felixhammerl

I also need this functionality. For example:

I added a custom button to the autosuggest container for "Showing all results" that navigates to the search results page. But when clicking this button, the suggestions dropdown stays open. And I would like to hide it.

gl0gl0 avatar Oct 09 '17 21:10 gl0gl0

I'm trying to implement the exact same thing as described by @gl0gl0 ^

kumar303 avatar Mar 09 '18 22:03 kumar303

Any news on this one? I have also created a custom link inside the suggestions container. But because it is not a standard suggestion, the dropdown stays open when i click it. Please advice

oneinchman avatar Sep 04 '18 12:09 oneinchman

Any news on this one? I have also created a custom link inside the suggestions container. But because it is not a standard suggestion, the dropdown stays open when i click it. Please advice

One workaround I found that works is to disable the search input and then re-enable it. You would want to do this as an onClick on one of your custom components:

document.getElementById('searchInput').disabled = true
document.getElementById('searchInput').disabled = false

Update: There is still a problem in safari (iOS) where the iOS keyboard will not go away even if you hit the "done" button on the keyboard.

dylanfpaul avatar Dec 04 '18 14:12 dylanfpaul

@moroshko I think you should definitely allow users to blur programmatically as its such a significant characteristic of the component's state. Should definitely be available in a developer's toolbox when implementing this library.

dylanfpaul avatar Dec 14 '18 19:12 dylanfpaul

While we waiting for blur, I decided to control it through ref.

construct(props) {
    super(props)
    this.autosuggest = React.createRef();
}
render() {
    // ....
    <Autosuggest
        ref={this.autosuggest}
        // .......
    />
}

// ... 
readAllButtonClickHandler = () => {
    // I'm calling onSuggestionClearRequeted and clearing my suggestions there so I can reset suggestions to [] and by that close results screen. 
    this.autosuggest.current.onSuggestionsClearRequested();
    // ... 
}

Kestutis avatar Jan 17 '19 08:01 Kestutis

still no updates ?

LuisSaybe avatar Apr 23 '20 19:04 LuisSaybe

Can we pass the property disabled in inputProps with true or false value?

anmol5varma avatar May 10 '20 12:05 anmol5varma

You can now pass your own ref to the underlying input using inputProps and call blur on it. Does it serve your use case?

aberezkin avatar Jun 02 '20 10:06 aberezkin

You can now pass your own ref to the underlying input using inputProps and call blur on it. Does it serve your use case?

Can you show an example of how to do this? I am having an issue where I need to hide the suggestion container on blur and it's just stuck showing there.

mdodge-ecgrow avatar Dec 28 '20 20:12 mdodge-ecgrow

Can you show an example of how to do this?

I've included an example of what @aberezkin mentioned below; I found this ref documentation useful: https://reactjs.org/docs/refs-and-the-dom.html.

...

class Autocomplete extends Component {
    constructor(props) {
      
      ...

      this.textInput = React.createRef();
      
      ...
      
    }
  
    ...
  
    onSuggestionSelected(event, { suggestion }) {
      this.props.history.push(`/profile/${suggestion.handle}`);
      this.textInput.current.blur();
    }
  
    render() {
      const { hits } = this.props;
      const { value } = this.state;
  
      const inputProps = {
        value,
        onChange: this.onChange,
        onFocus: this.onFocus,
        onBlur: this.onBlur,
        placeholder: "Search",
        ref: this.textInput,
      };
  
      return (
        <AutoSuggest
          suggestions={hits}
          onSuggestionsFetchRequested={this.onSuggestionsFetchRequested}
          onSuggestionsClearRequested={this.onSuggestionsClearRequested}
          getSuggestionValue={this.getSuggestionValue}
          renderSuggestion={this.renderSuggestion}
          inputProps={inputProps}
          onSuggestionSelected={this.onSuggestionSelected}
          shouldRenderSuggestions={this.shouldRenderSuggestions}
          focusInputOnSuggestionClick={false}
        />
      );
    }
}

export default connectAutoComplete(withRouter(Autocomplete));

d4ydr34mzzz avatar Mar 13 '21 01:03 d4ydr34mzzz