Hands on

Dropping Markers on Geocoded Locations within a Vue.js Web Application

By Nic Raboy | 11 October 2018

When working with maps in any application, rarely do you ever want to work with only map tiles. Instead you’re probably going to want to include map objects such as markers to highlight locations on the map. HERE provides a very nice JavaScript API to get the job done, but more commonly you’re going to be working with a framework rather than vanilla JavaScript.

We’re going to see how to use the HERE Maps API for JavaScript to place markers on a map using the Vue.js JavaScript framework.

Take a look at the following image:

here-maps-marker-vuejs

In the above image we have a simple map with a single marker. Naturally, these markers are placed by using latitude and longitude coordinates. However, in our example, we’re going to see how to take an address string, obtain the coordinates of the address, and then place the marker on the map.

The Requirements

There are very few requirements necessary to get this project up and running. The requirements are as follows:

  1. You must have a HERE developer account
  2. You must have the Vue CLI installed and configured

If you don’t already have a developer account, you can sign up for free. You’ll need the app id and app code for one of your developer projects to make this project functional. These values can be found in your HERE developer dashboard. While the Vue CLI isn’t absolutely necessary when working with Vue.js, it does make life easier. The Vue CLI can be installed with the Node Package Manager (NPM).

Getting Started with a New Vue.js Web Application

If you haven’t already seen it, I previously wrote about displaying maps in a Vue.js web application. If you haven’t seen the tutorial, it isn’t absolutely necessary, but it will give you more thorough descriptions when creating a map component. In other words, I recommend you taking a moment to look it over.

We’re going to create a fresh project. With the Vue CLI, execute the following:

vue create here-marker-project

The above command will start the project wizard to create a new project. For this example, we’re only going to use the defaults. This means that it is not necessary to mess around with the Vue Router or Vuex.

Within the new project, open the public/index.html file and include the following HTML markup:

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="utf-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width,initial-scale=1.0">
        <link rel="icon" href="<%= BASE_URL %>favicon.ico">
        <title>HERE Maps with Vue</title>
    </head>
    <body>
        <noscript>
            <strong>We're sorry but vue-map doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
        </noscript>
        <div id="app"></div>
        <!-- built files will be auto injected -->
        <script src="https://js.api.here.com/v3/3.0/mapsjs-core.js" type="text/javascript" charset="utf-8"></script>
        <script src="https://js.api.here.com/v3/3.0/mapsjs-service.js" type="text/javascript" charset="utf-8"></script>
    </body>
</html>

In reality, all we added were the two <script> lines towards the bottom. These lines will give us a map and basic functionality with the HERE APIs for JavaScript.

The next step is to create a reusable component for our map. Create a src/components/HereMap.vue file within your project and include the following:

<template>
    <div class="here-map">
        <div ref="map" v-bind:style="{ width: width, height: height }"></div>
    </div>
</template>

<script>
    export default {
        name: "HereMap",
        data() {
            return {
                map: {},
                platform: {}
            }
        },
        props: {
            appId: String,
            appCode: String,
            lat: String,
            lng: String,
            width: String,
            height: String
        },
        created() {
            this.platform = new H.service.Platform({
                "app_id": this.appId,
                "app_code": this.appCode
            });
        },
        mounted() {
            this.map = new H.Map(
                this.$refs.map,
                this.platform.createDefaultLayers().normal.map,
                {
                    zoom: 10,
                    center: { lng: this.lng, lat: this.lat }
                }
            );
        }
    }
</script>

<style scoped></style>

Without re-explaining the previous article too much, the above code will create a placeholder for the map with dynamic style information, initialize some variables, define possible component attributes, initialize the HERE platform, and position the map when the view loads.

The component can then be used in the project’s src/App.vue file like so:

<template>
    <div id="app">
        <HereMap appId="APP-ID-HERE" appCode="APP-CODE-HERE" lat="37.7397" lng="-121.4252" width="100%" height="835px" />
    </div>
</template>

<script>
    import HereMap from "./components/HereMap.vue"

    export default {
        name: 'app',
        components: {
            HereMap
        }
    }
</script>

<style>
    #app {
        font-family: 'Avenir', Helvetica, Arial, sans-serif;
        -webkit-font-smoothing: antialiased;
        -moz-osx-font-smoothing: grayscale;
        text-align: center;
        color: #2c3e50;
    }
</style>

Notice the HereMap UI component. Those are the attributes that we defined in the actual component file. Now we’re caught up to the previous tutorial in terms of bootstrapping our project. Did I mention that you should check out the previous tutorial I wrote?

