Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / web / ASP.NET

Sharepoint OnLine and AngularJS

4.17/5 (3 votes)
16 Feb 2015CPOL2 min read 23.6K   9  
A Sample using AngularJS with Sharepoint OnLine

Introduction

When I had some downtime, I wanted to create a sample using AngularJS framework to display list items from a SharePoint Online site.  I have seen some of the angular demonstrations and I was drawn to the idea of breaking up javascript into self contained modules that can be unit tested.  The result is a very clean easy to read and maintain javascript code base.  

This article will touch on some of the nuances I found when using AngularJS with Sharepoint and Sharepoint Online.

Background

There are a few things I found with AngularJS framework which is very different from other javascript frameworks.  The learning curve.  It is very easy to write an Angular application with very little knowledge of the framework unlike BackBone.js.  However, it very hard to write a hard core serious Angular application.  The documentation is either incomplete or lacking.  Don't be frustrated, just keep on plugging away.

Using the code

AngularJS Service

Creation of the service

Here we create the service within the SharePointJSOMService.js file and grab the user information from sharepoint using a rest call

JavaScript
myApp.service('SharePointJSOMService', function ($q, $http) {
    this.getCurrentUser = function () {
        var deferred = $.Deferred();
        //First we must call the EnsureSetup method
        JSRequest.EnsureSetup();
        hostweburl = decodeURIComponent(JSRequest.QueryString["SPHostUrl"]);
        appweburl = decodeURIComponent(JSRequest.QueryString["SPAppWebUrl"]);

        var userid = _spPageContextInfo.userId;
        var restQueryUrl = appweburl + "/_api/web/getuserbyid(" + userid + ")";

        var executor = new SP.RequestExecutor(appweburl);
        executor.executeAsync({
            url: restQueryUrl,
            method: "GET",
            headers: { "Accept": "application/json; odata=verbose" },
            success: function (data, textStatus, xhr) {
                deferred.resolve(JSON.parse(data.body));
            },
            error: function (xhr, textStatus, errorThrown) {
                deferred.reject(JSON.stringify(xhr));
            }
        });
        return deferred;
    };

Creation of the list in the Host Web

The following function will grab the context of the host web and create a list.  Remember, you have to specify the application to have access to the host web in your AppMainifest.xml file.

JavaScript
this.createList = function ($scope, listTitle) {
        var deferred = $.Deferred();
        //First we must call the EnsureSetup method
        var hostUrl = decodeURIComponent(getQueryStringParameter("SPHostUrl"));


        var currentcontext = new SP.ClientContext.get_current();
        var hostcontext = new SP.AppContextSite(currentcontext, hostUrl);
        var hostweb = hostcontext.get_web();

        //check list exists
        var lists = hostweb.get_lists();
        currentcontext.load(lists);
        currentcontext.executeQueryAsync(
            function () {
                var isListAvail = false;
                var listEnumerator = lists.getEnumerator();
                while (listEnumerator.moveNext()) {
                    list = listEnumerator.get_current();
                    if (list.get_title() == listTitle) {
                        isListAvail = true;
                        deferred.done("success list already exists");
                    }
                }
                if (isListAvail != true) {
                    //create the list
                    var listCreationInfo = new SP.ListCreationInformation();
                    listCreationInfo.set_title(listTitle);
                    listCreationInfo.set_templateType(SP.ListTemplateType.tasks);
                    var list = hostweb.get_lists().add(listCreationInfo);
                    currentcontext.load(list);
                    currentcontext.executeQueryAsync(
                        function () {
                            deferred.done("created list");
                        },
                        function (sender, args) {
                            deferred.reject('Request failed. ' + args.get_message() + '\n' + args.get_stackTrace());
                        }
                    );
                }
            },
            function (sender, args) {
                deferred.reject('Request failed. ' + args.get_message() + '\n' + args.get_stackTrace());
            }
        );

        return deferred;
    };

 

Retrieval of the List

The following function will use a REST call to retrieve information from the list within the hostweb

JavaScript
this.getTasksREST = function ($scope, listTitle) {
       var deferred = $.Deferred();
       //First we must call the EnsureSetup method
       JSRequest.EnsureSetup();
       hostweburl = decodeURIComponent(JSRequest.QueryString["SPHostUrl"]);
       appweburl = decodeURIComponent(JSRequest.QueryString["SPAppWebUrl"]);

       var restQueryUrl = appweburl + "/_api/SP.AppContextSite(@target)/web/lists/getByTitle('" + listTitle + "')/items?$select=Title,ID,DueDate,Status,Priority&@target='" + hostweburl + "'";

       var executor = new SP.RequestExecutor(appweburl);
       executor.executeAsync({
           url: restQueryUrl,
           method: "GET",
           headers: { "Accept": "application/json; odata=verbose" },
           success: function (data, textStatus, xhr) {
               deferred.resolve(JSON.parse(data.body));
           },
           error: function (xhr, textStatus, errorThrown) {
               deferred.reject(JSON.stringify(xhr));
           }
       });
       return deferred;
   };

 

AngularJS Controller

Creation of the controller

The creation of the controller by passing in the scope and SharePointJSOMService objects

JavaScript
myApp.controller('ListCtrl', ['$scope', 'SharePointJSOMService', function ($scope, SharePointJSOMService) {
    SP.SOD.executeOrDelayUntilScriptLoaded(runDelayedCode, "SP.js");
    function runDelayedCode() {
        $scope.tasks = [];

        // grab current user from web service
        // place it in scope
       $.when(SharePointJSOMService.getCurrentUser())
          .done(function (jsonObject) {
              currentUser = jsonObject.d;
              $scope.currentUser = currentUser;
              //scope was not updated so we need to push it in
              if (!$scope.$$phase) { $scope.$apply(); }
          })
          .fail(function (err) {
              console.info(JSON.stringify(err));
          });

Default.aspx Page

The default.aspx will create the AngularJS application and bind to the list items.  It is a very clean binding.

HTML
<div ng-app="myApp">

        <div ng-controller="ListCtrl">


        <div>
            Find current user from _api/webs/getuserbyid using angular service
            <h1>Welcome: {{currentUser.Title}}</h1>
        </div>

             <ul class="unstyled">
            <li class="row" ng-repeat="task in tasks">
                 <input type="checkbox" ng-model="task.done" />
                 <span class="done-{{todo.done}}">{{task.text}}</span>
            </li>
                 </ul>


    </div>



</div>

App.js

The App.js file will set up some global variables for use in the default.aspx page

JavaScript
'use strict';
var TaskListName = 'testlist';
var myApp = angular.module('myApp', ['ui.bootstrap']);

var hostweburl;
var appweburl;
var currentUser;

Points of Interest

Some examples loaded the sharepoint js files by using the following tags in the default.aspx page

HTML
<SharePoint:ScriptLink name="sp.js" runat="server" LoadAfterUI="true" Localizable="false" />    
<SharePoint:ScriptLink name="sp.runtime.js" runat="server" LoadAfterUI="true" Localizable="false" />

I found that had the side effect of inconsitent list creation in the host web.  The error was "Unexpected Response From Server" with a null stack trace.  To fix the issue, I went with the following javascript includes

HTML
<script type="text/javascript" src="/_layouts/15/sp.runtime.<wbr />js"></script>
<script type="text/javascript" src="/_layouts/15/sp.js"></<wbr style="color: rgb(34, 34, 34); font-family: Calibri, sans-serif; font-size: 14.6666669845581px; background-color: rgb(255, 255, 255);" />script>

 or within my javascript

JavaScript
$.getScript(scriptbase + "SP.Runtime.js",
            function () {
                $.getScript(scriptbase + "SP.js",
                    function () {
                        $.getScript(scriptbase + "SP.RequestExecutor.js", 
                             function () {

 

History

Version 1, just binding

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)