├── .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 | }
--------------------------------------------------------------------------------