Accessing BCS External Data From An App For SharePoint 2013
September 6, 2012
Introducing SharePoint Saturday Mobile!
September 19, 2012

One of the new features in SharePoint 2013 is the Geolocation field.  You can learn more about it here in the MSDN.  As I was developing some new SharePoint 2013 demos for my upcoming sessions at the SharePoint Connections Fall 2012 Conference I started looking into this new functionality.  My goal was to see how I could use the new Geolocation field type it to replace the Silverlight Bing Maps control I created for my SharePoint 2010 mashup demo.

As I went through the MSDN examples I saw that all of the examples and code samples use command line programs to create the Geolocation field and map-enabled list view that relies on the Geolocation field.  Personally, I’m not a fan of using command line tools when I develop solutions, I’d rather have something with a simple user interface that allows me to create new components quickly and easily without having to open a command prompt and remember the syntax associated with the command line program or a script.  If you have been following my blog for a while you’re probably familiar with the SharePoint Feature Manager I created about 6 years ago to manage features for a SharePoint site which falls into this same category.

So, along these lines, I decided to create a simple SharePoint Hosted App that allows me to easily specify which list I would like to add a Geolocation field to, give the Geolocation field a name, specify a name for the map-enabled list view that relies on the Geolocation field, and click a button or two to make everything for me.

This is also a fantastic way to roll out this functionality to your users and give them self service capabilities to create this type of functionality directly from a web browser.

It turned out to be a very easy exercise!  Here’s what the SP APP looks like.

image

Just fill in the values, click the buttons the Geolocation field, and the Geolocation column and the map-enabled view are created in the target list as you can see below.

image

image

Here’s what the new Map list view looks like.  That’s some pretty sweet out of the box functionality!

image

Here’s how I went about it.  First, I added some simple controls to the default.aspx page.

<%-- The following 4 lines are ASP.NET directives needed when using SharePoint components --%>
<%@ Page Inherits="Microsoft.SharePoint.WebPartPages.WebPartPage, Microsoft.SharePoint, Version=15.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" MasterPageFile="~masterurl/default.master" language="C#" %>
<%@ Register Tagprefix="SharePoint" Namespace="Microsoft.SharePoint.WebControls" Assembly="Microsoft.SharePoint, Version=15.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
<%@ Register Tagprefix="Utilities" Namespace="Microsoft.SharePoint.Utilities" Assembly="Microsoft.SharePoint, Version=15.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
<%@ Register Tagprefix="WebPartPages" Namespace="Microsoft.SharePoint.WebPartPages" Assembly="Microsoft.SharePoint, Version=15.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>

<%-- The markup and script in the following Content element will be placed in the <head> of the page --%>
<asp:Content ContentPlaceHolderId="PlaceHolderAdditionalPageHead" runat="server">
<script type="text/javascript" src="../Scripts/jquery-1.6.2.min.js"></script>

<!-- Add your CSS styles to the following file -->
<link rel="Stylesheet" type="text/css" href="../Content/App.css" />

<!-- Add your JavaScript to the following file -->
<script type="text/javascript" src="../Scripts/App.js"></script>

<!-- The following script runs when the DOM is ready. The inline code uses a SharePoint feature to ensure -->
<!-- The SharePoint script file sp.js is loaded and will then execute the sharePointReady() function in App.js -->
<script type="text/javascript">
$(document).ready(function () {
SP.SOD.executeFunc('sp.js', 'SP.ClientContext', function () { sharePointReady(); });
});
</script>
</asp:Content>

<%-- The markup and script in the following Content element will be placed in the <body> of the page --%>
<asp:Content ContentPlaceHolderId="PlaceHolderMain" runat="server">

<div>
List Name:<br /><input type="text" id="listName"/><p />
Geolocation Field Name:<br /><input type="text" id="fieldName"/><p />
View Name:<br /><input type="text" id="viewName"/><p />
<button id="createFieldButton" type="button" value="">Create Geolocation Field</button><p />
<button id="createViewButton" type="button" value="">Create Map View</button>
</div>

</asp:Content>

Then, I wrote the JavaScript to do the work and added it to the app.js file.

var context;
var web;
var user;
var field;
var view;

function sharePointReady() {
context = new SP.ClientContext.get_current();
web = context.get_web();

$("#createFieldButton").click(function () {
var fieldName = $("#fieldName").val();
createGeoLocationField(fieldName);
});

$("#createViewButton").click(function () {
var fieldName = $("#fieldName").val();
var viewName = $("#viewName").val();
createGeoLocationView(viewName, fieldName);
});
}

function createGeoLocationView(viewName, fieldName) {
spHostUrl = decodeURIComponent(getQueryStringParameter("SPHostUrl"));
rootClientContext = new SP.ClientContext(spHostUrl);
list = rootClientContext.get_web().get_lists().getByTitle($("#listName").val());

var viewCreationInformation = new SP.ViewCreationInformation();
viewCreationInformation.set_title(viewName);

var viewType = new SP.ViewType();
viewCreationInformation.set_viewTypeKind(viewType.html)

view = list.get_views().add(viewCreationInformation);

view.set_jsLink("mapviewtemplate.js");
view.get_viewFields().add("Location");

view.update();

rootClientContext.load(view);
rootClientContext.executeQueryAsync(
Function.createDelegate(this, this.onCreateGeoLocationViewSucceeded),
Function.createDelegate(this, this.onCreateGeoLocationViewFailed)
);
}

function onCreateGeoLocationViewSucceeded() {
var result = 'The view ' + view.get_title() + ' was successfully added.';
alert(result);
}

function onCreateGeoLocationViewFailed(sender, args) {
alert('Request failed. ' + args.get_message() +
'\n' + args.get_stackTrace());
}

function createGeoLocationField(fieldName) {
spHostUrl = decodeURIComponent(getQueryStringParameter("SPHostUrl"));
rootClientContext = new SP.ClientContext(spHostUrl);
list = rootClientContext.get_web().get_lists().getByTitle($("#listName").val());
field = list.get_fields().addFieldAsXml(
'<Field DisplayName=\'' + fieldName + '\' Type=\'Geolocation\' />',
true,
SP.AddFieldOptions.defaultValue
);

rootClientContext.load(field);
rootClientContext.executeQueryAsync(
Function.createDelegate(this, this.onCreateGeoLocationFieldSucceeded),
Function.createDelegate(this, this.onCreateGeoLocationFieldFailed)
);
}

function onCreateGeoLocationFieldSucceeded() {
var result = 'The GeoLocation field ' + field.get_title() + ' was successfully added.';
alert(result);
}

function onCreateGeoLocationFieldFailed(sender, args) {
alert('Request failed. ' + args.get_message() +
'\n' + args.get_stackTrace());
}

function getQueryStringParameter(paramToRetrieve) {
var params =
document.URL.split("?")[1].split("&");
var strParams = "";
for (var i = 0; i < params.length; i = i + 1) {
var singleParam = params[i].split("=");
if (singleParam[0] == paramToRetrieve)
return singleParam[1];
}
}

It’s pretty simple, as you can see.  Hopefully this helps you out and gives some ideas that you can use to create your own SP APPs.

It’s already snowing at the ski resorts in Colorado!  Opening day shouldn’t be more than 30 days away at some of them!