Using the JavaScript object model (JSOM) in apps for SharePoint


Hi! My name is Ricardo Loo. I am a Programming Writer for SharePoint. In today’s article we’ll talk about how to use the JavaScript object model (JSOM) in a simple HTML page in your app for SharePoint. By using the JSOM, you can access data and functionality in SharePoint 2013. You can also use Representational State Transfer (REST) endpoints to access data. The choice depends on various factors such as your abilities or development platform. For more information, see Choose the right API set in SharePoint 2013.

To keep things simple and short, I am using an app page hosted in SharePoint—but remember that you can also use the JSOM if your pages are not hosted in SharePoint. To access the objects using the JSOM in pages not hosted in SharePoint, you can use the cross-domain library (we’ll post more information about the cross-domain library in a subsequent article.)

To use the JSOM, you must follow these steps:

1. Reference the required libraries.

2. Get a client context instance and load SharePoint objects.

3. Execute the query and provide callback functions.

Reference the required libraries

Before using the JSOM you must reference the following libraries, in this order:

1. ASP.NET Ajax library

2. sp.runtime.js file

3. sp.js file

When the app pages are hosted in SharePoint, you can use relative paths to the required files. The following script tags show you how to reference the required libraries in a page hosted in SharePoint:

<script 
type="text/javascript"
src="//ajax.aspnetcdn.com/ajax/4.0/1/MicrosoftAjax.js">
</
script>
<
script type="text/javascript" src="_layouts/15/sp.runtime.js"></script>
<
script type="text/javascript" src="_layouts/15/sp.js"></script>
<
script type="text/javascript">
// Continue your program flow here.
</script>

Get a client context and load the objects

To access the objects in the JSOM, you first need an instance of the client context. You can get an instance of SP.ClientContext by using the get_current() method. Now, we have an access point (the client context) to the objects in SharePoint. As you probably imagine, you must issue a query to get the specific objects you need.

What’s next? Let’s create a list. You can use lists in the app web to provide storage for your app. For example, you can use a list to store user data or some other information. Whether you use lists or another type of storage depends on how you design your app. For more information, see Data storage options in apps for SharePoint.

The following code shows how to get an instance of the client context and load the required objects to create a list:

var clientContext; 
var listCreationInfo;
var web;
var list;

clientContext = SP.ClientContext.get_current();
web = clientContext.get_web();
listCreationInfo =
new SP.ListCreationInformation();
listCreationInfo.set_title(
"User data");
listCreationInfo.set_templateType(SP.ListTemplateType.genericList);
list = web.get_lists().add(listCreationInfo);

clientContext.load(list);

Execute the query and provide callback functions

Now, you are ready to send the query to SharePoint and get your list created. You can send your query by using the executeQueryAsync method in the client context object. You should provide callback functions to handle the success and failure events. The following code shows how to use the executeQueryAsync method and provide callback functions for the success and failure events:

clientContext.executeQueryAsync(
function () { alert("Success!") },
function () { alert("Request failed") }
);

Great! So… where is your list?

To see your list, just go to the following URL:

app_web/Lists/User%20data

clip_image002[6]

Figure 1. List created using the JSOM

Easy! Well, I think that is enough for one post. I hope you found it useful to get up and started using the JSOM in your apps for SharePoint.

Beyond this article

  • About the tools used for this article: I wrote the code for this article on my home computer. I don’t have Visual Studio or SharePoint installed on that computer. I just used the “Napa” Office 365 Development Tools. You can sign up for Office 365 and install the “Napa” app in your developer website. Then you can build apps just like the one explained in this article, using only your browser. For the full instructions, see Sign up for an Office 365 Developer Site.
  • About storage in real-world apps: You can check for apps that handle data in real-world scenarios by browsing the Office Store. The Customer Orders and Products app is a good example of a real app that handles and stores data.
  • About more operations using the JSOM: The example in this article is a very simple one. I chose creating a list to demonstrate how to use the JSOM. You can find many more operations in the article How to: Complete basic operations using JavaScript in SharePoint 2013.

