SharePoint Features are Lame, Go Client-Side with AngularJS


Traditional SharePoint development feels like a root canal gone wrong. It's chocked full of confusing acronyms, sluggish performance and deployments, and tools that crash without warning (thanks SP Designer). Luckily, Javascript libraries like AngularJS can remove some of the irritable development syndrome from the process.

In this tutorial, I'll show you a relatively simple way to pull data from a SPList and render it using Javascript, HTML, and the SharePoint FormWebPart.

Build the data service

Let's start with pulling data from SharePoint. I chose to use SharePoint's SOAP client library because this example works with 2010, but if you're on 2013, SharePoint's REST API may be a better choice.

Setup the promise and fetch your SPList

The following method sets up a SharePoint SOAP client context to start pulling data from a specified SPSite and SPList.

getList: function (siteUrl, listTitle) {

    var deferred = $q.defer();

    var clientContext = new SP.ClientContext(siteUrl);
    var web = clientContext.get_web();
    var list = web.get_lists().getByTitle(listTitle);

Query for all the list's items

var items = list.getItems(SP.CamlQuery.createAllItemsQuery());


    clientContext.executeQueryAsync(onQuerySucceeded, onQueryFailed);

NOTE: I'm grabbing all the list items, but you can easily modify the CAML Query to fetch specific ones.

Query success handler

function onQuerySucceeded() {

        var data = [], itemEnumerator = items.getEnumerator();

        // Iterate through returned list items
        while (itemEnumerator.moveNext()) {

            var item = itemEnumerator.get_current();
            var obj = {};

            // Map returned data to object
            obj['title'] = item.get_item('Title');

            // Add to collection


I decided to manually map the each of the list item's columns to the collection that's returned. I'm sure that there are better ways to map that data.

Query failure handler

function onQueryFailed(sender, args) {
        alert('Failed to get list. Error:' + args.get_message());


    return deferred.promise;

Configure your ng app and controller logic

This app consists of one module and one controller. In it's simplest form, the controller loads the SharePoint list and renders those items into the view.

The key when attempting to use the SharePoint SOAP service is to use the ExecuteOrDelayUntilScriptLoaded() function to initiate querying SharePoint. This ensures that all the necessary dependencies are ready to rock.

Here's the main guts of the controller in detail:

$(document).ready(function() {
  ExecuteOrDelayUntilScriptLoaded(loadListItems, 'sp.js');

function loadListItems() {

  // Query DataService to fetch parsed SPList data

    // On success
    function(data) {

      // Set returned degree collection
      $scope.listItems = data;


    // On failure
    function(reason) {
      console.log('DataService getList() failed: ', reason);


Create the FormWebPart HTML

Upload and Reference your JS files

<script src="" type="text/javascript"></script> 
<script src="../Documents/Styles_Scripts/MainCtrl.js" type="text/javascript"></script> 
<script src="../Documents/Styles_Scripts/data.js" type="text/javascript"></script>

As you notice the path references, you can choose to use a CDN for your angular script and a local relative path for my two custom scripts. I typically upload them to the Styles & Scripts library found under Documents in the same SPSite where the app lives.


<div ng-app="app"> <div ng-controller="MainCtrl" ng-init="'init()'"> <div ng-repeat="item in listItems"> {{item.title}} </div> </div> </div>

Add a FormWebPart to your web part zone and then drop the snippet into it. Finally, check-in and publish your page. Refresh and test.

One Caveat

If you're using this approach to display data on a public-facing website, you will need your farm administrator to grant all read privileges on your SPList or else permissions will block the client from being able to pull data for non-sessioned users.


Here's a zipped up demo for you to get started with.

Stay Connected

Join us on our social networks for all the latest updates, announcements and more.


> Follow Us


> Connect