In Part 1 we created a fully interactive Bing Map into a SharePoint-hosted app and deployed it to the host web. Now it’s time to explore some of the capabilities with Bing Maps and use them together with data stored in SharePoint.
An interactive map without a location search interface, is a sad map. The Bing Maps Ajax control does not have this functionality itself, but you can easily implement it to your application by using the Bing Map REST Services.
In this demo we are going to create a simple search functionality, where the user enters a geolocation, then the input data will be passed to the Bing service . If found, the service returns the position to the map which changes its view to put the location in the center.
The first thing we will do is to create a text field and a button for the user to enter and submit searches. Open up the default.aspx file in the project we created in part 1. Add the following code after the <div id=”mapDiv”> tag:
Next, add the controls style class and update the map style class in the App.css file as follows:
Open up App.js and define the following global variables at the top of the file:
Add the Search button onclick event handler function to App.js:
The map.getCredentials() call requires some explanation. The key thing is that Bing REST Services also require the Bing Maps key, so this function call is used to retrieve the key from the map object to make sure the Maps and the Service are running in the same session. The requestLocation parameter is a callback function which is called after the getCredentials() function has completed.
To support the functionality above, we have to do some changes to the LoadMap function we created in the first part. Edit it to look as follows:
Next, add the requestLocation() callback function:
The other section of the function appends a <script></script> tag to the body element, setting the source to the loc REST service call string we just created.
What remains to be done is to add the locationCallback() function which is invoked when the REST service call returns. This function will first test and validate the return location string, then it will use the boundary data in the location string to define and update the map view’s boundaries, resulting in the found location being centered on the map. Finally we grab the coordinates and add a pin to mark the location
Build and deploy your project, then open SharePoint and launch the app. Enter a location in the input box below the map and press Search. If everything goes well, the requested location is found by the service and centered onto the map. Try experimenting with different locations, like rivers, buildings, addresses etc.
Interfacing with the Host web.
Now it’s time to add some SharePoint-ness to the project. We are going to load a set of locations from a list in the SharePoint host into the map. So go ahead create a new custom List, name it Locations, and optionally add other columns to add some simple metadata to the locations. My list looks like this (the last item is the address of one of Google’s offices in Austin, Texas):
There are lots of other sites and blogs describing how a SharePoint app interacts with the SharePoint host so I won’t go into those details here. My favourite resource is of course Microsoft themselves, so if you want to dig into the details, here’s a good starting point: http://msdn.microsoft.com/en-us/library/jj163230.aspx
By default an app does not have permissions to access resources on the host. To be able to do that you must define your permissions requests in the app manifest. For this exercise we just need read access to lists so open the AppManifest.xml file in the project. In the Permission Requests section, click inside the Scope column and select Web and in the Permission column, select Read . Add another Read permission for the List scope.
Now, open default.aspx and add a new button under the Search button definition as follows:
<input type=”button” value=”Mark locations from list” onclick=”getLocationsFromList()” />
Due to a possible bug when using SPHostUrl ( explained in a blog post by Chris O’Brien ), we need to preserve the SPHostUrl and SPAppWebUrl parameters during load. These are provided to the app during launch from the host site via the query string and hold the host web and the app web url respectively. First let’s add a function that parses the querystring:
Also add 2 global variables, hostWebUrl and appWebUrl to the top of the list. Then add the 2 following lines at the beginning of the sharePointReady() function:
Next, add the getLocationsFromList() event handler in App.js:
This function uses CSOM to read the contents from the Locations list, using a CAML query to filter the Title field.
Before adding the callback functions, add a global variable named allItems at the top of the file .
Then add the 2 callbacks invoked from executeQueryAsync() .
The success() function reads each Title field and calls getLocations() . This function in turn calls requestLocations() in order to request the locations from the Bing REST Service. These 2 functions are more or less identical to the requestLocation() and getLocation() functions defined previously. The only difference is requestLocations() taking a list item field as input. A potential reusability here, but I haven’t put much focus on it, so I leave that part as an exercise for the reader. The 2 functions are defined as follows:
As you can see the same locationCallback function is used in requestLocations() to pin the locations to the map.
Finally add another global variable named locations to the top of the file to hold the location names.
Rebuild and deploy the app. Launch it on your SharePoint test site and press the Mark locations from List button . Then zoom out the map and verify that all the locations defined in the list have got pushpins in the correct positions on the map.
That was all for now; I hope some of you have found this interesting. In Part 3 we will be looking at getting route directions between 2 points defined in a list, and we will use the response information provided by the service to update other fields in the same list.