Revisiting this 6 months later, I’ve made several significant changes and improvements in an actual plugin for Vue projects: x5-gmaps

This article is still great for learning and should be easier to follow along with, but please check out the source code and examples of the plugin too.

Recently I needed to use Google Maps for a project, and after a quick search, I found that the vast majority of recommendations were to just use the package vue2-google-maps. Now I did use it, and it’s great, but a) I prefer not to use packages, and b) I wanted to understand the Google Maps API first… So I made my own, and thought I’d share it.

Setup and Requirements

Step 1: Learn Vue
Step 2: Have a Google Cloud account
Step 3: Activate the Maps Javascript API
Step 4: Generate an API key

The Google Maps API

To start with, let’s look at how Google recommends we include this. From Google’s Javascript API tutorial we can see that there are two main parts to including a map on a normal page: The initMap() function and actual Google Maps API script. Looking at the API script link we can see that it needs our API key, and also has a callback to the initMap() function. Looking at the initMap() function we also see a simple logic of choosing a HTML element where the map object can be injected, and then creating a Google Maps Marker which we feed a geolocation and the defined map object.

Easy. Let’s do that all in Vue.

The Map

OK, so creating a new Vue project using the CLI vue create vue-maps-example we are going to need to include this Google Maps API script somewhere. For simplicity, just put it in the same position as in the example, in your [public]/index.html, and let’s also get rid of the callback variable:

Now, let’s keep it simple and replace the App.vue. For our template, we just need to add a map div inside the app div:

*Note: added a Vue reference name “map”

And some quick styling:

*Note: it’s default height is zero

And then for the script we can basically copy the tutorial with some minor changes:
1. We are storing our created Map object in the Vue data property map for our later use.
2. To access the injected global variable Google Maps in Vue, we need to add window in front of the reference (window.google.maps).
3. To get the element to inject into, we are using refs which is one of MANY ways to access the DOM.

Now we can give it the element Vue reference (map), and the options for the map in an object (see all the options here) et voila.

So you should have a map showing now like in the tutorial (minus the marker).

The Marker

Now to add the marker, you can use almost exactly the same code in the tutorial but with aforementioned differences:

Just give it the created map reference we stored before

But that’s not a reusable component! OK so instead let’s get our Map ready for some components. So that we can use things like v-for loops, we want to end up with this working:

As we’ve seen, we can easily add things to the map *if* we have the map reference; but the devil is in the details. You see, after the HTML of the page loads, it runs the JS scripts (Vue.js and Google Maps API script), and then sends off a check to make sure your API key is good, and if it is then the Google Maps API script will do your bidding. BUT! That all takes time, so if you don’t consider that, you will continually run into errors as Vue will load it, and it will throw an error because it can’t find the map… I am embarrassed to tell you how long this took me to figure out.

So, we’re going to make a map method that the map’s children can access that will run a callback AFTER the map is loaded:

I will elaborate if needed — let me know in comments!

OK, so let’s make a new component: MapMarker.vue

Now a Marker does not have custom HTML, and it’s all handled by Google Maps, so we don’t need a template or style. All we need is a script:
1. Two properties which must be included and must be numbers
2. A data property to track the created marker
3. The marker creation code in the mounted() hook
4. Disposal code in the beforeDestroy() hook
5. A render function because we don’t have a template

Again, I will elaborate if you have any questions

And then, if all went well, if you add in some MapMarker components (like we said we wanted at the top) as children of the Map, you should see the markers showing up.

You can see code here if you got lost.

Bonus: Info Window

Very similarly, we can add Info Windows in the same way, but they’re a little more interesting as you can put HTML inside them… So we already have our parent Map setup so can jump straight into the MapInfoWindow.vue component. This one does have a template but it’s just a div to hold a slot:

And the script:
1. Basically the same as the Marker
2. An additional option of content which is the HTML element that should be put into the window. I used this.$el which means the component root element (the div)
3. While not needed, the 3rd parameter stops the map from panning to the created Info Window. This may be desired, but when I added 20 of them the window jumped around and looked terrible.
4. We need to open() and close() Info Windows (the little x in the bubble created also closes it)

Now for our map:

*Note: text, a span, and an img are in the info windows

That’s all for now. Google Maps Popups are a bit harder and will need their own tutorial. Let me know if you want to see that too.

I have a background in process engineering, management, and consulting; but my passion is making systems and processes more efficient. Visit me: chisnall.io