google maps click event isn't reading objects from data - google-maps

I'm trying to get latitude and longitude by clicking on map then I use them to get formatted address from google maps API and finally I want to persist lat, lng and formatted address in my object "station" declared in data
data() {
return {
station: {},
mapName: this.name + "-map",
lat: Number,
lng: Number,
Fulladdress: String
};
} ,
mounted() {
const element = document.getElementById(this.mapName);
const options = {
zoom: 14,
center: new google.maps.LatLng(51.501527, -0.1921837)
};
const map = new google.maps.Map(element, options);
google.maps.event.addListener(map, "click", function(event) {
this.lat = event.latLng.lat();
this.lng = event.latLng.lng();
axios
.get(
"https://maps.googleapis.com/maps/api/geocode/json?latlng=" +
this.lat +
"," +
this.lng +
"&key=APIKEY"
)
.then(resp => {
var fulladdress;
console.log(resp.data.results[0].formatted_address);
fulladdress = resp.data.results[0].formatted_address;
this.Fulladdress = fulladdress;
//persist lat, lng and formatted address in my object station
this.station.address = this.Fulladdress;
this.station.lat = this.lat;
this.station.lng = this.lng;
})
.catch(e => {
console.log(e);
});
});
}

The context is changing. Inside the click handler, the this is not referring to the Vue instance, but something else (it depends on how google maps does it, but it could be window or the map instance).
To have the this be the Vue instance, use arrow functions instead.
Change from:
google.maps.event.addListener(map, "click", function(event) {
To:
google.maps.event.addListener(map, "click", (event) => {

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>

Using Geocorder result in other function in VUe

i try to use the result of Geocode Lag Long, but i can't use out of the function. How can i use the result in other function in Vue?
Why i can't use "this.markerCoordinates" in other functions?
getLocation : function (address){
const element = document.getElementById(this.mapName);
var local;
// geocoder API (pega o endereço)
var geocoder = new google.maps.Geocoder(address);
geocoder.geocode({ 'address': address}, function (results, status){
if (status == google.maps.GeocoderStatus.OK) {
var latitude = results[0].geometry.location.lat();
var longitude = results[0].geometry.location.lng();
// I WANT USE THIS IN OHTER FUNCTION
this.markerCoordinates = [{"latitude" :latitude , "longitude" : longitude}]
callback( this.markerCoordinates[0])
}
var mapCentre = this.markerCoordinates[0]
var options = {
zoom : 16,
center: new google.maps.LatLng(mapCentre.latitude , mapCentre.longitude)
}
this.options = options;
this.map = new google.maps.Map(element, options);
this.markerCoordinates.forEach((coord) => {
const position = new google.maps.LatLng(coord.latitude, coord.longitude);
const marker = new google.maps.Marker({
position,
map: this.map
});
});
});
},
in other functions is return undefined
Define a data element for your coordinates in your component, see here for an example: data() {return { markerCoordinates: undefined } }
In your getLocation function, you need a closure that points to the enclosing Vue instance , like this let vm = this. See here, e.g.
In the callback, use this variable to access the data element: vm.markerCoordinates = [{"latitude" :latitude , "longitude" : longitude}]
Access the it in the template simply by using markerCoordinates and in other methods of your component with this.markerCoordinates

Filter google markers with knockout

I've been trying to solve this issues with no luck. I already check other posts and no luck. I think I have an error on my code, my goal is to be able to filter the list and show/hide only the markers on that list. A sample of the code is here: https://jsfiddle.net/rp2t3gyn/2/
Here is a sample of the code that is not working for some reason:
self.filteredPlaces = ko.computed(function() {
var filter = self.filter().toLowerCase();
if (!filter) {
ko.utils.arrayForEach(self.placeList(), function (placeItem) {
placeItem.marker.setVisible(true);
});
return self.placeList();
} else {
return ko.utils.arrayFilter(self.placeList(), function(placeItem) {
// set all markers visible (false)
var result = (placeItem.city.toLowerCase().search(filter) >= 0);
placeItem.marker.setVisible(result);
return result;
});
}
}, this);
Thanks
In order to filter the markers you need to do a few things.
Your first problem is this line:
placeItem.marker.setVisible(true);
Place item doesn't have a marker object based on your constructor. So, you have to add it. I changed the Place constructor to add a marker object (see below).
var Place = function(data, map, viewmodel) {
this.city = data.city;
this.lat = data.lat;
this.lng = data.lng;
var marker = new google.maps.Marker({
map: map,
position: {lat: data.lat, lng: data.lng},
city: data.city,
icon: {
path: google.maps.SymbolPath.BACKWARD_CLOSED_ARROW,
scale: 5
},
animation: google.maps.Animation.DROP,
});
marker.addListener('click', function() {
viewmodel.clickSelection(marker, viewmodel.largeInfoWindow);
});
this.marker = marker;
};
and used that to initialize your objects. Lastly, I changed your filteredPlaces function, it needs to subscribe to the query observable so that when you type in text the markers on the map adjust accordingly .
self.query.subscribe(function() {
var filter = self.query().toLowerCase();
if (!filter) {
ko.utils.arrayForEach(self.placeList(), function (placeItem) {
placeItem.marker.setMap(map);
});
return self.placeList();
} else {
ko.utils.arrayForEach(self.placeList(), function(placeItem) {
var result = (placeItem.city.toLowerCase().search(filter) >= 0);
if(result)
placeItem.marker.setMap(map);
else
placeItem.marker.setMap(null);
});
}
});
Working fiddle here.

Google map not showing using AngularJS but the images are being downloaded

This is my angular js directive through which I am trying to display code:
"use strict";
app.directive('geomap', function () {
return {
restrict:'E',
link:function (scope, elem, attrs) {
scope.$watch(attrs.ngModel, function (v) {
var geoBoardlocation = v;
if (v != undefined) {
var ICON = new google.maps.MarkerImage('medicare.png', null, null,
new google.maps.Point(14, 13));
var SHADOW = new google.maps.MarkerImage('medicare-shadow.png', null, null,
new google.maps.Point(14, 13));
google.maps.event.addDomListener(window, 'load', function () {
var map = new google.maps.Map(document.getElementById('map-canvas'), {
center:new google.maps.LatLng(37.7, -122.2),
zoom:4,
streetViewControl:true,
mapTypeId:google.maps.MapTypeId.ROADMAP
});
var panelDiv = document.getElementById('panel');
var data = new MedicareDataSource(geoBoardlocation);
var view = new storeLocator.View(map, data, {
geolocation:false,
features:data.getFeatures()
});
view.createMarker = function (store) {
console.log(store.getDetails());
var markerOptions = {
position:store.getLocation(),
icon:'medicare.png',
shadow:'medicare-shadow.png',
title:store.getDetails().title
};
return new google.maps.Marker(markerOptions);
}
var infoBubble = new InfoBubble;
view.getInfoWindow = function (store) {
if (!store) {
return infoBubble;
}
var details = store.getDetails();
var html = ['<div class="store"><div class="title">', details.title,
'</div><div class="address">', details.address, '</div>',
'<div class="hours misc">', details.hours, '</div></div>'].join('');
infoBubble.setContent($(html)[0]);
return infoBubble;
};
new storeLocator.Panel(panelDiv, {
view: view,
directions: false,
});
});
}
});
}
};
});
However using this the map doesn't show up. Any idea why would that happen? I can see map images being downloaded in Network tab in Chrome however the map doesn't show up.
Can you check url # https://github.com/angular-ui/ui-map and Angular UI Implementation of Google Map
This directive allows you to add Google Maps JavaScript API elements in angularJS

Google Place API v3 with Sencha Touch 2.x

I am new to Sencha Touch, knows Javascript,jQuery,HTML5.
I am developing simple Google Map application with Sencha Touch + Sencha Architect where it place marker on current position and also use Google Place to find 'store'(i.e. types need for Google place search) near the current location. I am getting the locations in 'callbackPlaces' (i.e. latitude, longitude) but Google.Maps.Marker gives error in 'callbackPlaces' method (i.e. called through 'addMarker' method and I also tried and tested by putting Google.Maps.Marker in 'callbackPlaces').
Ext.define('MyApp.view.Map', {
extend: 'Ext.Map',
alias: 'widget.map',
config: {
useCurrentLocation: true,
listeners: [
{
fn: 'onMapMaprender',
event: 'maprender'
}
]
},
onMapMaprender: function(map, gmap, options) {
this.initializePlaces();
},
initializePlaces: function() {
//Set Marker on Current Position
var geo = this.getGeo();
var currentPosition = new google.maps.LatLng(geo.getLatitude(), geo.getLongitude());
this.createMarker(currentPosition);
//request set for Places Services
var request = {
location: currentPosition,
radius: 500,
types: ['store']
};
this.getMap().zoom = 15;
// Call PlacesService
var service = new google.maps.places.PlacesService(this.getMap());
service.nearbySearch(request, this.callbackPlaces);
},
callbackPlaces: function(results, status) {
if (status == google.maps.places.PlacesServiceStatus.OK) {
for (var i = 0; i < results.length; i++) {
addMarker(results[i]);
}
}
},
createMarker: function(position) {
//Here Position = Google Map LatLng
var infoWindow = new google.maps.InfoWindow();
var marker = new google.maps.Marker({
map: this.getMap(),
position: position
});
google.maps.event.addListener(marker, "click", function() {
infoWindow.setContent("Lng: " + marker.position.lng() + "\n Lat: " + marker.position.lat());
infoWindow.open(this.getMap(), marker);
});
},
addMarker: function() {
//Here Place = google.maps.places
var infoWindow = new google.maps.InfoWindow();
var marker = new google.maps.Marker({
map: this.getMap(),
position: place.geometry.location
});
google.maps.event.addListener(marker, "click", function() {
infoWindow.setContent("Lng: " + marker.position.lng() + "\n Lat: " + marker.position.lat());
infoWindow.open(this.getMap(), marker);
});
}
});
I don't know what went wrong!
Any help|hint would appreciated!
Thanks in advance.
You pointed out there was a scope issue in the callbackPlaces function.
Therefore you should replace the following line:
service.nearbySearch(request, this.callbackPlaces);
with
service.nearbySearch(request, function (results, status) {
this.callbackPlaces.call(this, [results, status]);
});
Hope this helps