Skip to content

Instantly share code, notes, and snippets.

@jkappers
Created July 24, 2018 15:53
Show Gist options
  • Save jkappers/cf852b9c6649df52a66347d19a7b4ee4 to your computer and use it in GitHub Desktop.
Save jkappers/cf852b9c6649df52a66347d19a7b4ee4 to your computer and use it in GitHub Desktop.
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