├── .gitignore ├── README.md ├── package.json ├── public └── index.html ├── src ├── index.js └── styles.css └── yarn.lock /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | .idea 3 | .DS_Store -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # react-autocomplete-demo 2 | 3 | Demo app for autocomplete widget using React and Elastic Search 4 | 5 | The full write-up is available at https://medium.com/@rcdexta 6 | 7 | ### Setup 8 | 9 | Clone the repository and install the dependencies 10 | 11 | ```bash 12 | $ git clone git@github.com:rcdexta/react-autocomplete-demo.git 13 | $ cd react-autocomplete-demo 14 | $ yarn 15 | ``` 16 | 17 | Start the server by running `yarn start` command 18 | 19 | The UI expects elastic search to be running on 9200 port. 20 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "new", 3 | "version": "1.0.0", 4 | "description": "", 5 | "keywords": [], 6 | "main": "src/index.js", 7 | "dependencies": { 8 | "axios": "0.18.0", 9 | "react": "16.4.2", 10 | "react-autosuggest": "9.4.1", 11 | "react-dom": "16.4.2", 12 | "react-scripts": "1.1.4", 13 | "throttle-debounce": "^2.0.1" 14 | }, 15 | "devDependencies": {}, 16 | "scripts": { 17 | "start": "react-scripts start", 18 | "build": "react-scripts build", 19 | "test": "react-scripts test --env=jsdom", 20 | "eject": "react-scripts eject" 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 12 | 13 | 14 | 23 | React App 24 | 25 | 26 | 27 | 30 |
31 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import ReactDOM from 'react-dom' 3 | import Autosuggest from 'react-autosuggest' 4 | import axios from 'axios' 5 | import { debounce } from 'throttle-debounce' 6 | 7 | import './styles.css' 8 | 9 | class AutoComplete extends React.Component { 10 | state = { 11 | value: '', 12 | suggestions: [] 13 | } 14 | 15 | componentWillMount() { 16 | this.onSuggestionsFetchRequested = debounce( 17 | 500, 18 | this.onSuggestionsFetchRequested 19 | ) 20 | } 21 | 22 | renderSuggestion = suggestion => { 23 | return ( 24 |
25 |
{suggestion.fullName}
26 |
{suggestion.shortCode}
27 |
28 | ) 29 | } 30 | 31 | onChange = (event, { newValue }) => { 32 | this.setState({ value: newValue }) 33 | } 34 | 35 | onSuggestionsFetchRequested = ({ value }) => { 36 | axios 37 | .post('http://localhost:9200/crm_app/customers/_search', { 38 | query: { 39 | multi_match: { 40 | query: value, 41 | fields: ['fullName', 'shortCode'] 42 | } 43 | }, 44 | sort: ['_score', { createdDate: 'desc' }] 45 | }) 46 | .then(res => { 47 | const results = res.data.hits.hits.map(h => h._source) 48 | this.setState({ suggestions: results }) 49 | }) 50 | } 51 | 52 | onSuggestionsClearRequested = () => { 53 | this.setState({ suggestions: [] }) 54 | } 55 | 56 | render() { 57 | const { value, suggestions } = this.state 58 | 59 | const inputProps = { 60 | placeholder: 'customer name or short code', 61 | value, 62 | onChange: this.onChange 63 | } 64 | 65 | return ( 66 |
67 |

AutoComplete Demo

68 | suggestion.fullName} 73 | renderSuggestion={this.renderSuggestion} 74 | inputProps={inputProps} 75 | /> 76 |
77 | ) 78 | } 79 | } 80 | 81 | const rootElement = document.getElementById('root') 82 | ReactDOM.render(, rootElement) 83 | -------------------------------------------------------------------------------- /src/styles.css: -------------------------------------------------------------------------------- 1 | .App { 2 | font-family: sans-serif; 3 | text-align: center; 4 | } 5 | 6 | .react-autosuggest__container { 7 | position: relative; 8 | display: inline-block; 9 | margin-top: -10px; 10 | } 11 | 12 | .react-autosuggest__input { 13 | width: 200px; 14 | height: 16px; 15 | padding: 10px; 16 | font-weight: 300; 17 | font-size: 13px; 18 | border: 1px solid rgba(0, 126, 255, 0.24); 19 | border-radius: 4px; 20 | color: #000; 21 | background-color: #fff; 22 | } 23 | 24 | .react-autosuggest__input::placeholder { 25 | color: #777; 26 | opacity: 1; 27 | } 28 | 29 | .react-autosuggest__input--focused { 30 | outline: none; 31 | } 32 | 33 | .react-autosuggest__input--open { 34 | border-bottom-left-radius: 0; 35 | border-bottom-right-radius: 0; 36 | } 37 | 38 | .react-autosuggest__suggestions-list { 39 | margin: 0; 40 | position: absolute; 41 | padding: 0; 42 | background-color: #fff; 43 | list-style-type: none; 44 | width: 220px; 45 | border: 1px solid #eee; 46 | } 47 | 48 | .react-autosuggest__suggestion { 49 | cursor: pointer; 50 | padding: 10px; 51 | border-bottom: 1px solid #eee; 52 | width: 200px; 53 | white-space: nowrap; 54 | } 55 | 56 | .react-autosuggest__suggestion--highlighted { 57 | background-color: #ddd; 58 | } 59 | 60 | .result { 61 | display: flex; 62 | align-items: center; 63 | justify-content: space-between; 64 | font-size: 80%; 65 | } 66 | 67 | .shortCode { 68 | background-color: #4696ec; 69 | color: #fff; 70 | padding: 4px; 71 | border-radius: 2px; 72 | } 73 | 74 | .highlight { 75 | background-color: yellow; 76 | padding: 4px; 77 | border-radius: 2px; 78 | } --------------------------------------------------------------------------------