ydeshayes / googlePlaceAutocomplete

Wrapper on top of the material-ui AutoComplete component that use google place api
https://ydeshayes.github.io/googlePlaceAutocomplete/
26 stars 12 forks source link

Material UI next version #11

Open ferarnoled opened 6 years ago

ferarnoled commented 6 years ago

Here is a modified version for the new version of Material UI based on this example

Might be useful.

import React from 'react';
import PropTypes from 'prop-types';
import Autosuggest from 'react-autosuggest';
import match from 'autosuggest-highlight/match';
import parse from 'autosuggest-highlight/parse';
import TextField from 'material-ui/TextField';
import Paper from 'material-ui/Paper';
import { MenuItem } from 'material-ui/Menu';
import { withStyles } from 'material-ui/styles';

function renderInput(inputProps) {
  const { classes, autoFocus, value, ref, ...other } = inputProps;

  return (
      <TextField
          autoFocus={autoFocus}
          className={classes.textField}
          value={value}
          inputRef={ref}
          InputProps={{
            classes: {
              input: classes.input,
            },
            ...other,
          }}
      />
  );
}

function renderSuggestion(suggestion, { query, isHighlighted }) {
  const matches = match(suggestion.description, query);
  const parts = parse(suggestion.description, matches);

  return (
      <MenuItem selected={isHighlighted} component="div">
        <div>
          {parts.map((part, index) => {
            return part.highlight ? (
                <span key={String(index)} style={{ fontWeight: 300 }}>
              {part.text}
            </span>
            ) : (
                <strong key={String(index)} style={{ fontWeight: 500 }}>
                  {part.text}
                </strong>
            );
          })}
        </div>
      </MenuItem>
  );
}

function renderSuggestionsContainer(options) {
  const { containerProps, children } = options;

  return (
      <Paper {...containerProps} square>
        {children}
      </Paper>
  );
}

function getSuggestionValue(suggestion) {
  return suggestion.description;
}

const styles = theme => ({
  container: {
    flexGrow: 1,
    position: 'relative',
    height: 200,
  },
  suggestionsContainerOpen: {
    position: 'absolute',
    marginTop: theme.spacing.unit,
    marginBottom: theme.spacing.unit * 3,
    left: 0,
    right: 0,
  },
  suggestion: {
    display: 'block',
  },
  suggestionsList: {
    margin: 0,
    padding: 0,
    listStyleType: 'none',
  },
  textField: {
    width: '100%',
  },
});

class GMapsAutocomplete extends React.Component {

  constructor(props) {
    super(props);
    this.autocompleteService = new google.maps.places.AutocompleteService();
    this.state = {
      value: props.selectedValue ? props.selectedValue : '',
      suggestions: []
    };
  }

  updateDataSource = (data) => {
    if (!data || !data.length) {
      return false;
    }

    if (this.state.suggestions) {
      this.previousData = { ...this.state.suggestions };
    }
    this.setState({
      suggestions: data
    });
  };

  getBounds = () => {
    if (!this.props.bounds || (!this.props.bounds.ne && !this.props.bounds.south)) {
      return undefined;
    }

    if (this.props.bounds.ne && this.props.bounds.sw) {
      return new google.maps.LatLngBounds(this.props.bounds.sw, this.props.bounds.ne);
    }

    return {
      ...this.props.bounds
    };
  };

  getSuggestions = (searchText) => {
    if (!searchText.length || !this.autocompleteService) {
      return false;
    }

    let request = {
      input: searchText,
      location: new google.maps.LatLng(this.props.location.lat, this.props.location.lng),
      radius: this.props.radius,
      types: this.props.types,
      bounds: this.getBounds()
    };

    if (this.props.restrictions) {
      request.componentRestrictions = { ...this.props.restrictions };
    }

    this.autocompleteService.getPlacePredictions(request, data => this.updateDataSource(data));
  }

  handleSuggestionsFetchRequested = ({ value }) => {
    this.getSuggestions(value);
  };

  handleSuggestionsClearRequested = () => {
    this.setState({
      suggestions: []
    });
  };

  handleChange = (event, { newValue }) => {
    this.setState({
      value: newValue,
    });
  };

  handleSuggestionSelected = (event, { suggestion, suggestionValue, suggestionIndex, sectionIndex, method }) => {
    console.log(suggestionValue);
    this.props.onSuggestionSelected(suggestion, suggestionValue);
  }

  render() {
    const { classes, placeholder } = this.props;

    return (
        <Autosuggest
            theme={{
              container: classes.container,
              suggestionsContainerOpen: classes.suggestionsContainerOpen,
              suggestionsList: classes.suggestionsList,
              suggestion: classes.suggestion,
            }}
            renderInputComponent={renderInput}
            suggestions={this.state.suggestions}
            onSuggestionsFetchRequested={this.handleSuggestionsFetchRequested}
            onSuggestionsClearRequested={this.handleSuggestionsClearRequested}
            renderSuggestionsContainer={renderSuggestionsContainer}
            getSuggestionValue={getSuggestionValue}
            renderSuggestion={renderSuggestion}
            onSuggestionSelected={this.handleSuggestionSelected}
            inputProps={{
              autoFocus: true,
              classes,
              placeholder: placeholder,
              value: this.state.value,
              onChange: this.handleChange,
            }}
        />
    );
  }
}

GMapsAutocomplete.propTypes = {
  classes: PropTypes.object.isRequired,
  placeholder: PropTypes.string.isRequired,
  selectedValue: PropTypes.string,
  onSuggestionSelected: PropTypes.func,
  //Google maps parameters,
  location: PropTypes.object,
  radius: PropTypes.number,
  restrictions: PropTypes.shape({
    country: PropTypes.oneOfType([
      PropTypes.string,
      PropTypes.arrayOf(PropTypes.string)
    ])
  })
};

GMapsAutocomplete.defaultProps = {
  location: {lat: 0, lng: 0},
  radius: 0
};

export default withStyles(styles)(GMapsAutocomplete);
ydeshayes commented 6 years ago

Hello!

I will create a branch and test that soon.

Thanks!

robinknox commented 6 years ago

Hi @ydeshayes. First thanks very much for this component. It has been very useful. I've recently upgraded to material UI's next version and am currently using both versions so that I can use autocomplete. Do you have an estimate on when you'll be able to look at updating this to the next version of MUI?

zwhitchcox commented 6 years ago

Any movement on this? I upgraded to @material-ui/core, which is now the standard, and this lists material-ui as a dependency.