Subscribe via RSS Feed Connect with me on LinkedIn

Experimenting with AngularJS in SharePoint Part 2

[ 8 ] September 5, 2013 |

If you haven’t checked out Part 1, please have a look. I’ve made some changes since then. I’ll be going over the changes here in Part 2.

First of all, I moved all of the AngularJS application code into its own javascript file. My ascx page is now simplified to look something like this:

<%@ Assembly Name="$SharePoint.Project.AssemblyFullName$" %>
<%@ Assembly Name="Microsoft.Web.CommandUI, Version=, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %> 
<%@ Register Tagprefix="SharePoint" Namespace="Microsoft.SharePoint.WebControls" Assembly="Microsoft.SharePoint, Version=, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %> 
<%@ Register Tagprefix="Utilities" Namespace="Microsoft.SharePoint.Utilities" Assembly="Microsoft.SharePoint, Version=, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
<%@ Register Tagprefix="asp" Namespace="System.Web.UI" Assembly="System.Web.Extensions, Version=, Culture=neutral, PublicKeyToken=31bf3856ad364e35" %>
<%@ Import Namespace="Microsoft.SharePoint" %> 
<%@ Register Tagprefix="WebPartPages" Namespace="Microsoft.SharePoint.WebPartPages" Assembly="Microsoft.SharePoint, Version=, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
<%@ Control Language="C#" AutoEventWireup="true" CodeBehind="VisualWebPart1.ascx.cs" Inherits="MyFirstVisualWebPart.VisualWebPart1.VisualWebPart1" %>
<script src="/_layouts/15/MyFirstVisualWebPart/angular.min.js"></script>
    var siteUrl = "<%= SPContext.Current.Web.Url %>";
<script src="/_layouts/15/MyFirstVisualWebPart/myngapp.js"></script>

<h1>My First Visual WebPart featuring Angular.js</h1>

<div ng-app="myApp">
    <div ng-controller="QuestionnaireCtrl">
            <li ng-repeat="question in questions">
                <br />
                <input type="text" ng-model="question.answer"/>
        <input type="submit" value="Submit" ng-click="addAnswers($event)"/>

I deployed the AngularJS library and myngapp.js into SharePoint’s layouts folder. Now I can make code changes to my Angular app without redeploying the web part. I declared my ng-app directive with a name of ‘myApp’ because I wanted to define a service (more details on this later).


myngapp.js is where the bulk of my changes were made. I cleaned up my controller a bit, and created a service that will perform the AJAX and JSOM calls into SharePoint.

Here is the code for my controller:

function QuestionnaireCtrl($scope, $SharePointJSOMService) {

    var promise = $SharePointJSOMService.getQuestions($scope, 'FoodQuestions');
    promise.then(function (data, status, headers, config) {
        $scope.questions = [];
        angular.forEach(, function (question) {
                text: question.Question,
                answer: ""
    }, function (data, status, headers, config) {
        console.log("Error " + status);

    $scope.addAnswers = function ($event) {

        var promise = $SharePointJSOMService.addAnswers($scope, 'FoodAnswers');

        promise.then(function (message) {
        }, function (reason) {
  • I am now using angular.forEach instead of underscore.js’s each function to iterate through my data result. Which resulted in me no longer requiring the use of underscore.js.
  • I added functionality to retrieve questions from a SharePoint list called FoodQuestions, and storing the answers in FoodAnswers. The questions are no longer hard coded.
  • I am dependency injecting my custom service called $SharePointJSOMService into my controller. This service returns a promise.

Here is the implementation of my custom service:

var myApp = angular.module('myApp', []);

myApp.service('$SharePointJSOMService', function ($q, $http) {
    // Store answers into SharePoint
    this.addAnswers = function ($scope, title) {
        var deferred = $q.defer();

        var valid = true;
        angular.forEach($scope.questions, function (que) {
            if (valid) {
                if (que.answer === "") {
                    valid = false;

        if (!valid) {
            deferred.reject('Please answer all the questions');
            return deferred.promise;

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

        angular.forEach($scope.questions, function (question, i) {
            // create the ListItemInformational object
            var listItemInfo = new SP.ListItemCreationInformation();
            // add the item to the list
            var listItem = list.addItem(listItemInfo);
            // Assign Values for fields
            listItem.set_item('Question', question.text);
            listItem.set_item('Answer', question.answer);
            listItem.set_item('Title', 'Question ' + (++i));


            Function.createDelegate(this, function () {
                $scope.$apply(function () {
                    var questions = $scope.questions;
                    angular.forEach(questions, function (question) {
                        question.answer = "";
                    deferred.resolve('Thank you, have a nice day.');
            Function.createDelegate(this, function () {
                scope.$apply(function (sender, args) {
                    deferred.reject('Request failed. ' + args.get_message() + '\n' + args.get_stackTrace());

        return deferred.promise;

    // Read from SharePoint List for Question
    this.getQuestions = function ($scope, listName) {
        var url = siteUrl + "/_api/web/lists/getByTitle('" + listName + "')/items?$select=Question";
        return $http({
            method: 'GET',
            url: url,
            headers: { "Accept": "application/json; odata=verbose" }
  • My service contains 2 functions getQuestions, and addAnswers
  • My service depends on 2 other services ($q and $http)
  • addAnswers looks similar to what I was doing in Part 1, in addition to a simple validation check to make sure every question is answered
  • getQuestions uses the $http service to make a SharePoint 2013 REST API call to get data from the requested list


I believe I’m still scratching the surface as to what AngularJS is capable of. I find it nice that AngularJS includes a number of commonly used tools in one library. I did not need to include jQuery to perform AJAX or promises. I did not need to include Knockout.js for data binding. I did not need to include underscore.js for handy utility functions. I also found some Twitter Bootstrap components written for AngularJS if you need some fancy front end stuff. Unfortunately, you will need to customize which Bootstrap css components to include in order to make it play nice with SharePoint.

Category: Blog, SharePoint 2013

About Jeff Yan: View author profile.

Comments (8)

Trackback URL | Comments RSS Feed

  1. Christo says:

    Great little two-part experiment. Makes for some interesting little apps inside of SharePoint. :)

  2. Raf says:

    Great article, Thnx !

  3. […] apart from Meligo’s post (which was a great starter to get the Todo app in my App) and Jeff Yan from Dynamic Owl. I really like what Jeff had done with the AngularJS Services to separate out the […]

  4. Jens says:

    Great post!

  5. Pavel says:

    It is very interesting code. I have some questions related to the reusability of this code (I didn’t try it, just wanted to know whether you did).

    What if you add 2 or more same web parts on the page, will it work?

    I am not even speaking about more complicated, but used often scenario, when user might want to have side by side “FoodQuestions” and let’s say “FoodQuestions2″.

  6. Pavel Brokhman says:

    It is very interesting and could work if we were speaking about 1 web part that is using angular. However, what you are going to do if you need more than one web parts on the same web page that uses angular or even the same web part twice, but with different lists.
    You create myApp within web part and if you are going to have another angular app on the page, only one is going to work.

    • Hi Pavel, our Bonzai product does this without issue. We have several web parts loaded onto the home page all using angular. The model is a bit different than the one written about here. We’re actually going to be doing some webinars where we walk through how we set this up. Check back here for an update on that. It’ll be the end of this month.

  7. Lara says:

    Hi, thank you very much with this valuable article!
    Everything works great for me, but my SharePoint site can’t create a list and not even store any information.
    Do you have any clue how can I fix that? :(

Leave a Reply

If you want a picture to show with your comment, go get a Gravatar.