I am referring to this tutorial for simple react autocomplete https://www.digitalocean.com/community/tutorials/react-react-autocomplete
But I have a slightly different requirement. Instead of typing something on the input
field, I want all the suggestions to come up on clicking the input
field. I am basically implementing a requirement where on clicking the input
field, it should show user what are the available options.
Here is my sandbox https://codesandbox.io/s/distracted-easley-wdm5x
Specifically in the Autocomplete.jsx
file (as mentioned below)
import React, { Component, Fragment } from "react"; import PropTypes from "prop-types"; class Autocomplete extends Component { static propTypes = { suggestions: PropTypes.instanceOf(Array) }; static defaultProps = { suggestions: [] }; constructor(props) { super(props); this.state = { // The active selection's index activeSuggestion: 0, // The suggestions that match the user's input filteredSuggestions: [], // Whether or not the suggestion list is shown showSuggestions: false, // What the user has entered userInput: "" }; } onChange = (e) => { const { suggestions } = this.props; const userInput = e.currentTarget.value; // Filter our suggestions that don't contain the user's input const filteredSuggestions = suggestions.filter( (suggestion) => suggestion.toLowerCase().indexOf(userInput.toLowerCase()) > -1 ); this.setState({ activeSuggestion: 0, filteredSuggestions, showSuggestions: true, userInput: e.currentTarget.value }); }; onClick = (e) => { this.setState({ activeSuggestion: 0, filteredSuggestions: [], showSuggestions: false, userInput: e.currentTarget.innerText }); }; onClick2 = (e) => { console.log("text check", e.currentTarget.innerText); if (e.currentTarget.innerText === "") { const { suggestions } = this.props; const filteredSuggestions = suggestions; this.setState({ activeSuggestion: 0, filteredSuggestions, showSuggestions: true, userInput: e.currentTarget.innerText }); } }; onKeyDown = (e) => { const { activeSuggestion, filteredSuggestions } = this.state; // User pressed the enter key if (e.keyCode === 13) { this.setState({ activeSuggestion: 0, showSuggestions: false, userInput: filteredSuggestions[activeSuggestion] }); } // User pressed the up arrow else if (e.keyCode === 38) { if (activeSuggestion === 0) { return; } this.setState({ activeSuggestion: activeSuggestion - 1 }); } // User pressed the down arrow else if (e.keyCode === 40) { if (activeSuggestion - 1 === filteredSuggestions.length) { return; } this.setState({ activeSuggestion: activeSuggestion + 1 }); } }; render() { const { onChange, onClick2, onClick, onKeyDown, state: { activeSuggestion, filteredSuggestions, showSuggestions, userInput } } = this; let suggestionsListComponent; if (showSuggestions) { if (filteredSuggestions.length) { suggestionsListComponent = ( <ul className="suggestions"> {filteredSuggestions.map((suggestion, index) => { let className; // Flag the active suggestion with a class if (index === activeSuggestion) { className = "suggestion-active"; } return ( <li className={className} key={suggestion} onClick={onClick}> {suggestion} </li> ); })} </ul> ); } else { suggestionsListComponent = ( <div className="no-suggestions"> <em>No suggestions, you're on your own!</em> </div> ); } } return ( <Fragment> <input type="text" onChange={onChange} onKeyDown={onKeyDown} value={userInput} onClick={onClick2} /> {suggestionsListComponent} </Fragment> ); } } export default Autocomplete;
In the input
element in return section,
<input type="text" onChange={onChange} onKeyDown={onKeyDown} value={userInput} onClick={onClick2} />
I have added a onClick
functionality that calls the function onClick2
.
onClick2 = (e) => { console.log("text check", e.currentTarget.innerText); if (e.currentTarget.innerText === "") { const { suggestions } = this.props; const filteredSuggestions = suggestions; this.setState({ activeSuggestion: 0, filteredSuggestions, showSuggestions: true, userInput: e.currentTarget.innerText }); } };
My function simply returns all the suggestions back on clicking the input
field. I am able to select items from suggestions and it gets put in the input
field. But when I click on the input field again, the value disappears.
I want this autocomplete suggestion to only show once on clicking the empty input
field and after selecting the item from list, I should be able to edit the value further.
What am I doing wrong?
Advertisement
Answer
Input values are not stored into innerText, but in value prop.
Look at this:
onClick2 = (e) => { console.log("text check", e.currentTarget.innerText); if (e.currentTarget.value === "") { const { suggestions } = this.props; const filteredSuggestions = suggestions; this.setState({ activeSuggestion: 0, filteredSuggestions, showSuggestions: true, userInput: e.currentTarget.value }); } };
This should solve your problem