Reputation: 14226
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
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>
Upvotes: 0
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