loading google map from another component with vue router - google-maps

I have an issue about google map loading. the thing is in #App component reading google map
component from <router-view> but with this way it's giving the error: "ReferenceError: google is not defined". first I thought I am missing something inside initMap() but no, because if I try to paste map method into the app.vue then google map running without a problem.
By the way my api is inside the public/index.html
<script async defer src="https://maps.googleapis.com/maps/api/js?key=MY_API&callback=initMap"></script>
the map.vue component:
<template>
<div id="map" class="map"></div>
</template>
<script>
export default {
mounted(){
this.initMap();
},
methods: {
initMap(){
let options = {
center: {lat: 34.693725, lng: 135.502254},
zoom: 15,
mapTypeId: "roadmap"
};
let map = new google.maps.Map(document.getElementById("map"), options);
}
}
}
</script>
so what do you think problem is and how can I map component work with the <router-view>

The Vue Cookbook has an example for loading google maps, which uses google-maps-api-loader to wrap the loading process into a promise.
The promise from the loader is awaited in the mount hook in the consuming component.
Here's a codesandbox demonstrating the approach.

Related

How to call a function inside methods when click a button in a Google Maps' InfoWindow?

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()

google is not defined in angular 4 app

Hello I am trying to use an npm package "#types/googlemaps": "^3.30.7", and I am trying to implement a component that will allow me to create any of the things that I need to create as google isn't defined.
I have ran npm install many times.
I import it like: import {} from '#types/googlemaps';
and implement it like:
ngOnInit(): void {
var location = this.googleMapService.getCurrentLocation();
let mapProp = {
center: new google.maps.LatLng(this.googleMapService.currentLatitude, this.googleMapService.currentLogitude),
zoom: 15,
mapTypeId: google.maps.MapTypeId.HYBRID
};
this.map = new google.maps.Map(this.googleMap.nativeElement, mapProp);
this.map.addListener('click', (event) => this.addMarker(event));
this.addMarkerAtCurrentLocation();
}
if someone could tell me what to look for or why it is undefined i would appreciate it.
I have found the issue. On my index.html page I needed to add
<script src="http://maps.googleapis.com/maps/api/js"></script>
in the script section.

Q: How to intercept GoogleMap's requestAnimationFrame using Zone.js

EDIT: I'm using Zone v0.8.20
Background: Google Maps triggers requestAnimationFrame when zooming out of the map and when panning, I want to intercept these requestAnimationFrame via Zone.js to debounce it and may be improve performance on mobile devices...
I have the following simple repro code:
<!DOCTYPE html>
<html>
<head>
...
<script src="node_modules/zone.js/dist/zone.js"></script>
</head>
<body>
<div id="map"></div>
<script>
var map;
var mapZone = Zone.current.fork({
name: "GMAPS",
onScheduleTask: (delegate, current, target, task) => {
console.log(task);
console.log(Zone.current.name)
return delegate.scheduleTask(target, task);
},
onHasTask: (delegate, current, target, task) => {
console.log(task)
}
})
function initMap() {
mapZone.run(() => {
map = new google.maps.Map(document.getElementById('map'), {
center: {lat: -34.397, lng: 150.644},
zoom: 8
});
var marker = new google.maps.Marker({
position: {lat: -34.100, lng: 150.644},
map: map,
title: 'Hello World!'
});
});
}
</script>
<script src="https://maps.googleapis.com/maps/api/js?key=API_KEY&callback=initMap&sensor=true"
async defer></script>
</body>
</html>
The problem here is that I can't seem to intercept the requestAnimationFrame on the onScheduleTask method defined on the ZoneSpec... as you can see on the code, I ran the instantiation of Google Maps inside the forked Zone called mapZone
I'm newbie on Zone.js, this probably might be a simple problem, but I can't seem to find a solution... what do you think am I missing here?
Thanks so much in advance!
the reason that it is not work because google map is loaded in root zone, and in current version of zone.js, there are no way to configure the root zone spec.
I have created a walk around about this one to config root zone by monkey-patch zone.js. you can find the working sample in below link.
https://github.com/JiaLiPassion/customize-root-zone

Loading Google Map using Meteor JS

Using Meteor 0.8.2 and Google Maps API version 3.0
HTML Doc: (I omitted my google maps key but I have a valid one)
<head>
<title>myapp</title>
<script src="http://maps.googleapis.com/maps/api/js?key=####&sensor=false">
type="text/javascript">
</head>
<body>
{{> hello}}
</body>
<template name="hello">
<h1>Hello World!</h1>
{{greeting}}
<input type="button" value="Click" />
</template>
js doc:
if (Meteor.isClient) {
Template.hello.greeting = function () {
return "Welcome to myapp.";
};
Template.hello.events({
'click input': function () {
// template data, if any, is available in 'this'
if (typeof console !== 'undefined')
console.log("You pressed the button");
}
});
}
if (Meteor.isServer) {
Meteor.startup(function () {
// code to run on server at startup
});
}
I have taken the boilerplate code largely from resources that I have found online. Most of these resources are about a year old, so I am wondering if there may be compatibility issues between versions of the software.
I am wondering how to load the map working with the code above.
Add the html element to the hello template:
<div id="map-canvas" style="height: 300px; width: 300px"></div>
Add the normal maps loader to the rendered callback:
Template.hello.rendered = function () {
var mapOptions = {
center: new google.maps.LatLng(-34.397, 150.644),
zoom: 8
};
var map = new google.maps.Map(document.getElementById("map-canvas"),
mapOptions);
};
This same code would have worked as far back as Meteor had the rendered callback, so nothing has changed.
All of the code is readily available on the Google Maps API page and there are already a few questions on this topic, including meteor specific ones.

Using Meteor's Template.rendered for google maps

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());
}
});