Dropping Markers on a Map with Latitude and Longitude Coordinates

With the project created and our basic map component in a working state, we can focus on dropping our first marker on the map. As of now, the map centers on a set of latitude and longitude coordinates, but no marker is places. We’re going to change that so the user knows what we’re looking at.

Open the project’s src/components/HereMap.vue file so we can prepare for the markers. Within the component, check out the mounted method:

mounted() {
    this.map = new H.Map(
        this.$refs.map,
        this.platform.createDefaultLayers().normal.map,
        {
            zoom: 10,
            center: { lng: this.lng, lat: this.lat }
        }
    );
    this.map.addObject(new H.map.Marker({lat: this.lat, lng: this.lng }));
}

If you take a look at your map, it should be centered on the latitude and longitude coordinates that the user provided and a marker should now exist at those same coordinates. Not so bad, right?

Working with exact coordinates is nice, but we can do better.

Geocoding an Address and Placing a Marker with the Results

I think very rarely are users passing around latitude and longitude coordinates when they want to do mapping business. More commonly people are going to be passing around addresses instead. To be successful with addresses, we can actually make use of the HERE Geocoder API for JavaScript. This API will allow us to discover coordinate information from addresses, or the opposite.

We’re going to make a few changes before we can make use of the Geocoder API. Open the project’s src/components/HereMap.vue file and include the following:

data() {
    return {
        map: {},
        platform: {},
        geocoder: {}
    }
},

In the above data function, we are now initializing a geocoder variable so that we can use it globally throughout the component. There are many ways to collect address information, but to keep things easy, we’re going to create another optional property for the component:

props: {
    appId: String,
    appCode: String,
    lat: String,
    lng: String,
    width: String,
    height: String,
    location: String
},

The location property will hold our address information. If you wanted to, you could remove the lat and lng properties as they won’t be too valuable to us any more.

With the variables in place, now we need to initialize the geocoder:

created() {
    this.platform = new H.service.Platform({
        "app_id": this.appId,
        "app_code": this.appCode
    });
    this.geocoder = this.platform.getGeocodingService();
},

Now that the geocoder has been initialized, it can be used to find our coordinate information for markers. Let’s revisit the mounted method which will be responsible for placing our markers.

mounted() {
    this.map = new H.Map(
        this.$refs.map,
        this.platform.createDefaultLayers().normal.map,
        {
            zoom: 10,
            center: { lng: this.lng, lat: this.lat }
        }
    );
    this.geocoder.geocode({ searchText: this.location }, data => {
        if(data.Response.View.length > 0) {
            if(data.Response.View[0].Result.length > 0) {
                var coords = data.Response.View[0].Result[0].Location.DisplayPosition;
                this.map.setCenter({lat: coords.Latitude, lng: coords.Longitude });
                this.map.addObject(new H.map.Marker({lat: coords.Latitude, lng: coords.Longitude }));
            }
        }
    }, error => {
        console.error(error);
    });
}

In the above mounted method, I’ve decided to leave the latitude and longitude properties that the user provides. However, given a location string, we can use the geocoder to find our position. Once found, the map is re-centered to that position and a marker is placed.

If we wanted to see this component in action, we could change our src/App.vue file to the following:

<template>
    <div id="app">
        <HereMap appId="APP-ID-HERE" appCode="APP-CODE-HERE" location="Manteca, CA" lat="37.7397" lng="-121.4252" width="100%" height="835px" />
    </div>
</template>

<script>
    import HereMap from "./components/HereMap.vue"

    export default {
        name: 'app',
        components: {
            HereMap
        }
    }
</script>

<style>
    #app {
        font-family: 'Avenir', Helvetica, Arial, sans-serif;
        -webkit-font-smoothing: antialiased;
        -moz-osx-font-smoothing: grayscale;
        text-align: center;
        color: #2c3e50;
    }
</style>

In the above code, notice that I’ve included a location="Manteca, CA". This is the address that will be converted and displayed as a marker. You can refine the address to include a street number and street name as well. The geocoder will figure it out and return numerous results as necessary.

Conclusion

You just saw how to not only display markers on a map, but also use the HERE Geocoder API for JavaScript within a Vue.js web application. Vue.js is a very popular framework and it really isn’t difficult to include the HERE Location Services (HLS) within a project created with it.

If you’re curious to see how to use the HERE Geocoder API for JavaScript with Angular, another popular framework, check out my previous tutorial on the topic titled, Using the HERE Geocoder API for JavaScript in an Angular Application.