Add support for places/Autocomplete service#768
Add support for places/Autocomplete service#768gergely-ujvari wants to merge 2 commits intotomchentw:masterfrom
Conversation
27c324a to
44950ac
Compare
44950ac to
806b155
Compare
|
Cool! Can anybody merge this into the project? |
|
I agree that we need this. I really want Autocomplete. In fact, I started using this library to rewrite an app I had previously written in react that is primarily focused around the Autocomplete control. However, I'm not sure sure that this solution is even working. I've copied the code locally and I'm getting errors. It also seems that you're creating an I would love for this to work. Perhaps I'm missing something. |
|
I wrote the following in my local project. Granted, I'm mostly unfamiliar with the structure of this project and I've very much just started playing around with React, but it seems to work for me: /* global google */
import canUseDOM from 'can-use-dom';
import invariant from 'invariant';
import _ from 'lodash';
import PropTypes from 'prop-types';
import React, { PureComponent } from 'react';
import ReactDOM from 'react-dom';
import {
construct,
componentDidMount,
componentDidUpdate,
componentWillUnmount,
} from 'react-google-maps/lib/utils/MapChildHelper';
import { MAP } from 'react-google-maps/lib/constants';
const AUTO_COMPLETE = '__SECRET_AUTO_COMPLETE_DO_NOT_USE_OR_YOU_WILL_BE_FIRED';
/**
* A wrapper around `google.maps.places.Autocomplete` on the map
*
* @see https://developers.google.com/maps/documentation/javascript/3.exp/reference#Autocomplete
*/
export class Autocomplete extends PureComponent {
static propTypes = {
/**
* Where to put `<Autocomplete>` inside a `<GoogleMap>`
*
* @example google.maps.ControlPosition.TOP_LEFT
* @type number
*/
controlPosition: PropTypes.number,
/**
* @type LatLngBounds|LatLngBoundsLiteral
*/
defaultBounds: PropTypes.any,
/**
* @type ComponentRestrictions
*/
defaultComponentRestrictions: PropTypes.any,
/**
* @type AutocompleteOptions
*/
defaultOptions: PropTypes.any,
/**
* @type LatLngBounds|LatLngBoundsLiteral
*/
bounds: PropTypes.any,
/**
* @type ComponentRestrictions
*/
componentRestrictions: PropTypes.any,
/**
* @type AutocompleteOptions
*/
options: PropTypes.any,
/**
* function
*/
onPlaceChanged: PropTypes.func,
}
static contextTypes = {
[MAP]: PropTypes.object,
}
state = {
[AUTO_COMPLETE]: null,
}
componentWillMount() {
if (!canUseDOM || this.containerElement) {
return;
}
invariant(google.maps.places, 'Did you include "libraries=places" in the URL?');
this.containerElement = document.createElement('div');
this.handleRenderChildToContainerElement();
if (React.version.match(/^16/)) {
return;
}
this.handleInitializeAutocomplete();
}
componentDidMount() {
let autocomplete = this.state[AUTO_COMPLETE];
if (React.version.match(/^16/)) {
autocomplete = this.handleInitializeAutocomplete();
}
componentDidMount(this, autocomplete, eventMap);
this.handleMountAtControlPosition();
}
componentWillUpdate(nextProp) {
if (this.props.controlPosition !== nextProp.controlPosition) {
this.handleUnmountAtControlPosition();
}
}
componentDidUpdate(prevProps) {
componentDidUpdate(this, this.state[AUTO_COMPLETE], eventMap, updaterMap, prevProps);
if (this.props.children !== prevProps.children) {
this.handleRenderChildToContainerElement();
}
if (this.props.controlPosition !== prevProps.controlPosition) {
this.handleMountAtControlPosition();
}
}
componentWillUnmount() {
componentWillUnmount(this);
this.handleUnmountAtControlPosition();
if (React.version.match(/^16/)) {
return;
}
if (this.containerElement) {
ReactDOM.unmountComponentAtNode(this.containerElement);
this.containerElement = null;
}
}
handleInitializeAutocomplete() {
/*
* @see https://developers.google.com/maps/documentation/javascript/3.exp/reference#Autocomplete
*/
const autocomplete = new google.maps.places.Autocomplete(this.containerElement.querySelector('input'),
this.props.options);
construct(Autocomplete.propTypes, updaterMap, this.props, autocomplete);
this.setState({
[AUTO_COMPLETE]: autocomplete,
});
return autocomplete;
}
handleRenderChildToContainerElement() {
if (React.version.match(/^16/)) {
return;
}
ReactDOM.unstable_renderSubtreeIntoContainer(this, React.Children.only(this.props.children), this.containerElement);
}
handleMountAtControlPosition() {
if (isValidControlPosition(this.props.controlPosition)) {
this.mountControlIndex = -1 + this.context[MAP].controls[this.props.controlPosition].push(
this.containerElement.firstChild);
}
}
handleUnmountAtControlPosition() {
if (isValidControlPosition(this.props.controlPosition)) {
const child = this.context[MAP].controls[this.props.controlPosition].removeAt(this.mountControlIndex);
if (child !== undefined) {
this.containerElement.appendChild(child);
}
}
}
render() {
if (React.version.match(/^16/)) {
return ReactDOM.createPortal(React.Children.only(this.props.children), this.containerElement);
}
return false;
}
/**
* Returns the bounds to which query predictions are biased.
* @type LatLngBounds
* @public
*/
getBounds() {
return this.state[AUTO_COMPLETE].getBounds();
}
/**
* Returns the query selected by the user, or `null` if no place has been found yet, to be used with `place_changed` event.
* @type PlaceResultnullplaces_changed
* @public
*/
getPlace() {
return this.state[AUTO_COMPLETE].getPlace();
}
}
export default Autocomplete;
const isValidControlPosition = _.isNumber;
const eventMap = {
onPlaceChanged: 'place_changed'
};
const updaterMap = {
bounds(instance, bounds) {
instance.setBounds(bounds);
}
};I might have missed somethings, but it's based almost completely on the existing |
|
I'll merge this over the weekend, let me just test this out locally first. |
|
This is great we'll merge this once I sync with Tom and we can push it to the upstream |
|
Hello @oshalygin , this feature is so important , i wish if you could push it to public soon as possible . any update about this feature please? |
|
It is nice to have same way for StandaloneSearchBox as well. |
|
Will this feature be incorporated into the project? |
|
Please add this feature. Country restriction is very important. It will be great if incorporated into StandaloneSearchBox. |
Hi, Failed to compile. ./node_modules/react-google-maps/lib/components/places/Autocomplete.js |
|
@tanmoy-ono What are you using to compile? This looks more like your project setup rather than an issue with the code itself. |
|
@neocotic Following code I am using for StandaloneSearchBox, tried same way. |
|
Guys do you have plan to merge this anytime soon? |
|
@bidva this lib is unmaintained for a year, please consider new replacement |
Thanks for your suggestion but as much as I see this package doesn't support the single search box('Autocomplete'). Do you have a plan to add any time soon? |
|
@ gergely-ujvari @bidva issues and pull requests are welcome https://github.com/JustFly1984/react-google-maps-api/issues |
Introduces a wrapper component around Autocomplete service
Example usage snippet: