I am using the following code:
Template.categories.rendered = function() {
var map = new GMaps({
div: '#map_canvas',
lat: -12.043333,
lng: -77.028333
});
}
to execute the Gmaps.js plugin - and it works, everytime I Submit a form, the layout gets re-rendered and my google maps get a re-paint too.
I also used constant to try to isolate it... And isolate.. Nothing. (it's not inside a template)
{{#constant}}
<div id="map_canvas"></div>
{{/constant}}
I tried changing Template.categories.rendered to Template.categories.created but I got a bunch of errors. I was hoping 'created' only gets executed once..
edit I made a new template 'maps' and separated the forms form the map
but I'm afraid this is not a viable solution as I want to communicate between the map and the form.. notably I want to get the latitude and longitude and automatically fill in a field...
Try putting your map in a seperate template e.g
<template name="categories">
{{>map}}
{{>other_form_with_submit_button}}
</template>
So you put your map in the
<template name="map">
<div id="map_canvas></div>
</template>
<template name="other_form_with_submit_button">
.. your form data
</template>
You should still be able to communicate to the map like normal, the DOM doesn't even notice much of the difference
Template.other_form_with_submit_button.events({
'submit' : function() {
var lat = "-12.043333",
var lng = "-77.028333";
var map = new GMaps({
div: '#map_canvas',
lat: -12.043333,
lng: -77.028333
});
}
}
Similarly while moving the map you can attach a listener and have it change the textbox like you wish:
Template.map.rendered = function() {
var map = new GMaps({
div: '#map_canvas',
lat: -12.043333,
lng: -77.028333
});
//Im not sure what you're using to get the location but this is the example if moving the center could be used
google.maps.event.addListener(map, 'center_changed', function() {
$("#lat").val(map.getPosition().lat());
$("#lng").val(map.getPosition().lng());
}
});
Related
I'm building a Google Maps app using Vue. (I use .vue instead of single file component)
i have a number of markers on the map and an InfoWindow tie to each of them with this code.
Markers section in the MapComponent.vue
this.markers[layer.lyr_id][node.nod_id] = new google.maps.Marker({
icon: {
scaledSize: configuration.marker.icon.scaledSize,
url: layer.icon_nod_sub_url,
},
position: {
lat: node.lat,
lng: node.lon,
},
map: mapCanvas,
});
InfoWindow section in the MapComponent.vue
this.infoWindows[layer.lyr_id][node.nod_id] = new google.maps.InfoWindow({
content: `<strong>${node.dflt_name}</strong>
<p>${node.dflt_info}</p>
<button v-on:click="this.addToPath(${node.nod_id})">Add this node to the path</button>`,
});
EventListener section in the MapComponent.vue
this.markers[layer.lyr_id][node.nod_id].addListener('click', () => {
this.infoWindows[layer.lyr_id][node.nod_id].open(
mapCanvas,
this.markers[layer.lyr_id][node.nod_id]
)
});
What I'm struggling right now is how to make the <button> in the InfoWindow section calls a function defined in the methods which looks like this
methods: {
...
addToPath(nod_id) {
alert(nod_id)
console.log(nod_id)
}
...
}
Right now when I click the button it does absolutely nothing, no warning, no error at all.
What should I do to get it work?
Note:
I have searched and found this similar question. However, it doesn't work for my case because I use this way to import (which it would be too late to change the way to import). When I use the solution in that question, I got the error that says TypeError: vm is undefined. So it didn't help me.
Thank you in advance!
Assign vue to a constant such as
const vm = new Vue({
el: '#app',
components: { 'map-component': MapComponent }
});
I then usually assign a ref to it:
<map-component ref="map-component">...</map-component>
And then you can all the methods inside the component with
vm.$refs.map-component.addToPath()
I have the following list called 'locationList':
[[lat:-6.2986514, lng:53.3324511, car_reg:161-D-XXXXXX], [lat:-7.259881, lng:53.041335, car_reg:151-D-YYYYY], [lat:-7.6273397, lng:53.3052366, car_reg:142-D-ZZZZZ]]
Now, if I just do a simple iteration like this it works. (It outputs my three lines of coordinates.).
<#list locationList as loc>
<p> Output: ${loc.lat} -- ${loc.lng} </p>
</#list>
But when I try to use it within my google maps function, it won't work. This is what I have:
function geocodeLatLng(geocoder, map, infowindow) {
<#list locationList as loc>
var latlng = {lat: ${loc.lat}, lng: ${loc.lng} };
var marker = new google.maps.Marker({
position: latlng,
map: map
});
</#list>
}
It works fine if I just write out manually three times what is contained within the freemarker list tags.
And I have tried everything I can think of. Can anyone help throw light on what is happening here?
EDIT - Whole script included below:
<script>
function initMap() {
<#assign lat='53.328015' lng='-6.3743767' >
var map = new google.maps.Map(document.getElementById('map'), {
zoom: 8,
center: {lat: ${lat}, lng: ${lng} }
});
var geocoder = new google.maps.Geocoder;
var infowindow = new google.maps.InfoWindow;
google.maps.event.addDomListener(window, 'load', function() {
geocodeLatLng(geocoder, map, infowindow);
});
}
function geocodeLatLng(geocoder, map, infowindow) {
<#list locationList as loc>
var latlng = {lat: ${loc.lat}, lng: ${loc.lng} };
var marker = new google.maps.Marker({
position: latlng,
map: map
});
</#list>
}
</script>
<script src="https://maps.googleapis.com/maps/api/js?key=REMOVED&callback=initMap"
async defer></script>
In cases like this, always check what the actual output is (you should be able to do that in the web browser) and how that differs from what you write when you fill it manually. Also, check what JavaScript errors you get.
My blind guess is that the numbers are formatted for human audience, and thus aren't valid JavaScript literals. Use ?c (as in ${loc.lat?c}) to format for computer "audience".
The code was fine. In constructing my list I had got longtitude and latitude the wrong way around. Apologies. I was looking in the entirely wrong place.
Trying out polymer and wanted to know how to add a marker element to the polymer element. I know how to add the marker to a standard google map. Should I just insert a marker object into the google-map elements marker array? If so whats the signature and is there an example? Do I need to call some sort of map init or refresh after I do so, or does it update automatically?
(function() {
Polymer({
is: 'users-map',
created: function(){
this.loadMap(this.data[0]);
},
loadMap: function(row) {
var map = document.querySelector('#users-location-map');
row.users.forEach(function (user) {
var location = user.location;
var markerOptions = {
position: {lat: location[1], lng: location[0]},
//map: map //can't set this otherwise it throws an error on finding the google library
};
if (!user.online) {
markerOptions.icon = 'http://chart.apis.google.com/chart?chst=d_map_pin_letter&chld=%E2%80%A2|666666';
}
map.markers.push(something); //how should I instanstiate this something
// new google.maps.Marker(markerOptions); //normally I would just do this
});
},
The answer below works if I comment out the map assingment.
It depends if you are using the google-map and google-map-marker or the google map API directly.
If you use the google-map and google-map-marker elements this approach should work:
marker = document.createElement('google-map-marker');
marker.longitude = location[0];
marker.latitude = location[1];
marker.icon = 'ICON_UR'
Polymer.dom(this.$.map).appendChild(marker);
If you use the google map API directly your normal appraoch with new google.maps.Marker(markerOptions); should work fine.
I had same task early and have solution by this question. I hope my example will have in future for solution.
For example we have google-map polymer in our html:
<google-map map="{{map}}" latitude="40.730610" longitude="-73.935242" zoom="5" click-events="true" mouse-events="true" api-key="{{you_api_key}}" disable-default-ui>
</google-map>
And for dynamically create marker on google-map by click and add EventListener for drag event I write script like this:
<script> var map = document.querySelector('google-map');
map.addEventListener('google-map-click', function (e) {
let marker = document.createElement('google-map-marker');
let latLng = e.detail.latLng;
marker.setAttribute('latitude', latLng.lat());
marker.setAttribute('longitude', latLng.lng());
marker.setAttribute('title', "Marker name");
marker.setAttribute('draggable', true);
marker.setAttribute('click-events', true);
marker.setAttribute('mouse-events', true);
marker.addEventListener('google-map-marker-dragend', function (e) {
let latLng = e.detail.latLng;
marker.setAttribute('latitude', latLng.lat());
marker.setAttribute('longitude', latLng.lng());
});
Polymer.dom(map).appendChild(marker);
});
</script>
Hope it help in future. Thanks.
Im creating a mobile app with Phonegap, Backbone.js, Require.js and PageSlider (https://github.com/ccoenraets/PageSlider).
I want to display a simple Google Map with a marker. The template looks like:
<div class='main-content' id='map-container'>
<a href="geo:51.903679,-8.468274">
<div id="map-canvas"></div>
</a>
</div>
Here is the view:
define(function (require) {
"use strict";
var $ = require('jquery'),
_ = require('underscore'),
Backbone = require('backbone'),
tpl = require('text!tpl/Map.html'),
side_nav = require('text!tpl/SideNav.html'),
template = _.template(tpl),
map, myLatlng, mapOptions, marker;
return Backbone.View.extend({
initialize: function () {
this.render();
},
initMap: function () {
myLatlng = new google.maps.LatLng(51.903679, -8.468274);
mapOptions = {
center: myLatlng,
zoom: 12,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
map = new google.maps.Map(this.$el.find('#map-canvas')[0],
mapOptions);
marker = new google.maps.Marker({
position: myLatlng,
map: map,
title: 'Christians Brothers College Cork'
});
},
render: function () {
this.$el.html(template({side_nav:side_nav}));
this.initMap();
},
});
});
Here is a link to the app. When you click on "location", the map renders perfectly. But when you navigate anywhere else, then back to location, only a tiny portion of the map can be seen in the top left hand corner.
I tried doing, which was suggested here:
google.maps.event.trigger(map, 'resize').
but to no avail. Any ideas?
Your view works on a node not appended to the DOM, thus without size, a situation Google Map is not very fond of. It is your router, via PageSlider, that does append the node after your render function has occurred.
Here is a demo of your predicament : http://jsfiddle.net/3C7g3/
You have several options to solve it:
call google.maps.event.trigger(map, 'resize') after the node is inserted into the DOM (this bit of code corresponds to your router entry for the map)
// assuming you stored the map object in your view
require(["app/views/Map"], function (Map) {
var view = new Map();
slider.slidePage(view.$el);
google.maps.event.trigger(view.map, 'resize');
});
http://jsfiddle.net/3C7g3/1/
insert the node into DOM before calling render. In your case, that probably means removing render from the view.initialize and calling view.render after container.append(page); in your slidePageFrom method.
http://jsfiddle.net/3C7g3/2/
a more hackish way would be to temporarily add the element to the DOM, apply Google Maps, and then remove it from the DOM
initMap: function () {
// assuming a temp class that hides the element. For example,
// .temp {position: absolute; visibility:hidden; }
this.$el.addClass('temp');
$('body').append(this.$el);
// ...
this.$el.remove();
this.$el.removeClass('temp');
}
http://jsfiddle.net/3C7g3/3/
I have the following problem:
I'm working in an aplication to book hotels that has tabs ("Hotel Details", "Map", "Reviews") in the overview page. the tabs are created with angularjs.
also, in the page I have the hotel address that is a link to the "Map" tab.
When I click on the "Map" tab, the google map is rendering ok. But, when I click on the hotel address, the "Map" tab opens but the map is not centered. If I refresh the page, it appears centered.
this is the code that process the map:
$scope.loadMap = function (targetID){
var latitude = $scope.latitude;
var longitude = $scope.longitude;
if(latitude && longitude && document.getElementById(targetID) != null ){
var center = new google.maps.LatLng(latitude, longitude);
var map_options = {
zoom: 13,
center: center,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
// create map
var map = new google.maps.Map(document.getElementById(targetID), map_options);
// configure marker
var marker_options = {
map: map,
position: center,
title: $scope.hotelName
};
// create marker
var marker = new google.maps.Marker(marker_options);
var infoWindow = new google.maps.InfoWindow();
window.setTimeout(function(){
google.maps.event.trigger(map, 'resize');
},2000);
}
}
Can you help me, please?
I've had this very problem when I was creating maps using Leaflet.js. I was trying to initialize the map inside of my angular service and it was loading very strangely. It appears you are trying to do the same thing, but you're doing it inside of your controller, rather than a service, but the effect is the same thing.
The problem is timing. Your controller is run before the DOM finishes loading and before angular has a chance to scan through the DOM to build out your Map page partial. Because of that, the page is only partially loaded when you call $scope.loadMap, which loads the google map, as you would expect. The problem is that once Angular finishes scanning the DOM partial, it modifies the DOM and then loads it into the view. When this happens, the google map has already been initialized to its default size based on the previous state of the DOM, and doesn't resize properly when angular is finished with the DOM.
Ok, that was a long explanation, but here's how you fix it:
You should do all of your map initialization inside of a directive's linking function. You could create a directive called something like app.directive('hotelMap'), which would initialize your map using the $scope.latitude and $scope.longitude variables from your controller.
link: function(scope, elem, attrs){
var center = new google.maps.LatLng(scope.latitude, scope.longitude);
var map_options = {
zoom: 13,
center: center,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
// create map
var map = new google.maps.Map(document.getElementById(targetID), map_options);
// configure marker
var marker_options = {
map: map,
position: center,
title: $scope.hotelName
};
// create marker
var marker = new google.maps.Marker(marker_options);
var infoWindow = new google.maps.InfoWindow();
}
And then in your map partial, you would have an element that looks something like <div hotel-map></div>. This fixes your problem, because your map will never be initialized until Angular has finished scanning/modifying the DOM and has finished rendering your partial. That way, the map's containing element will be at its final size/position and the map will be loaded into the element's center properly. Give it a try and let me know if that works.