ajmajmajma
ajmajmajma

Reputation: 14226

Google places autocomplete in react, don't display full address in places input

I am creating a react component that has a form that uses places to help users fill in their address easier. It's been working great, However I am wondering if there is a way to stop the places input from displaying the entire address, as I would like to use it as a address field (with just the street address, if possible).

Right now I am just hiding it after the user searches and selects inside it initially, but when the user wants to come back and change the field or whatever I need to manage setting it back to the places field (showing it again in place of the address bar) and all the states and focus/click/key down around that (which is possible but i'm wondering if there is an easier way).

So - I could get around this if the google places input just did not show the entire address when I selected one. Perhaps there is a way to intercept the place details result, I can't tell from reading the API docs. Here is my implementation so far :

import React from 'react';
import ShippingAddress from './shippingAddress.jsx';

import _ from 'lodash';

function reducePlaces(memo, item) {
  return {
    ...memo,
    [item.types[0]]: {
      long_name: item.long_name,
      short_name: item.short_name
    }
  };
}

export default class MyCheckoutShipping extends React.Component {
  constructor(props) {
    super(props);

    this.geolocate = this.geolocate.bind(this);
    this.initAutocomplete = this.initAutocomplete.bind(this);
    this.fillInAddress = this.fillInAddress.bind(this);
  }

  componentDidMount() {
    this.initAutocomplete();
  }

  initAutocomplete() {
    // eslint-disable-next-line no-undef
    const autocomplete = new google.maps.places.Autocomplete((this.refs.autoCompletePlaces), {types: ['geocode']});

    autocomplete.addListener('place_changed', this.fillInAddress);
    this.setState({ autocomplete });
  }

  fillInAddress() {
    const place = this.state.autocomplete.getPlace();
    const addressObj = _.reduce(place.address_components, reducePlaces, { street_address: place.name });

    this.props.updateShippingAddress(addressObj);
  }

  geolocate() {
    if (navigator.geolocation) {
      navigator.geolocation.getCurrentPosition(function(position) {
        const geolocation = {
          lat: position.coords.latitude,
          lng: position.coords.longitude
        };

        // eslint-disable-next-line no-undef
        const circle = new google.maps.Circle({
          center: geolocation,
          radius: position.coords.accuracy
        });
        this.state.autocomplete.setBounds(circle.getBounds());
      });
    }
  }

  render() {
    let autoCompleteStyle;

    if (this.props.user.checkout.shipping.address) {
      autoCompleteStyle = { 'display': 'none'};
    }
    return (
  <div className="col-xs-12 My-checkout-shipping">
    <div className="col-sm-12 col-md-8 shipping-information">

      <form>

          <div className="form-group" style={autoCompleteStyle}>
            <input
              type="text"
              className="form-control"
              placeholder="Street Address"
              onFocus={this.geolocate}
              ref="autoCompletePlaces"
              />
          </div>

          <ShippingAddress address={this.props.user.checkout.shipping.address} />


      </form>

    </div>
  </div>
  );
}
}

MyCheckoutShipping.displayName = 'MyCheckoutShipping';

MyCheckoutShipping.propTypes = {
  user: React.PropTypes.object,
  updateShippingAddress: React.PropTypes.func
};

So it just inits on component mount and I have my google api script with key on my index.html - this has all been working great. Does anyone know a way to have the places field only put the street address and not the full address so I do not have to micromanage all the user states? Thanks For reading!

Upvotes: 3

Views: 7878

Answers (2)

Bohdan Salenik
Bohdan Salenik

Reputation: 251

We can easy get all needed data and create custom design for this auto-complete.

import useGoogle from 'react-google-autocomplete/lib/usePlacesAutocompleteService';

const {
    placesService,
    placePredictions,
    getPlacePredictions,
    isPlacePredictionsLoading
  } = useGoogle({
    debounce: 200,
    language: 'en',
    apiKey: 'TOKEN'
  });


<div className="eag-mb-20">
        <input
          type="text"
          placeholder="Enter address"
          onChange={(e) => {
            getPlacePredictions({
              input: e.target.value
            });
          
          }}
        />

        {!isPlacePredictionsLoading &&
          placePredictions.map((item) => (
            <div
              onClick={() => {
                placesService?.getDetails(
                  { placeId: item.place_id },
                  (placeDetails) => console.log(placeDetails) //HERE WILL BE ADDRESS_COMPONENT
                );
              }}>
              {item.description}
            </div>
          ))}
      </div>

enter image description here

Upvotes: 0

Ericgit
Ericgit

Reputation: 7103

after spending alot of time, I figure out this library, which solved my problem. the important this is the type parameter , you should specify you

import Autocomplete from "react-google-autocomplete";

<Autocomplete
          apiKey={apiKey}
          className={clsx(classes.inputText, classes.autocomplete)}
          onPlaceSelected={onPlaceSelectedHandler}
          componentRestrictions={{ country: "us" }}
          options={{
            types: ["geocode", "establishment"],
          }}
        />

if you're using vanilla javascript here is the codesandbox.

Happy Coding

Upvotes: 1

Related Questions