Using Google map API with Umbraco

Multiple marker display using Umbraco list view

So far in this series we have created a document type called Location which saves a location and displays it on a map and a geocoding property editor that can be added to a document type. This article builds on the first two by explaining how to create a repository for multiple items location content and a template that can be used to display a marker on a Google map for each item of location content in the repository.

Create Location repository document type

Create another document type and call it Location repository, allowing Umbraco to create a template for it at the same time. Select the Enable list view option and select the Location document type option for the allowed child node types. This document type will be used as the repository for any locations you add to the site.

Edit Locations repository template

Go to the settings section and open the Location repository template.

Add razor code

Start by adding a razor code block, this is where we get the data from Umbraco and format it for use with the Google map API. To get the data use the Umbraco CurrentPage.Children() method to return a collection of child location content items:

@{
    var locations = CurrentPage.Children("Location");
}

Because razor code is processed server side we can’t just pass our location collection to the client side Google API JavaScript as objects. So what we need to do is embed the collection of location content in the html output as a JSON array where it can be processed by the JavaScript.

To do this we add the following code to the razor script block:

var locationList = new List<string>();

foreach (var location in locations)
{
    locationList.Add(
       string.Format(
           @"{{""title"":  ""{0}"", ""position"": new google.maps.LatLng({1}, {2})}}",
           location.Name,
           location.Geocoder.latitude,
           location.Geocoder.longitude
       )
   ); } var markerJsonArray = "[" + string.Join(",", locationList.ToArray()) + "]";

This code loops through the location collection and with each iteration it adds a string (with the data in the necessary format for the Google map API to be able to generate markers) to a list which it then converts to an array, ready to be embedded into the html.

Add the page mark-up

As with part 1 of the series, the template code examples will use the mark-up for a full HTML page that doesn’t inherit any HTML layout or site CSS from the Umbraco instance that you’re working with. This is so we can avoid any layout or styling issues that could cause problems displaying the map. So let’s add the mark-up for a HTML page:

<html>
<head>
    <title>@Umbraco.Field("pageName")</title>
    <script src="~/umbraco/lib/jquery/jquery.min.js"></script>
    <script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyC-sOLv-YADP4SK8kJZVFr0j8r2osSs8-k"></script>
</head>
<body>
<!-- map content and google map JS goes here-->
</body>
</html>

Add container div

Add a div element to the body of the html with an id of ‘map_canvas’ and set its height to 100% so it fills the screen, like so:

<div id="map_canvas" style="height:100%;"></div>

Add JavaScript to display the map

Add a script block with the JQuery document ready function so it runs when the page using this template is loaded:

<script>
   $(document).ready(function () {        
       // code goes here
   });
</script>

Now add the code to the function that creates the map, the makers and sets their positions.

First create the map object specifying the ’map_canvas’ div element as the element to load the map into.

var map = new google.maps.Map(document.getElementById('map_canvas'));

Next we write the JSON array into the html source of the page. To do this we use some server side code to embed the array we created earlier into the html, where it can be assigned to a JavaScript variable for use with the Google map code.

var markers = @Html.Raw(markerJsonArray);

All that’s left to do for this template is to loop through the marker JSON and create the markers, setting the bounds for the map at the same time.

if (markers && markers.length > 0) {
    var bounds = new google.maps.LatLngBounds();

    for (var i = 0; i < markers.length; i++) {
        var marker = new google.maps.Marker(markers[i]);
        marker.setMap(map);
        bounds.extend(marker.getPosition());
    }

    map.fitBounds(bounds);
    map.setCenter(bounds.getCenter());
}

The full template code

@{
    var locations = CurrentPage.Children("Location");
    var locationList = new List<string>();

    foreach (var location in locations)
    {
        locationList.Add(
           string.Format(
               @"{{""title"":  ""{0}"", ""position"": new google.maps.LatLng({1}, {2})}}",
               location.Name,
               location.Geocoder.latitude,
               location.Geocoder.longitude
           )
       );     }     var markerJsonArray = "[" + string.Join(",", locationList.ToArray()) + "]"; }
<html> <head> <title>@Umbraco.Field("pageName")</title> <script src="~/umbraco/lib/jquery/jquery.min.js"></script> <script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyC-sOLv-YADP4SK8kJZVFr0j8r2osSs8-k"></script> </head> <body>
<div id="map_canvas" style="height:100%;"></div>
<script>     $(document).ready(function () {         var map = new google.maps.Map(document.getElementById('map_canvas'));         var markers = @Html.Raw(markerJsonArray);         if (markers && markers.length > 0) {             var bounds = new google.maps.LatLngBounds();             for (var i = 0; i < markers.length; i++) {                 var marker = new google.maps.Marker(markers[i]);                 marker.setMap(map);                 bounds.extend(marker.getPosition());             }             map.fitBounds(bounds);             map.setCenter(bounds.getCenter());         }            }); </script> </body>
</html>

Create Locations content item

Now create a new content item called Locations using the Locations repository document type and the Locations repository template. It should now be possible to view location content items in the list view along with the option to create new ones. Add a few location content items to the repository and then browse to the URL of the page, you should see a Google map with markers for any locations that you have added.

See this code in action

Next article: Create a web service to expose location data

Comments

  • sam - 25/10/17 19:44

    Hello, Thanks for the great tutorial. I am wanting to use the map as a partial view so that it can be used in other parts of the site. how can I get the latitude and longitude using a Model.Content... query? I cant seem to separate the two values from the one property value. Thanks.

  • sam - 01/11/17 21:31

    I figured this out. instead of using Model.content I used Currentpage... and traversed the content tree for the data i needed.

To be able to comment you need to login using a Google or Facebook account.