Subscribe via RSS Feed Connect with me on LinkedIn

Experimenting with AngularJS inside a SharePoint Visual Web Part

[ 3 ] August 22, 2013 |

One day, I was having breakfast with a JavaScript guru buddy of mine and I asked him, what is the latest development trend on the web these days? One of the things he mentioned was¬†AngularJS by Google. That got me thinking… can I use this in SharePoint some how? Well, outlined below is my little experiment with AngularJS inside a SharePoint Visual Web Part.

Start a new Visual Web Part project

I’ll be deploying my project to SharePoint 2013, so here is a screenshot of the Visual Studio 2012 New Project wizard. I’ll be deploying the project as a farm solution because I’ll need to deploy some JavaScript files to the LAYOUTS directory.

Once the project is ready, there should a file called VisualWebPart1.ascx created. This is where all the magic happens. Lets add ‘Hello World’ to it, and deploy.

VisualWebPart1.ascx Hello World

<%@ Assembly Name="$SharePoint.Project.AssemblyFullName$" %>
<%@ Assembly Name="Microsoft.Web.CommandUI, Version=15.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
<%@ Register Tagprefix="SharePoint" Namespace="Microsoft.SharePoint.WebControls" Assembly="Microsoft.SharePoint, Version=15.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
<%@ Register Tagprefix="Utilities" Namespace="Microsoft.SharePoint.Utilities" Assembly="Microsoft.SharePoint, Version=15.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
<%@ Register Tagprefix="asp" Namespace="System.Web.UI" Assembly="System.Web.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" %>
<%@ Import Namespace="Microsoft.SharePoint" %>
<%@ Register Tagprefix="WebPartPages" Namespace="Microsoft.SharePoint.WebPartPages" Assembly="Microsoft.SharePoint, Version=15.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
<%@ Control Language="C#" AutoEventWireup="true" CodeBehind="VisualWebPart1.ascx.cs" Inherits="MyFirstVisualWebPart.VisualWebPart1.VisualWebPart1" %>

Hello World

Add Web Part to Page

Add the Visual Web Part to a Page. If you see Hello World, then we are ready to begin the real experiment.

Beginning of the AngularJS experiment

My Web Part is going to be a simple form with a few questions and a text box for entering the answers. Answers get saved to a SharePoint list via JavaScript Object Model (JSOM).

The HTML


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

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

Here I am initializing the AngularJS App on a div with the ng-app tag. Then I have a ng-controller called QuestionnaireCtrl which contains a bunch of questions that I loop through using ng-repeat.

The JavaScript

var siteUrl = "<%= SPContext.Current.Web.Url %>";

    function QuestionnaireCtrl($scope) {

        $scope.questions = [
            { text: 'How would you like your eggs done?', answer: "" },
            { text: 'What kind of bread would you like?', answer: "" },
            { text: 'What kind of drink would you like?', answer: "" }
        ];

        $scope.addAnswers = function ($event) {
            $event.preventDefault();

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

            _.each($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));

                listItem.update();
            });

            clientContext.executeQueryAsync(
                Function.createDelegate(this, onQuerySucceeded),
                Function.createDelegate(this, onQueryFailed)
            );

        };

        onQuerySucceeded = function () {
            alert('Thank you, have a nice day.');

            var questions = $scope.questions;
            _.each(questions, function (question) {
                question.answer = "";
            });
            $scope.$apply();
        }

        onQueryFailed = function (sender, args) {
            alert('Request failed. ' + args.get_message() + '\n' + args.get_stackTrace());
        }
    }

In the JavaScript, I hard coded 3 questions. Then I have a click event handler that triggers $scope.addAnswers, which will save the answers to my questions into a SharePoint list.

VisualWebPart1.ascx final product

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

        $scope.questions = [
            { text: 'How would you like your eggs done?', answer: "" },
            { text: 'What kind of bread would you like?', answer: "" },
            { text: 'What kind of drink would you like?', answer: "" }
        ];

        $scope.addAnswers = function ($event) {
            $event.preventDefault();

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

            _.each($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));

                listItem.update();
            });

            clientContext.executeQueryAsync(
                Function.createDelegate(this, onQuerySucceeded),
                Function.createDelegate(this, onQueryFailed)
            );

        };

        onQuerySucceeded = function () {
            alert('Thank you, have a nice day.');

            var questions = $scope.questions;
            _.each(questions, function (question) {
                question.answer = "";
            });
            $scope.$apply();
        }

        onQueryFailed = function (sender, args) {
            alert('Request failed. ' + args.get_message() + '\n' + args.get_stackTrace());
        }
    }
</script>

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

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

    </div>

</div>

Congrats if you were able to follow along. I know I left out quite a bit of detail, so please let me know. As this is an experiment, pointers would be great too. I can post my whole Visual Studio project on github or somewhere if anybody is interested.

Thanks for reading.

Tags: , , , ,

Category: Blog, SharePoint 2010, SharePoint 2013

About Jeff Yan: View author profile.

Comments (3)

Trackback URL | Comments RSS Feed

  1. […] 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 […]

  2. […] 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 […]

  3. Manoj Gudi says:

    What is the use of ?

    Could you please explain this?

Leave a Reply




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