Vue-google-map autocomplete two way binding not working - javascript

I am using vue-google-maps, and I have implemented the plugin and it works flawlessly, but there is a small problem ( or maybe I am not able to do it correctly ). When I implemented the autocomplete functionality it works one way. I enter the address and the map points me to the selected place but when I drag the pointer it doesn't update the address in the search field.
I am using Vuejs 2
and vue-google-maps
This is what I am doing:
<template>
<div>
<label>
AutoComplete
<GmapAutocomplete :position.sync="markers[0].position" #keyup.enter="usePlace" #place_changed="setPlace">
</GmapAutocomplete>
<button #click="usePlace">Add</button>
</label>
<br/>
<gmap-map
:center="center"
:zoom="7"
map-type-id="terrain"
style="width: 100%; height: 500px"
>
<gmap-marker
#dragend="updateMaker"
:key="index"
v-for="(m, index) in markers"
:position="m.position"
:clickable="true"
:draggable="true"
#click="center=m.position"
></gmap-marker>
</gmap-map>
</div>
</template>
<script>
export default {
data() {
return {
center: {lat: 10.0, lng: 10.0},
markers: [{
position: {lat: 11.0, lng: 11.0}
}],
place: null,
}
},
description: 'Autocomplete Example (#164)',
methods: {
setPlace(place) {
this.place = place
},
setDescription(description) {
this.description = description;
},
usePlace(place) {
if (this.place) {
var newPostion = {
lat: this.place.geometry.location.lat(),
lng: this.place.geometry.location.lng(),
};
this.center = newPostion;
this.markers[0].position = newPostion;
this.place = null;
}
},
updateMaker: function(event) {
console.log('updateMaker, ', event.latLng.lat());
this.markers[0].position = {
lat: event.latLng.lat(),
lng: event.latLng.lng(),
}
},
}
}
</script>

I'm not sure this is supported. You might have to implement this by yourself.
In your updateMaker() method, you could use google.maps.Geocoder() to find the address name yourself:
updateMaker: function(event) {
const geocoder = new google.maps.Geocoder()
geocoder.geocode({ 'latLng': event.latLng }, (result, status) => {
if (status === google.maps.GeocoderStatus.OK) {
// set the input field value with address:
console.log(result[0].formatted_address)
}
})
}

add 'ref' to your auto complete component like :
<GmapAutocomplete ref="gmapAutocomplete" :position.sync="markers[0].position" #keyup.enter="usePlace" #place_changed="setPlace">
</GmapAutocomplete>
Change updateMarker function to this:
updateMaker: function(event) {
console.log('updateMaker, ', event.latLng.lat());
this.markers[0].position = {
lat: event.latLng.lat(),
lng: event.latLng.lng(),
}
const geocoder = new google.maps.Geocoder()
geocoder.geocode({ 'latLng': event.latLng }, (result, status) => {
if (status === google.maps.GeocoderStatus.OK) {
this.$refs.gmapAutocomplete.$refs.input.value = result[0].formatted_address
}
})
},

Related

Map: Expected mapDiv of type Element but was passed undefined - google maps

I have a map inside a div with a reference #mapa
When i want to trace a route in the map the map refreshes. I want to not refresh the map i have the following code:
<div style="height: 500px; width: auto;" #mapa>
<google-map height="500px" width="100%" [zoom]="zoom" [center]="center" [options]="options" (mapClick)="click($event)">
<map-marker #markerElem *ngFor="let marker of markers" [position]="marker.position" [label]="marker.label" [title]="marker.title" [options]="marker.options" (mapClick)="openInfo(markerElem, marker.info)" (mapDragend)="moveMap($event)">
</map-marker>
<map-info-window>{{ infoContent }}</map-info-window>
</google-map>
</div>
If i remove the div with the reference #mapa and i put it the reference into the <google-map> tag i got the title error and show the map without routes.
trazarRutaMapa() {
const directionsService = new google.maps.DirectionsService;
const directionsDisplay = new google.maps.DirectionsRenderer;
const map = new google.maps.Map(this.mapa.nativeElement, {
zoom: 7,
center: {
lat: this.markers[0].position.lat,
lng: this.markers[0].position.lng
}
});
directionsDisplay.setMap(map);
directionsDisplay.setOptions({
suppressMarkers: false,
draggable: true,
markerOptions: {
icon: 'https://developers.google.com/maps/documentation/javascript/examples/full/images/beachflag.png'
}
});
directionsService.route({
origin: {
lat: this.markers[0].position.lat,
lng: this.markers[0].position.lng
},
destination: {
lat: this.markers[1].position.lat,
lng: this.markers[1].position.lng
},
travelMode: google.maps.TravelMode.DRIVING,
}, (response, status) => {
if (status === google.maps.DirectionsStatus.OK) {
console.log('ESTATUS OKEY');
directionsDisplay.setDirections(response);
} else {
window.alert("Fallo el estatus" + status);
}
});
}
As far as I can see you can accomplish your goal just using the #angular/google-maps official module.
Your HTML will become something like this
<google-map [options]="options">
<map-marker *ngFor="let some of somearray" [icon]="...", [label]="...", [position]="..."></map-marker>
<map-directions-renderer [directions]="..." [options]="..."></map-directions-renderer>
</google-map>
and your trazarRoutaMapa() method will become something like this:
trazarRoutaMapa(): void {
const directionsService = new google.maps.DirectionsService; // better if injected from constructor
const request: google.maps.DirectionsRequest = {
destination: {
lat: this.markers[0].position.lat,
lng: this.markers[0].position.lng
},
origin: {
lat: this.markers[1].position.lat,
lng: this.markers[1].position.lng
},
travelMode: google.maps.TravelMode.DRIVING
};
return directionsService.route(
request,
(response, status) => {
if (status === google.maps.DirectionsStatus.OK) {
console.log('ESTATUS OKEY');
directionsDisplay.setDirections(response);
} else {
window.alert("Fallo el estatus" + status);
}
});
}
Disclaimer: I didn't test the code, just created on notepad copy/pasting :)

