Created
July 24, 2018 15:53
-
-
Save jkappers/cf852b9c6649df52a66347d19a7b4ee4 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import React from 'react'; | |
import PropTypes from 'prop-types'; | |
import { withStyles } from '@material-ui/core/styles'; | |
import Input from '@material-ui/core/Input'; | |
import InputLabel from '@material-ui/core/InputLabel'; | |
import FormControl from '@material-ui/core/FormControl'; | |
import Paper from '@material-ui/core/Paper'; | |
import MenuItem from '@material-ui/core/MenuItem'; | |
let autocompleteService = null; | |
let geocodeService = null; | |
class LocationTextField extends React.Component { | |
state = { | |
suggestions: [] | |
} | |
componentDidMount() { | |
if (!autocompleteService) { | |
// eslint-disable-next-line no-undef | |
autocompleteService = new google.maps.places.AutocompleteService(); | |
} | |
if (!geocodeService) { | |
// eslint-disable-next-line no-undef | |
geocodeService = new google.maps.Geocoder(); | |
} | |
} | |
inputRef = null; | |
_renderSuggestions = () => { | |
const { classes } = this.props; | |
const { suggestions } = this.state; | |
if (suggestions.length) { | |
return ( | |
<Paper className={classes.paper} square> | |
{suggestions.map(x => ( | |
<MenuItem key={x.id} component="div" onClick={this._onSelected(x)}> | |
{x.description} | |
</MenuItem> | |
))} | |
</Paper> | |
); | |
} | |
return null; | |
} | |
_onChange = ({ target: { value } }) => { | |
const { types = ['address'] } = this.props; | |
if (value) { | |
autocompleteService.getPlacePredictions( | |
{ | |
componentRestrictions: { | |
country: 'us' | |
}, | |
input: value, | |
types | |
}, | |
(predictions, status) => { | |
if (status === 'OK') { | |
this.setState({ suggestions: predictions }); | |
} | |
} | |
); | |
} else { | |
this.setState({ suggestions: [] }); | |
} | |
} | |
_onSelected = place => () => { | |
const { onPlaceSelected } = this.props; | |
this.inputRef.value = place.description; | |
this.setState({ suggestions: [] }); | |
geocodeService.geocode( | |
{ address: place.description }, | |
(results, status) => { | |
if (status === 'OK' && results && results.length) { | |
onPlaceSelected(results[0]); | |
} | |
} | |
); | |
} | |
render() { | |
const { | |
id, | |
classes, | |
label, | |
fullWidth, | |
margin, | |
onPlaceSelected, | |
...rest | |
} = this.props | |
return ( | |
<div className={classes.container}> | |
<FormControl | |
className={classes.formControl} | |
fullWidth={fullWidth} | |
margin={margin}> | |
<InputLabel htmlFor={id}>{label}</InputLabel> | |
<Input | |
id={id} | |
onChange={this._onChange} | |
inputRef={x => { this.inputRef = x; }} | |
{...rest} | |
/> | |
</FormControl> | |
{this._renderSuggestions()} | |
</div> | |
); | |
} | |
} | |
LocationTextField.propTypes = { | |
id: PropTypes.string.isRequired, | |
classes: PropTypes.object.isRequired, | |
onPlaceSelected: PropTypes.func.isRequired | |
}; | |
const styles = theme => ({ | |
container: { | |
flexGrow: 1, | |
position: 'relative' | |
}, | |
paper: { | |
position: 'absolute', | |
zIndex: 1, | |
marginTop: theme.spacing.unit, | |
left: 0, | |
right: 0 | |
} | |
}); | |
export default withStyles(styles)(LocationTextField); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment