Using Google Maps API with Meteor.js - javascript

I'm trying to use the Google Maps API with Meteor 1.3 and with the dburles:google-maps package.
I tried various way to load it but the thing is that I can't use it because it takes too long to load I think and my page is rendered before.
I load it this way in my main.js to be sure that is loaded first.
import { GoogleMaps } from 'meteor/dburles:google-maps';
import { Meteor } from 'meteor/meteor';
Meteor.startup(function () {
GoogleMaps.load({ key: 'myKey' });
});
Then I include the helper in my template to display the map.
<template name="home">
<h1>Home</h1>
<div class="map-container">
{{> googleMap name="exampleMap" options=exampleMapOptions}}
</div>
</template>
Finally there is my helper to set the options for the template.
import { Template } from 'meteor/templating';
import { GoogleMaps } from 'meteor/dburles:google-maps';
import './home_page.html';
Template.home.helpers({
exampleMapOptions() {
// Make sure the maps API has loaded
if (GoogleMaps.loaded()) {
// Map initialization options
return {
center: new google.maps.LatLng(-37.8136, 144.9631),
zoom: 8,
};
}
},
});
Template.home.onCreated(function() {
GoogleMaps.ready('exampleMap', function(map) {
console.log("I'm ready!");
});
});
I think that the condition if (GoogleMaps.loaded()) is the reason why nothing is displayed but if I dont put it I got an error because the google object doesn't exist.

If you don't have an error on your JS console, the map could be loaded but not shown for missing css.
If it's so, Add the line below to your main.css
body, html {
height: 100%;
width: 100%;
}
.map-container {
width: 100%;
height: 100%;
}

Related

Access Variables Created During onMount in Svelte

I'm working my first Svelte app which includes an embedded Google Map.
Setup Google Maps With Svelte 3 provided a good starting point for creating a component which asynchronously loads a Google Map. However, I can't figure out how to access the map object outside the initial onMount call, and without access to that object I can't add in functionality I want (for example, re-centering the map based on a button the user clicks).
main.js
import App from './App.svelte';
const app = new App({
target: document.body,
props: {
ready: false,
}
});
window.initMap = function ready() {
app.$set({ ready: true });
}
export default app;
App.svelte
<script>
import Map from './Map.svelte';
export let ready;
</script>
<svelte:head>
<script defer async src="https://maps.googleapis.com/maps/api/js?key={}&callback=initMap"></script>
</svelte:head>
{ #if ready }
<Map></Map>
{ /if }
Map.svelte
<script>
// Imports
import { onMount } from 'svelte';
// Globals
let map;
let container;
// Load the map async
onMount(async () => {
map = new google.maps.Map(container, {
zoom: 6,
center: { lat: 0, lng: 0 },
});
});
// This function has no access to the `map` variable created above!!
function recenterMap() {
map.setCenter({lat: 1, lng: 1});
}
</script>
<div class="full-screen" bind:this={container}></div>
<button on:click="{recenterMap}"></button>
Running the above gives an error for trying to invoke the setCenter call on an object that does not exist. I've searched for how other frameworks (React, Vue) might handle this, but the solutions are specific to the frameworks and are not applicable here.
Any help would be greatly appreciated!

How to add Jitsi Meet to Vuejs

I have loaded the jitsi meet script in the body of my public.html, and i have a component as follows:
<template>
<div class="container">
<div id="meet"></div>
</div>
</template>
<script>
export default {
name: "ServiceMeet",
mounted() {
const domain = "meet.jit.si";
const options = {
roomName: "PickAnAppropriateMeetingNameHere",
width: 700,
height: 700,
parentNode: document.querySelector("#meet"),
};
const api = new JitsiMeetExternalAPI(domain, options);
console.log(api.getVideoQuality());
},
};
</script>
When I try to run I get an error saying 18:21 error 'JitsiMeetExternalAPI' is not defined no-undef, however in the background i can see that the meet is working fine, so I do I fix the error or dismiss it.
You could disable the linting error, but I would recommend specifying it as a global variable instead.
.eslintrc.js
module.exports = {
globals: {
JitsiMeetExternalAPI: true
}
}
It should work if you prefix the global with window:
const api = new window.JitsiMeetExternalAPI(domain, options);

nuxt.js get default head in vue.js component

I am trying to get the head object that is configured by nuxt.config.js in a vue layout. In order to show the same title in an app bar as the page title.
I know that you can alter the page title with the head function in a vue component. But is it also possible to retrieve this information somehow?
<script>
export default {
data () {
return {
title: head.titleTemplate // possible?
}
},
head () {
// here it is possible to change it but how about getting it?
}
}
</script>
Another approach could be to get some data out of an page in the nuxt.config.js. But I think this is not how the hierarchy is structured.
Thanks for you help I am just starting to use javascript to code a website :)
(If I understand you correctly) You can use the changed callback to keep track of the latest meta info used (and thus the title).
Example:
head() {
return {
changed: (info) => {
this.title = info.title;
console.log(info, info.title);
},
};
},
data() {
return {
title: '',
};
},
In nuxt.config.js before export I have setted variable with a string of the title.
Then added it to the head section and create a new env section:
https://nuxtjs.org/api/configuration-env/
const title = `Site title`
export default {
head: {
title
},
env: {
title
}
}
This how I'm getting the title in any Vue component:
export default {
computed: {
title () {
return process.env.title
}
},
}
This helps you to keep your original title in process.env.title, even if you will want to change head.title dynamically.
Did anyone found a better solution maybe? :)