Handling Google Geocode Callback Results to Vue JS Model

Here's my issue... I have two selections for my user, use current location, or use a zip code. When the user selects a zip code I make a call to the Google geocode API and retrieve the central point for that zip code. I want to be able to put these coordinates into my Vue model and then execute a method within Vue called refresh which retrieves some data from my database and calls a function that sets up the map with markers and bounds. Since the callback function is decoupled from the model, I cannot seem to set the Vue properties, nor can I call the method. How do I handle the callback?
Please note that the refresh method works properly when using the selection for current location.
getLocation is called when the user selects "Current Location"
checkZip is called when the user selects "Use Zip Code"
<script>
var app = new Vue({
el: '#app-content',
data: {
locationType: "CurrentLocation",
lat: "",
lng: "",
radiusInMiles: 10,
filters: [],
zipCode: "",
geoError: "",
error: "",
results: []
},
methods: {
getLocation: function () {
this.zipCode = "";
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(this.storeLocation, this.locationError);
} else {
this.locationType = "ZipLocation";
console.log("Geolocation does not appear to be supported by the browser.");
this.geoError = "Unable to obtain location. Please make sure location services are turned on and try again.";
}
},
storeLocation: function (position) {
this.lat = position.coords.latitude;
this.lng = position.coords.longitude;
this.refresh();
},
locationError: function (err) {
this.locationType = "ZipLocation";
this.results = [];
console.warn(err);
this.geoError = "Unable to obtain location. Please make sure location services are turned on and try again.";
},
refresh: function () {
if (!(this.lat && this.lng && this.radiusInMiles && this.filters)) {
console.log("Location and filters are undefined.");
}
else {
//https://github.com/axios/axios
axios
.post('xyxyxyxyx', {
lat: this.lat,
lng: this.lng,
radiusInMiles: this.radiusInMiles,
filters: this.filters.toString()
})
.then(response => {
this.results = response.data.d;
//Send to map function...
loadMap(this.lat, this.lng, this.results);
})
.catch (error => console.log(error))
}
},
checkZip: function () {
if (this.zipCode.length == 5 && !isNaN(this.zipCode)) {
var geocoder = new google.maps.Geocoder();
geocoder.geocode({ 'address': 'zipcode ' + this.zipCode }, function (results, status) {
if (status == google.maps.GeocoderStatus.OK) {
//Here's my issue...
//How do I store to the model and then call this.refresh
this.lat = results[0].geometry.location.lat();
this.lng = results[0].geometry.location.lng();
this.refresh();
} else {
console.error("Request failed.")
}
});
}
}
}
})
</script>
I was able to get this to work by copying the Vue model into a variable (self).
How can I update a Vue app's or component's property in a promise call back?
checkZip: function () {
if (this.zipCode.length == 5 && !isNaN(this.zipCode)) {
var self = this;
var geocoder = new google.maps.Geocoder();
geocoder.geocode({ 'address': 'zipcode ' + this.zipCode }, function (results, status) {
if (status == google.maps.GeocoderStatus.OK) {
self.lat = results[0].geometry.location.lat();
self.lng = results[0].geometry.location.lng();
self.refresh();
} else {
console.error("Request failed.")
}
});
}
}

Google Map Address Search With GPS Location

I try to do a map with seach address/find location and take gps coordinate/find location. I can make to work one by one but I couldn't work them together in one map. These are my google map functions :
Address Search
// When the search form is submitted
jQuery('.js-form-search').on('submit', function(){
GMaps.geocode({
address: jQuery('.js-search-address').val().trim(),
callback: function ($results, $status) {
if (($status === 'OK') && $results) {
var $latlng = $results[0].geometry.location;
$mapSearch.removeMarkers();
$mapSearch.addMarker({ lat: $latlng.lat(), lng: $latlng.lng(), title: 'Adres : '+jQuery('.js-search-address').val()});
$mapSearch.fitBounds($results[0].geometry.viewport);
document.getElementById("lat").value = $latlng.lat();
document.getElementById("long").value = $latlng.lng();
} else {
alert('Adres Bilgisi Bulunamadı ! ');
}
}
});
return false;
});
GPS Location finder
// When the GPS button clicked
jQuery('.js-form-gps').on('submit', function(){
GMaps.geolocate({
success: function(position) {
$mapSearch.setCenter(position.coords.latitude, position.coords.longitude);
$mapSearch.addMarker({
lat: position.coords.latitude,
lng: position.coords.longitude,
animation: google.maps.Animation.DROP,
title: 'GeoLocation',
infoWindow: {
content: '<div class="text-success"><i class="fa fa-map-marker"></i> <strong>Your location!</strong></div>'
}
});
},
error: function(error) {
alert('Geolocation failed: ' + error.message);
},
not_supported: function() {
alert("Your browser does not support geolocation");
},
always: function() {
// Message when geolocation succeed
}
});
return false;
});
};
How can I entegrate two of them ?
Thanks,

angularJS find the location/place name using angular google map

I want to find the location name which user select on map.
Currently I am getting latitude and longitude both.
But unable to get the location name.
I am using angularJS and angular-google-maps 2.1.5.
Here is the html.
<ui-gmap-google-map center="map.center" zoom="map.zoom" draggable="true" options="options" events="map.events">
</ui-gmap-google-map>
JS :
$scope.map = {
center: {
latitude: 21.0000,
longitude: 78.0000
},
zoom: 4,
events: {
click: function(mapModel, eventName, originalEventArgs,ok) {
var e = originalEventArgs[0];
objOneDevice.dev_latitude = e.latLng.lat();
objOneDevice.dev_longitude = e.latLng.lng();
$scope.templatedInfoWindow.show = true;
}
}
};
$scope.options = {
scrollwheel: true
};
Anything is appreciated.
Here what I have done using Reverse geocoding.
$scope.map = {
center: {
latitude: 21.0000,
longitude: 78.0000
},
zoom: 4,
events: {
click: function(mapModel, eventName, originalEventArgs,ok) {
var e = originalEventArgs[0];
var geocoder = new google.maps.Geocoder();
var latlng = new google.maps.LatLng(e.latLng.lat(), e.latLng.lng());
geocoder.geocode({ 'latLng': latlng }, function (results, status) {
if (status == google.maps.GeocoderStatus.OK) {
if (results[1]) {
console.log(results[1].formatted_address); // details address
} else {
console.log('Location not found');
}
} else {
console.log('Geocoder failed due to: ' + status);
}
});
}
}
};
Given Latitude/Longitude object you can map location to approximate address using Google Map API.
You can use the Geocoding API for mapping locations to addresses and addresses to locations.
Geocoder.geocode( { 'latLng': latLngObject }, callbackFn);
Here is the link for Google Map API for Geocoding.
Try these links
https://developers.google.com/maps/documentation/javascript/examples/geocoding-reverse?csw=1
Use the Geocoding API for mapping locations to addresses and addresses to locations. http://code.google.com/apis/maps/documentation/javascript/services.html#Geocoding
Geocoder.geocode( { 'latLng': latLngObject }, callback);
http://wbyoko.co/angularjs/angularjs-google-maps-components.html
Hope it helps!!!

Remove Streetview Controls

I'm working on the front-end of an app I had developed and wanting to remove the controls from the Google StreetView embed shown here:
function displayGoogleSV(address_str) {
var geocoder = new google.maps.Geocoder();
var myStreetView = null;
var marker = null;
var address = address_str;
geocoder.geocode({
'address': address
}, function (results, status) {
//alert (results);
if (status == google.maps.GeocoderStatus.OK) {
//alert(results[0].geometry.location);
myStreetView = new google.maps.StreetViewPanorama(document.getElementById("streetview"));
myStreetView.setPosition(results[0].geometry.location);
google.maps.event.addListenerOnce(myStreetView, 'status_changed', function () {
var heading = google.maps.geometry.spherical.computeHeading(myStreetView.getLocation().latLng, results[0].geometry.location);
myStreetView.setPov({
heading: heading,
pitch: 0
});
Where would I stick in the controls seen here: https://developers.google.com/maps/documentation/javascript/examples/streetview-controls
Thanks!
You should disable them by using the link's options in your Street View's options:
/* ... */
myStreetView.setPov({
heading: heading,
pitch: 0
});
var panoOptions = {
addressControlOptions: {
position: google.maps.ControlPosition.BOTTOM_CENTER
},
linksControl: false,
panControl: false,
zoomControlOptions: {
style: google.maps.ZoomControlStyle.SMALL
},
enableCloseButton: false
};
myStreetView.setOptions( panoOptions );

Categories

Resources