Let us know what other topics you would like us to talk about by using the comments section below. Thanks for your time!

Comments (24)

  1. Ricalo says:

    Some people has been hitting the following error when using the JSOM:

    0x800a1391 – JavaScript runtime error: 'Type' is undefined in the sp.runtime.js file.

    The code breaks at this line:

    Type.registerNamespace("SP");

    This error is usually fixed by adding the reference to MicrosoftAjax:

    <script type="text/javascript" src="//ajax.aspnetcdn.com/ajax/4.0/1/MicrosoftAjax.js">

    </script>

    Hope this helps somebody

  2. Mikey says:

    If you're inside of SharePoint (i.e. a SharePoint-Hosted App, and not an Autohosted App) the correct way to reference sp.js, etc is as follows:

    <SharePoint:ScriptLink ID="ScriptLink1" Name="sp.js" runat="server" OnDemand="true" LoadAfterUI="true" Localizable="false" />

    <SharePoint:ScriptLink ID="ScriptLink2" Name="SP.UI.Dialog.js" runat="server" OnDemand="true" LoadAfterUI="true" Localizable="false" />

    You can do this in your header's content control.

  3. Mikey says:

    Also the correct way to register MicrosoftAjax.js is to use the ScriptManager tag, if you prefer to use the cdn, set EnableCdn="true":

    <asp:ScriptManager ID="ScriptManager1" runat="server" EnableCdn="true" />

    (If your page already has one [i.e. included from the MasterPage], you can register a ScriptManagerProxy instead.)

  4. Ricalo says:

    Great info for ASP.NET developers, Mikey. Thank you!

    Developers writing apps on other platforms should use the standard script tags or whatever mechanisms your platform offers.

  5. Manan says:

    Hey its very nice post. I got the list created but how to add field from the code. I want to create 2 column while creating list. Is it possible?

  6. Shekar says:

    I Added Reference to MicrosoftAjax.js and it is loaded correctly but still im getting the same error, 'Type' is undefined

  7. BHarat Sukhwal says:

    hi,

    I want to use JSOM in the provider hosted app web site. Is this possible. Because i ma using the below code and its giving the below error

    SCRIPT5009: 'Type' is undefined

    SP.Runtime.js, line 2 character 129

    Code :

    function loadDependentScripts() {

       var scriptbase = hostweburl + "/_layouts/15/";

       // Load the js files and continue to the successHandler

       $.getScript(scriptbase + "SP.Runtime.js",

           function () {

               $.getScript(scriptbase + "SP.js",

                   function () { $.getScript(scriptbase + "SP.RequestExecutor.js", runCode); }

                   );

           }

       );

    }

    $(document).ready(function () {

       hostweburl = decodeURIComponent(getQueryStringParameter("SPHostUrl"));

       //appweburl = decodeURIComponent(getQueryStringParameter("SPAppWebUrl"));//No SPAppWebURL in query string

       appweburl = decodeURIComponent(getQueryStringParameter("SPHostUrl"));

       // resources are in URLs in the form:

       // web_url/_layouts/15/resource

        scriptbase = hostweburl + "/_layouts/15/";

        loadDependentScripts();

    });

    function runCode() {

       loadUser();

    }

    function loadUser() {

       var ctx = new SP.ClientContext.get_current();

       user = ctx.get_web().get_currentUser();

        ctx.load(user);

       ctx.executeQueryAsync(onGetUserNameSuccess, onGetUserNameFail);

    }

    function onGetUserNameSuccess() {

           fetchedUserName = 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());

    }

    function getQueryStringParameter(param) {

       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] == param) {

               return singleParam[1];

           }

       }

    }

    Please help me if its possible in provider hosted app.

    Thanks

  8. Ricalo says:

    Bharat,

    Did you add the reference to MicrosoftAjax.js mentioned in the previous comments? That should solve the "Type is undefined" error

  9. Raghu says:

    I am trying to create site columns and later create content types ( using the site columns created ). The content types have dependencies on few content types that we should create. I am trying this using jquery deferred but I am unable to sequence them as required. Can you  please help me with the creating site columns and content types.

  10. Jean says:

    I'm developing an app for sharepoint and I m trying to get list items on sharepoint. It works successful when I load the page for the first time but when I open another page and I want to return on the first page for the second time, I'm getting this error :

    "JavaScript runtime error: Unable to get property 'split' of undefined or null reference"

    here is the code :

    var hostweburl;

    var appWebUrl;

    $(document).ready(function () {

       //Get the URI decoded URLs.

      hostweburl = decodeURIComponent(

              getQueryStringParameter("SPHostUrl"));

      appWebUrl = decodeURIComponent(

              getQueryStringParameter("SPAppWebUrl"));

       // Load the js file and continue to the

       //   success event

       $.getScript("../_layouts/15/SP.RequestExecutor.js", execCrossDomainRequest);

    });

    // Function to prepare and issue the request to get

    //  SharePoint data

    function execCrossDomainRequest() {

       // Initialize the RequestExecutor with the app web URL.

       executor = new SP.RequestExecutor(appWebUrl);

       // Issue the call against the host web.

       // To get the title using REST we can hit the endpoint:

       //   app_web_url/_api/SP.AppContextSite(@target)/web/title?@target='siteUrl'

       // The response formats the data in the JSON format.

       // The functions successHandler and errorHandler attend the

       //      success and error events respectively.

       executor.executeAsync(

           {

               url:

       appWebUrl + "/_api/SP.AppContextSite(@target)/web/Lists/GetByTitle('video')/items?@target='" +

                   hostweburl+"'",

               method: "GET",

               headers: { "Accept": "application/json; odata=verbose" },

               success: successHandler,

               error: errorHandler

           }

       );

    }

    // Function to handle the success event.

    // Prints the host web's title to the page.

    function successHandler(data) {

       var jsonObject = JSON.parse(data.body);

      // code to run…

    }

    }

    // Function to handle the error event.

    // Prints the error message to the page.

    function errorHandler(data, errorCode, errorMessage) {

       document.getElementById("table").innerText =

           "Could not complete cross-domain call: " + errorMessage;

    }

    // Function to retrieve a query string value.

    // For production purposes you may want to use

    //  a library to handle the query string.

    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 decodeURIComponent(singleParam[1]);

       }

    }

  11. Matt says:

    Great Post, very helpful. Thanks…

  12. Ricalo says:

    Jean,

    My guess is that when you're going back to your page, the URL doesn't contain the query string parameters anymore.

    It's probably failing in this line:

    var params = document.URL.split("?")[1].split("&");

    When you go back to the original page make sure that the URL contains a ? and some parameters after that. If it doesn't have it, you must implement a mechanism to handle empty parameters, or you must make sure that all the pages pass the query string to the other pages when the user is navigating through the app pages.

  13. Rajesh says:

    I am trying to access data inside excel through Excel services REST APi from a Sharepoint hosted app. Both the app and the excel file are hosted in the same site. The app is installed in:

    http://<site-name&gt;.Sharepoint.com/<sitecollection-name>/<App-Name>

    and the excel i am trying to access is located on the same site collection as above inside documents library.

    http://<site-name&gt;.Sharepoint.com/<sitecollection-name>/_vti_bin/ExcelRest.aspx/Shared Documents/Test1.xlsx/Model/Tables('table1')

    I am able to get the data from the below thru browser. But when i access the same thru app i get the error "Invalid field or parameter requestInfo.url.". Below is the code:

    $(document).ready(function () {

    hostweburl =

           decodeURIComponent(

               getQueryStringParameter("SPHostUrl")

       );

    appweburl =

               decodeURIComponent(

                   getQueryStringParameter("SPAppWebUrl")

           );

    var scriptbase = hostweburl + "/_layouts/15/";

       // Load the js files and continue to the successHandler

    $.getScript(scriptbase + "SP.Runtime.js",

               function () {

                   $.getScript(scriptbase + "SP.js",

                       function () { $.getScript(scriptbase + "SP.RequestExecutor.js", execCrossDomainRequest); }

                       );

               }

               );

    });

       // Function to prepare and issue the request to get

       //  SharePoint data

    function execCrossDomainRequest() {

       // executor: The RequestExecutor object

       // Initialize the RequestExecutor with the app web URL.

       var url1 = hostweburl + "/_vti_bin/ExcelRest.aspx/Shared Documents/Test1.xlsx/Model/Tables('table1')?$format=json";

           var executor = new SP.RequestExecutor(appweburl);

       executor.executeAsync(

               {

                   url: url1,

                   //"/_api/web/lists",

                   method: "GET",

                   headers: { "Accept": "application/json; odata=verbose" },

                   success: successHandler,

                   error: errorHandler

               }

           );

  14. Jon says:

    Is the abbreviation "JSOM" an official Microsoft term? I couldn't find this in the msdn.

  15. Ricalo says:

    More than an official term it is an acronym that we use to make it easier to read articles like this one.

    As a rule of thumb, we define the term early in the article, like JavaScript object model (JSOM), and then use the short version through the rest of the article.

    The acronym is widely used on MSDN content, for example:

    msdn.microsoft.com/…/dn268594(v=office.15).aspx

    msdn.microsoft.com/…/jj907313(v=office.15).aspx

  16. Aldo Martinez says:

    Hello Ricardo, nice to read some post from you!  

    I'm using Sharepoint 2013 and I'm working with JSOM. I need to read 3 different Sharepoint lists on my masterpage. It's working perfectly when I only have one, but not good when I add a new one.

    Do I need to get a client context instance and load SharePoint objects for each one?

    How to execute 2 or more asynchronous querys?

    do you have some examples I can take a look? do you suggest use something different than JSOM for doing this? I'm applying branding to my homepage and some data is coming from lists that user can configure

    Thanks!

  17. dev says:

    Hi, I am trying to upload a document in office 365 using CSOM and javascript but its not happening.

    Please help.

  18. Cubalibre says:

    Yeah me 2 dev. I just a HTML page with a fileupload control to be able to crate a document in SharePoint online. I've tried everything but nothing works… 🙁 MSFT HELP

  19. Paul says:

    Hello Ricardo  – Can you please help me to learn the cross domain library to use JSOM for those pages which are not hosted in SharePoint?

  20. Ricalo says:

    dev, Cubalibre…

    If you want to add a file to a document library using cross-domain library take a look at the following file.

    code.msdn.microsoft.com/…/sourcecode

    It uploads a file by hitting the following endpoint

    fileEndpoint = appweburl + "/_api/SP.AppContextSite(@target)/web/lists(listid)/rootfolder/files/add(url' bookTitle.txt')?@target='hostweburl';

       fileContent = document.getElementById("content").value;

  21. netdev2000 says:

    Hi Ricardo,

    Need help.

    I created a developer site in SharePoint online.

    I have added an asp text box and an asp button in default.aspx.

    Then I downloaded the site to local computer to edit in Visual Studio 2013.

    Now I want to add the functionality of writing the data entered in the text box to a SQL table once the button is clicked.

    Is it possible?

    Thanks in advance.

    Regards,

    Dave

  22. Ricalo says:

    Hi Dave,

    Sorry it took so long to get back to you. We're not monitoring this blog anymore. May I suggest using stackoverflow.com? Use SharePoint and Office365 tags.

    Regarding your question, you shouldn't try to add server-side code to your solutions, if you can updated the SQL table with client-side code then you should be okay.

  23. Ashraf Alhaj says:

    Great Post