Reassign google map var to new div - google-maps

I'm using react and I have a component that renders a google map view when it mounts.
I'd like to save the google map var globally and when so that when the component is unmounted then remounted I can just reassign the map to a div instead of recreating it. Is this possible?
So Something like this
/** #jsx React.DOM */
var React = require('react');
window.coverage_map = null;
var CoverageMap = React.createClass({
componentDidMount: function(){
if(window.coverage_map == null){
var ele = React.findDOMNode(this.refs.map);
window.coverage_map = new google.maps.Map(ele, {
center: {lat: 37.7833, lng: -122.4167},
mapTypeControlOptions: {
mapTypeIds: [google.maps.MapTypeId.ROADMAP, 'map_style']
}
});
}
else{
//reassign google map
}
},
render(){
// render code
},
})

No - the root element of a map cannot be changed once instantiated.

Related

how do I filter pins on Google Map pulled from a json api endpoint using Vue

I have a map with a number of pins on it, the pins are generated from an endpoint api (json). I want to filter the pins via an input that has a v-modal - the search criteria is already set up and is pulled from the same api.
Even if someone can give some tips as to where in the vue lifecycle the filter should happen, i.e mounted, updated computed ect
Originally I used this article as a reference
https://medium.com/#limichelle21/integrating-google-maps-api-for-multiple-locations-a4329517977a
created() {
axios
.get(
`https://cors-anywhere.herokuapp.com/myEndpoint`
)
.then(response => {
// JSON responses are automatically parsed.
this.allProperties = response.data;
this.markers = this.allProperties.map(function (x) {
return {
lat: parseFloat(x.lat).toFixed(3),
lng: parseFloat(x.lng).toFixed(3),
add: x.dispAddress,
propId: x.property_id,
propPrice: x.outputAskingPrice,
propImg: x.imagePath
};
});
this.allProperties = response.data.map(x => {
x.searchIndex = `${x.sellingStatus} ${x.priceType} ${x.typeNames[0]} ${x.typeNames[1]} ${x.dispAddress}`.toLowerCase();
return x;
});
});
},
mounted: function () {
var _this = this;
function initMap() {
var center = {
lat: 53,
lng: -3
};
var map = new google.maps.Map(document.getElementById("map-canvas"), {
zoom: 10,
center: center
});
var newPin = new google.maps.Marker({
position: center,
map: map
});
}
},
updated() {
var _this = this;
var map = new google.maps.Map(document.getElementById("map-canvas"), {
zoom: 9,
center: new window.google.maps.LatLng(55.961, -3)
});
var infowindow = new google.maps.InfoWindow({});
var newPin;
var count;
for (count = 0; count < _this.markers.length; count++) {
newPin = new google.maps.Marker({
position: new google.maps.LatLng(
_this.markers[count].lat,
_this.markers[count].lng
),
map: map,
icon: "../assets/img/map-pin.png"
});
google.maps.event.addListener(
newPin,
"click",
(function (newPin, count) {
return function () {
infowindow.setContent(` ${_this.markers[count].add} <p> ${_this.markers[count].propPrice}</p><img src="${_this.markers[count].propImg}"><p>`);
infowindow.open(map, newPin);
};
})(newPin, count)
);
}
If you have v-model on an <input> field like mentioned in your question, you are binding the value of this <input> field to a variable probably defined in the data part of your Vue component. The value is always up to date in the model (reactive binding). You can watch this value and then trigger a function which updates Google Maps. Here is an example:
Vue.component('demo', {
data () {
return {
inputField: ''
};
},
created () {
console.log('Component script loaded, HTML not yet ready, load the data from your backend. Use a flag like isLoading or similar to indicate when the data is ready to enable input.');
},
mounted () {
console.log('Component mounted, HTML rendered, load Google Maps');
},
watch: {
inputField (newValue) {
console.log(`inputField changed to ${newValue}. Trigger here a method which update Google Maps. Make sure to debounce the input here, so that it does not trigger a Google Maps update too often.`);
}
},
template: `
<div>
<input type="text" v-model="inputField" placeholder="Lookup place">
</div>`
});
new Vue({ el: '#vue-demo-container' });
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="vue-demo-container">
<demo></demo>
</div>

How do I do bind to property title of a marker from google maps with vuejs?

I am working with api google maps now I am development with vuejs now exist the posibility from bind a property to the property title from markers, for example
this is my component on vuejs
Vue.component('root-map',{
template: `
<div id="sidebar_builder"
style="width: 100%; height: 600px;">
</div>
`,
data: function(){
return {
map:null,
marker:{
title: 'hello'
}
}
},
mounted: function () {
this.$nextTick(function () {
var myLatlng = new google.maps.LatLng(-25.363882,131.044922);
var mapOptions = {
zoom: 4,
center: myLatlng
};
this.map = new google.maps.Map(document.getElementById('sidebar_builder'),mapOptions);
var marker_icon= new google.maps.Marker({
position: myLatlng,
title: this.marker.title}); // the most important part
marker_icon.setMap(this.map);
});
}
});
Now when I want change the property markers.title='I change' and happend nothing, the markers on the maps keep 'hello', could you please how do I do it ? If can do it without use method native from api google maps thanks!!
you can use watch
watch: {
marker() {
this.reDrawMarkers()
}
}
more info vue watcher https://v2.vuejs.org/v2/guide/computed.html#Watchers
if you dont know how to redraw markers also you can look google documentation
https://developers.google.com/maps/documentation/javascript/examples/marker-remove

Google places autocomplete inside a react component

I am trying to build a google map component and everything is working fine with the Google Maps API v3 but not the Autocomplete functionality.
This is the code I am using:
The Google Map component
import React, {Component} from 'react';
import ReactDOM from 'react-dom';
const Marker = React.createClass({
componentDidMount: function() {
console.log("Marker on mount");
},
render: function() {
return false;
}
});
export default Marker;
const GoogleMap = React.createClass({
componentDidMount: function() {
var mapOptions = {
center: this.createLatLng(this.props.center),
zoom: this.props.zoom || 14
};
var map = new google.maps.Map(ReactDOM.findDOMNode(this), mapOptions);
//Render all the markers (children of this component)
React.Children.map(this.props.children, (child) => {
var markerOptions = {
position: this.createLatLng(child.props.position),
title: child.props.title || "",
animation: google.maps.Animation.DROP,
icon: child.props.icon || null,
map: map,
autocomplete:new google.maps.places.AutocompleteService()
};
var marker = new google.maps.Marker(markerOptions);
if(child.props.info) {
var infowindow = new google.maps.InfoWindow({
content: child.props.info
});
marker.addListener('click', function() {
infowindow.open(map, marker);
});
}
});
var input = this.refs.search;
map.controls[google.maps.ControlPosition.TOP_LEFT].push(input);
var autocomplete = new google.maps.places.Autocomplete(input);
autocomplete.bindTo('bounds', map);
this.setState({map});
},
createLatLng: function(element) {
return new google.maps.LatLng(element.lat, element.lng);
},
render: function() {
return (
<div className="map">
<input ref="search"/>
</div>
)
}
});
export default GoogleMap;
And this is where I call the component
import React, {Component} from 'react';
import GoogleMap from './GoogleMap';
import Marker from './GoogleMap';
import Geosuggest from 'react-geosuggest';
class DoodlesMap extends Component {
state = {
center: null,
marker: null,
directions: null
};
componentWillMount() {
navigator.geolocation.getCurrentPosition((position) => {
this.setState({
center: {
lat: position.coords.latitude,
lng: position.coords.longitude
},
marker: {
position: {
lat: position.coords.latitude,
lng: position.coords.longitude
}
}
});
});
}
renderYouAreHereMarker() {
return (
<Marker
position={this.state.center}
icon="../../img/you-are-here.png"
/>
)
}
render() {
if (!this.state.center) {
return (
<div>Loading...</div>
)
}
return (
<div>
<GoogleMap
center={this.state.center}
zoom={15}
>
{this.renderYouAreHereMarker()}
<Marker
position={{lat: 41.317334, lng: -72.922989}}
icon="../../img/marker.png"
info="Hola"
/>
<Marker
position={{lat: 41.309848, lng: -72.938234}}
icon="../../img/marker.png"
info="Epi"
/>
</GoogleMap>
</div>
);
}
}
export default DoodlesMap;
I do not receive any console error. The map is displayed correctly (with the markers as children) the input also, but does not make the autocomplete.
Thank you in advance!!
I figure it out, and was very simple issue.
The thing was that I did not "enable" the places API in my google developer console.
Once I did this everything worked fine!!
It took me quite some time to get the google-places-autocomplete feature working nicely with a React Component. I did however manage to figure it out and wrote a short tutorial on it over here.
Medium Tutorial Post!
TL;DR of tutorial: You have to use a library called react-scripts to render the google-maps-places library after the component has mounted. Most of the time the reason that the autocomplete doesn't work is because the library did not load properly.

Google maps centered load failure

Well I'm having this problem, load the map once and everything works perfect. The second time or once update the map does not load ok, but not centered load when navigating on you can see the marks that are made but is deformed or simply lost.
I have tried several ways to solve this problem, first and most common I found was to use google.maps.event.trigger(map 'resize') but it did not work then and logic, try that whenever loading map is executed, create a new map, with the same data and focused but neither worked for me. It may be also the way I use the map. I am using the plugin of the camera in my application, the user takes a photo and this should detect where I draw the picture and display the map. Each time the view is opened, the plug of the camera, in the process of taking and show the picture is where I call the appropriate functions to load the map and this has me a bit tricky immediately loaded I have a good time locked in this problem, I found solutions serve me but only for the browser, the device does not work. I am using ionic framework and plugins cordova.
Controller :
.controller("CamaraCtrl", function($scope,$rootScope, Camera,$cordovaGeolocation,$state,$location,$ionicSideMenuDelegate) {
var posOptions = {timeout: 10000, enableHighAccuracy: false};
$cordovaGeolocation
.getCurrentPosition(posOptions)
.then(function (position) {
var latitud_actual = position.coords.latitude
var longitud_actual = position.coords.longitude
$scope.latitud = latitud_actual;
$scope.longitud = longitud_actual;
//$scope.map = new google.maps.Map(document.getElementById("mapa_ubicacion"), mapOptions);
}, function(err) {
// error
});
function initialize() {
var mapOptions = {
center: new google.maps.LatLng($scope.latitud, $scope.longitud),
zoom: 15,
mapTypeId: google.maps.MapTypeId.ROADMAP,
scrollwheel: false
};
var map = new google.maps.Map(document.getElementById("map"),
mapOptions);
$scope.setMarker(map, new google.maps.LatLng($scope.latitud, $scope.longitud), 'Yo', '');
$scope.map = map;
}
$scope.setMarker = function(map, position, title, content) {
var marker;
var markerOptions = {
position: position,
map: map,
title: title
};
marker = new google.maps.Marker(markerOptions);
google.maps.event.addListener(marker, 'click', function () {
// close window if not undefined
if (infoWindow !== void 0) {
infoWindow.close();
}
// create new window
var infoWindowOptions = {
content: content
};
infoWindow = new google.maps.InfoWindow(infoWindowOptions);
infoWindow.open(map, marker);
});
}
$scope.mostrar_form = false;
$scope.mostrar_boton_view = false;
$scope.getPhoto = function() {
Camera.getPicture().then(function(imageURI) {
console.log(imageURI);
$scope.lastPhoto = imageURI;
$scope.mostrar_form = true;
$scope.mostrar_boton_view = false;
google.maps.event.addDomListener(window, 'load', initialize);
initialize();
}, function() {
$scope.mostrar_boton_view = true;
}, {
quality: 75,
targetWidth: 320,
targetHeight: 320,
saveToPhotoAlbum: false
});
};
$scope.getPhoto();
})
The only solution I found was to create a function that executes the map again. It should not be as optimal but at least it solved my problem.
$scope.centrar = function(){
var mapOptions = {
center: new google.maps.LatLng($scope.latitud, $scope.longitud),
zoom: 15,
mapTypeId: google.maps.MapTypeId.ROADMAP,
scrollwheel: false
};
var map = new google.maps.Map(document.getElementById("map"),
mapOptions);
$scope.setMarker(map, new google.maps.LatLng($scope.latitud, $scope.longitud), 'Yo', '');
$scope.map = map;
}

Google Map Api Marker not showing with Reactjs

I am trying to display a google map with a marker. I am using React.js. The map displays in the correct location, but the marker does not show and I get multiple 'object is not extensible' error in the browser console
The code looks like this
/** #jsx React.DOM */
var Map = React.createClass({
initialize: function() {
var lat = parseFloat(this.props.lat);
var lng = parseFloat(this.props.lon);
var myPosition = new google.maps.LatLng(lat,lng);
var mapOptions = {
center: myPosition,
zoom: 8
};
var map = new google.maps.Map(this.getDOMNode(), mapOptions);
var marker = new google.maps.Marker({position: myPosition, title: 'Hi', map: map});
},
componentDidMount: function(){
this.initialize();
},
render:function(){
return <div className="map"/>
}
});
detailed errors from console:
Uncaught TypeError: Can't add property k, object is not extensible VM3577:92
Uncaught TypeError: Can't add property onerror, object is not extensible main.js:3
Uncaught TypeError: Can't add property k, object is not extensible VM3577:92
Uncaught TypeError: Cannot read property 'style' of undefined VM3577:69
Uncaught TypeError: Can't add property onerror, object is not extensible
Craig Savolainen has a nice explanation on using Google Maps as a React Component here, the gist for the example is here. I acomplished the marker render with the following code:
var ExampleGoogleMap = React.createClass({
getDefaultProps: function () {
return {
initialZoom: 8,
mapCenterLat: 43.6425569,
mapCenterLng: -79.4073126,
};
},
componentDidMount: function (rootNode) {
var mapOptions = {
center: this.mapCenterLatLng(),
zoom: this.props.initialZoom
},
map = new google.maps.Map(document.getElementById('react-valuation-map'), mapOptions);
var marker = new google.maps.Marker({position: this.mapCenterLatLng(), title: 'Hi', map: map});
this.setState({map: map});
},
mapCenterLatLng: function () {
var props = this.props;
return new google.maps.LatLng(props.mapCenterLat, props.mapCenterLng);
},
render: function () {
return (
<div className='map-gic'></div>
);
}
});
Working jsFiddle