How to: Use the SharePoint 2013 Client Object Model (SP.js) from a Client Web Part
Posted
Friday, October 19, 2012 1:13 PM
by
CoreyRoth
I was talking to Tom Resing (@resing) last week about using the SharePoint Client Object Model inside a Client Web Part and it became apparent that I left you all hanging with my last post. I got you to the point where you could build your web part, but referencing SP.js is not as simple as you would think it would be. I had to look at a lot of code samples to put this all together. This follow-up post will give you the necessary steps to get started working with SharePoint right away.
The first thing I do is add some script references to the page. For Client Web Parts, I tend to use a new .js file to host the web part’s JavaScript and I leave app.js to serve the needs of Default.aspx. Building on my example from the last post, I add a new script called HelloWorldClientWebPart.js. I add this in the Scripts folder.
We’ll add our code to this file in a minute but first I want to add those references. In this case, we aren’t loading a reference to SP.js yet. Instead, we’ll load jQuery from a CDN as well as MicrosoftAjax.js. You may not need all of those, but chances are you do.
<head>
<script type="text/javascript" src="../Scripts/jquery-1.6.2.min.js"></script>
<script type="text/javascript" src="//ajax.aspnetcdn.com/ajax/4.0/1/MicrosoftAjax.js"></script>
<script type="text/javascript" src="../Scripts/HelloWorldClientWebPart.js"></script>
</head>
Now we’ll jump over to our new script file. We’re going to borrow a few lines from App.js starting with variables to hold the context, web, and user.
var context;
var web;
var user;
Now we use jQuery’s document.ready function to add our code.
$(document).ready(
function () {
}
);
You can add this line to your document.ready function to get a reference to the SPSite object of the site hosting the client web part (app part) as opposed to the site actually hosting the app itself. We’ll also need it to get our reference to SP.js as well.
//Get the URI decoded SharePoint site url from the SPHostUrl parameter.
var spHostUrl = decodeURIComponent(getQueryStringParameter('SPHostUrl'));
This method relies on getQueryStringParameter which you’ll find in many App examples.
function getQueryStringParameter(urlParameterKey) {
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] == urlParameterKey)
return decodeURIComponent(singleParam[1]);
}
}
To get the host URL, you will have to modify your elements.xml to make this work. Do this by adding {standardtokens} to the URL of the Content element.
<Content Type="html" Src="~appWebUrl/Pages/HelloWorldClientWebPart.aspx?{StandardTokens}" />
When you do this, SharePoint will automatically pass you a number of query string parameters that you can take advantage of including the SPHostUrl. At that point you can pass the URL into your call to get a SPWeb object.
Back in the JavaScript file, we add the rest of our code. First we need to get the URL to the 15 folder inside _layouts and assign it to our layoutsRoot variable. Now we can use the jQuery getScript() method to retrieve the scripts we need. Before you get SP.js, you have to get SP.Runtime.js. That is why you see the nested calls below. Once SP.js can be retrieved, it makes a call to the execOperation method. This method can then take advantage of the SharePoint Client Object Model.
//Build absolute path to the layouts root with the spHostUrl
var layoutsRoot = spHostUrl + '/_layouts/15/';
$.getScript(layoutsRoot + "SP.Runtime.js", function () {
$.getScript(layoutsRoot + "SP.js", execOperation);
}
);
To demonstrate it’s use, we’ll use the same script example used in App.js. We start by defining execOperation and getting a reference to the content and SPSite object.
function execOperation() {
// get context and then username
context = new SP.ClientContext.get_current();
web = context.get_web();
getUserName();
}
We then use the same getUserName() and other functions from App.js.
function getUserName() {
user = web.get_currentUser();
context.load(user);
context.executeQueryAsync(onGetUserNameSuccess, onGetUserNameFail);
}
// This function is executed if the above OM call is successful
// It replaces the content of the 'welcome' element with the user name
function onGetUserNameSuccess() {
$('#message').text('Hello ' + user.get_title());
}
// This function is executed if the above OM call fails
function onGetUserNameFail(sender, args) {
alert('Failed to get user name. Error:' + args.get_message());
}
Putting the entire script together, here is what it looks like.
var context;
var web;
var user;
//Wait for the page to load
$(document).ready(
function () {
//Get the URI decoded SharePoint site url from the SPHostUrl parameter.
var spHostUrl = decodeURIComponent(getQueryStringParameter('SPHostUrl'));
//Build absolute path to the layouts root with the spHostUrl
var layoutsRoot = spHostUrl + '/_layouts/15/';
$.getScript(layoutsRoot + "SP.Runtime.js", function () {
$.getScript(layoutsRoot + "SP.js", execOperation);
}
);
// Function to execute basic operations.
function execOperation() {
// get context and then username
context = new SP.ClientContext.get_current();
web = context.get_web();
getUserName();
}
}
);
function getQueryStringParameter(urlParameterKey) {
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] == urlParameterKey)
return decodeURIComponent(singleParam[1]);
}
}
// This function prepares, loads, and then executes a SharePoint query to get the current users information
function getUserName() {
user = web.get_currentUser();
context.load(user);
context.executeQueryAsync(onGetUserNameSuccess, onGetUserNameFail);
}
// This function is executed if the above OM call is successful
// It replaces the content of the 'welcome' element with the user name
function onGetUserNameSuccess() {
$('#message').text('Hello ' + user.get_title());
}
// This function is executed if the above OM call fails
function onGetUserNameFail(sender, args) {
alert('Failed to get user name. Error:' + args.get_message());
}
Lastly, I update HelloWorldClientWebPart.aspx with a div to hold the results. Here is what the entire file looks like.
<%@ Register Tagprefix="WebPartPages" Namespace="Microsoft.SharePoint.WebPartPages" Assembly="Microsoft.SharePoint, Version=15.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
<WebPartPages:AllowFraming ID="AllowFraming1" runat="server" />
<head>
<script type="text/javascript" src="../Scripts/jquery-1.6.2.min.js"></script>
<script type="text/javascript" src="//ajax.aspnetcdn.com/ajax/4.0/1/MicrosoftAjax.js"></script>
<script type="text/javascript" src="../Scripts/HelloWorldClientWebPart.js"></script>
</head>
<div>
<h2>Hello World Client Web Part!</h2>
<div id="message"></div>
</div>
We can then execute the app in the debugger and then add the App Part to the root page of our developer site. It should look something like this when you’re done.
Sorry to leave you hanging like that on my previous blog post. I hope this helps you get started with your app. It’s a bit involved but not too bad. It would be nice to create a custom SharePoint Project Item that does this for us.
Come see my sessions at SPC12 and follow me on twitter @coreyroth.