initializing 'marker-animate-unobtrusive' in Vue fails

I am trying to use marker-animate-unobtrusive but I keep getting this error:
I found another post on SO that talked about requiring the file after google has loaded but I do not know how to do that. in my component I have this:
import SlidingMarker from 'marker-animate-unobtrusive'
In my mounted method I have this:
SlidingMarker.initializeGlobally()
Any help is greatly appreciated
This is expected error since SlidingMarker extends google.maps.Marker class, GoogleMaps JavaScript API library needs to be loaded first, one option would to add a reference via index.html file:
<script src="https://maps.googleapis.com/maps/api/js?key=--KEY-GOES-HERE--"></script>
Another option would to utilize async JavaScript loader, e.g. scriptjs. The example for loading GoogleMaps JavaScript API and marker-animate-unobtrusive module could look like this:
created: function(){
get("https://maps.googleapis.com/maps/api/js?key=", () => {
const SlidingMarker = require('marker-animate-unobtrusive')
SlidingMarker.initializeGlobally()
const map = new google.maps.Map(document.getElementById('map'), this.mapOptions);
const marker = new SlidingMarker({
position: this.mapOptions.center,
map: map,
title: 'Im sliding marker'
});
});
}
Here is a demo for your reference
Update
With vue-google-maps library marker-animate-unobtrusive plugin could be integrated like this:
<template>
<div>
<GmapMap :center="center" :zoom="zoom" ref="mapRef"></GmapMap>
</div>
</template>
<script>
/* global google */
export default {
data() {
return {
zoom: 12,
center: { lat: 51.5287718, lng: -0.2416804 },
};
},
mounted: function() {
this.$refs.mapRef.$mapPromise.then(() => {
this.initSlidingMarker(this.$refs.mapRef.$mapObject)
})
},
methods: {
initSlidingMarker(map){
const SlidingMarker = require('marker-animate-unobtrusive')
SlidingMarker.initializeGlobally()
const marker = new SlidingMarker({
position: map.getCenter(),
map: map,
title: 'Im sliding marker'
});
google.maps.event.addListener(map, 'click', (event) => {
marker.setDuration(1000);
marker.setEasing('linear');
marker.setPosition(event.latLng);
});
}
}
}
</script>
<style>
.vue-map-container {
height: 640px;
}
</style>
Install the package google from npm this should fix it.

Meteor 1.3 and includes: where to declare your helpers?

I'm struggling to understand Meteor 1.3's include logic.
For an app I'm trying to put together, I have in /client/main.js:
import '../imports/startup/accounts-config.js';
import '../imports/ui/body.js';
import '../imports/ui/home.js';
import '../imports/ui/map.js';
import '../imports/ui/admin.js';
...
In /imports/ui/body.js, I have (I use flow router and mainLayout is the main layout, in which all other templates are rendered):
...
Template.mainLayout.onCreated(function mainLayoutOnCreated() {
Meteor.subscribe('tasks');
Meteor.subscribe('categories');
});
...
Then I have the following function:
Template.admin.helpers({
categories() {
return Categories.find({}, { sort: { createdAt: -1 } });
},
});
If I put this function in /imports/ui/body.js, I'm able to call 'categories' in the template with name 'admin'. However, when I put this function in /imports/ui/admin.js, I get a useless exception in the javascript console:
Exception in template helper: categories#http://localho...
How is it that moving the file in which this helper is declared, while still being included in the same 'main' file, results in an exception being thrown?
You should import the desired template and the templating package at the top of your admin.js file.
import {
Template
} from 'meteor/templating';
import '.deep/admin.js';
Template.admin.helpers({
categories() {
return Categories.find({}, { sort: { createdAt: -1 } });
},
});

Categories

Resources