In-Depth

Where JavaScript and SharePoint Apps Intersect

SharePoint is versatile, in that developers can interact with its data via other programming languages besides what's in Visual Studio. Here's how AngularJS fits into the development mix.

With SharePoint 2013, Microsoft wants developers to reduce the workload they put on servers and maximize the use of client-side rendering to the best possible extent. With the availability of the REST API and JavaScript object model, Microsoft has enabled interacting with SharePoint data through many other programming languages and frameworks.

One such popular JavaScript framework is AngularJS, which has been getting lots of attention lately and comes with the promise of helping to build next-generation front-end customizations. It provides easy and smart ways to use less code through data binding and dependency injection. In turn, these features reduce server-side rendering by minimizing server requests and handling a considerable amount of workload in the Web browser.

AngularJS provides another way of giving dynamic looks to static documents with the help of new HTML constructs, called directives. I'd especially emphasize these AngularJS features:

  • DOM event handling
  • Two-way data binding
  • Easy to use DOM control structures
  • Ways to interact with form validations

All of these features support building Create-Read-Update-Delete (CRUD) operations within applications, but it's not just about enabling CRUD operations but also about testability. You can use AngularJS for Ununit testing as well as mock testing with the available features.

Key AngularJS Concepts
Before going into the integration of AngularJS with SharePoint, let's look at some basic principles of AngularJS that I believe are worth noting:

Directives: Directives apply special behaviors to the attributes or the elements in HTML. They can be further defined as the markers on DOM elements that tell the AngularJS HTML compiler to attach a specific behavior to the DOM element and make transitions if necessary. They basically start with an "ng" prefix and there are a set of predefined set of directives from which you can add custom directives. Here are some of the basic directives that you'll most frequently use:

  • Ng-app: Defines a root scope from where the framework gets active.
  • Ng-controller: Uses a custom JavaScript file to define the content that needs to be managed within the particular scope where it is defined.
  • Ng-repeat: Displays an item collection in a repetitive template with the required properties defined within the repeated element.

Model: A model can be defined as a set of data that is to be shown to the users. There can be model elements that exist within a page and that data can be directly bound to reflect on the page very easily.

Scope: Scope is an object that refers to the application model. It can be also considered as an execution context for the expressions where we can write some AngularJS expressions to display some data, do some operations and so on.

Data binding: Data binding is simplified with a standard syntax and with ability to add filters to in in easy ways. They allow a specific model element defined in a scope to be displayed within html with the following syntax.

Now, let's create a SharePoint hosted app via AngularJS.

Create the SharePoint Hosted App
Open Visual Studio 2013 and create a new SharePoint App named Angular.App. Then go to http://angularjs.org and download the latest stable release of AngularJS framework. The version that was available as I wrote this article was version 1.3x. From that, I selected the minified version.

Now right-click on the Scripts folder and add the downloaded file to the scripts folder. It should be visible (see Figure 1). If I just deploy the app and browse it, it should show the default page.

Adding AngularJS files
[Click on image for larger view.] Figure 1: Adding AngularJS files

Now empty the content inside the App.js file within the script folder and add the following reference to the head section of the Default.aspx file:

<script type="text/javascript" src="../Scripts/angular.min.js"></script>

Then replace the content inside the asp:Content tag with ID attribute PlaceHolderMain with the following content:

<div ng-app="">
  <p>My name is:
  <input type="text" ng-model="name"></p>
  <p>Welcome {{name}}</p>
  </div>

Now deploy the app and check browsing (see Figure 2). As you keep typing your name in the textbox you can see the welcome message getting updated. That is because there is a strict binding of the model property, which is called name. This is a simple example and a source for assurance on correct configuration of AngularJS within SharePoint.

Deploying the App
[Click on image for larger view.] Figure 2: Deploying the App

As you can see, we are using the ng-model directive and another directive named ng-app. The ng-app directive designates the root element of the application and is typically placed near the root element of the page or where AngularJS need to be active.

Two other concepts worth noting as we proceed further are the Controllers and the Services.

The controllers in AngularJS attach a controller class to a view. This is one of the key components, given AngularJS supports the MVC design pattern implementation. Controller for a particular view can be defined with the ng-controller directive.

Services in AngularJS provide a greater way to connect the objects using a software design pattern known as dependency injection. Services are normally used for organizing and sharing the code across a particular app. Given it uses dependency injection, a service is only initiated when an application component feels the need to depend on it.

There are some built-in services that starts with the "$" tag such like "$http". Most of the time we end up writing our own service to take care of any other required functionality.

All these services, directives and other AngularJS components are initialized through a concept called Modules in AngularJS. Modules make code easier to unit test and debug as well as improves the portability of the code to a greater extent.

Connecting to SharePoint List Data
To demonstrate the interaction with AngularJS and SharePoint, let's create a list that contains movie names. Right-click on the Visual Studio project and proceed with Add | New | List and name the project as "Movies." Select the custom list template as the list template.

Open the list template in Visual Studio and add two new columns, "Directors" and "Year," which will be single line of text fields (see Figure 3). This will create a list named Movies in the App Web each time it is deployed.

Movies List
[Click on image for larger view.] Figure 3: Movies List

Now let's see how we can show the list items added to this SharePoint list within a SharePoint page.

First replace the content inside the asp:Content tag with the ID PlaceHolderMain with following HTML. This was earlier changed to display a basic AngularJS model binding:

<div ng-app="store">
  <div ng-controller="movieController" >
  <ul>
  <li ng-repeat="item in movies" >
  {{item.Title}} - {{item.Year}}
  </li>
  </ul>
  </div>
  </div>

Here, I have defined an app named "store" where the AngularJS functionality will appear in the page. It can contain multiple controllers that are helpful for implementing the functionality, but in this case I just need one named "movieController." In addition to those two I have used a directive named "ng-repeat," which functions similarly like a For…Each loop that most developers are used to seeing in everyday programming languages. Just like we'd do with most object-oriented programming languages, here we can access the properties of a movie entity that is represented in a variable named "item." I've also made references to two properties, Title and Year.

Now let's add some JavaScript functionality. Go to the Scripts module and start editing the App.js file. First create a module that will create a module named "store," which is referenced in the aspx file:

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

Next, assign a controller named "movieController" that is assigned for the ng-controller directive:

app.controller('movieController', function ($scope, SharePointList) {
  
  var self = this;
  self.movies = SharePointList.list();
  alert('1 ' + self.movies.length);
  
  });

As you can see I have assigned a variable named movies with a service I am creating named "SharePointList" that's shown in Listing 1.

Listing 1: SharePoint List Service

app.service('SharePointList', function () {
  
  var self = this;
  
  self.allItems = [];
  
  self.list = function () {
  EnsureScriptFunc("sp.js", "SP.ClientContext", function () {
  var loc = new SP.ClientContext(_spPageContextInfo.webServerRelativeUrl);
  
  var web = loc.get_web();
  var locList = web.get_lists().getByTitle("Movies");
  
  var query = new SP.CamlQuery();
  
  var queryString = "<View>\
  <Query>\
  <OrderBy>\
  <FieldRef Name='Title' Ascending='True'/>\
  </OrderBy>\
  </Query>\
  </View>";
  query.set_viewXml(queryString);
  
  var locItems = locList.getItems(query);
  loc.load(locItems, "Include(ID,Title,Directors,Year)");
  loc.executeQueryAsync(function () {
  var movies = [];
  var locItemEnumerator = locItems.getEnumerator();
  // Iterate through our retrieved data set and build an array of JSON objects containing
  // the relevent properties.
  while (locItemEnumerator.moveNext()) {
  
  var movieObject = new createItems({
  Year: locItemEnumerator.get_current().get_item("Year"),
  Directors: locItemEnumerator.get_current().get_item("Directors"),
  Title: locItemEnumerator.get_current().get_item("Title"),
  Id: locItemEnumerator.get_current().get_item("ID")
  });
  
  movies.push(movieObject);
  
  }
  self.allItems = movies;
  return self.allItems;
  
  }, function (sender, args) {
  alert('Loading failed. ' + args.get_message() + '\n' + args.get_stackTrace());
  });
  
  });
  };
  
  
  });
  
  function createItems(data) {
  var self = this;
  self.ID = data.ID;
  self.Title = data.Title;
  self.Year = data.Year;
  self.Directors = data.Directors;
  };

As you can see I am assigning the current instance of the client context to a variable named "self." Then I assign a function named list that will bind the existing list items to the current instance. The function inside needs to ensure the sp.js file which contains all the SharePoint client-side scripting is available.

Then I have defined a CAML query that queries the SharePoint list items to be sorted by the Title field in ascending order. Given I don't need all the columns, I query for only the ID, Title, Directors and Year fields. Thereafter it is a matter of creating the necessary objects that will be bound to the Angular UI thread.

I have added functionality to track the exceptions and errors coming on. With that I can get an idea on what goes wrong whenever something happens.

Next up is testing the app. Browse to the list created inside the app web and add some data to the list of movies you prefer to be displayed in the Default.aspx page. Once you browse back through to the Default.aspx, you will be able to see data bound to it (see Figure 4).

Data Is Bound!
[Click on image for larger view.] Figure 4: Data Is Bound!

Advantages of Using AngularJS
There are many advantages that makes AngularJS a great framework for integrating with other platforms. I've highlighted three:

Two-way data binding: This can be identified as one of the coolest features in AngularJS. This reduces the lines of code we need to write for all data related operations by many means. Data manipulation within an application logic makes most of the coding activities. AngularJS simplifies the data binding needs by operating simply within the model as the place of concern. Whenever the model gets updated, the relevant other functionalities get its reflections.

Dependency Injection: Dependency Injection is arguably one of the coolest features that comes with AngularJS. With this developer does not need to find the places need to be affected as the dependencies get defined. This makes the development process much easier and clean. Somehow some sources mention this can work badly for the performances as well in some situations.

Templates: If you are familiar with any XAML based language Microsoft introduced over the past decade, then you know the advantages of having templates defined. AngularJS simplify the templates and it makes them purely HTML based and makes it so easy to work with.

As you can see, it is really simple to get start using AngularJS with SharePoint Apps. There are many advantages as well as points of concerns to be careful with, as is always the case when integrating with another framework. As AngularJS improves, there will be more useful app integrations to come.

About the Author

Malin De Silva is a SharePoint Specialist at Exilesoft and has been involved in many custom development projects, intranets, search, and other projects using SharePoint, .NET, Java and PHP. Malin is a frequent contributor to many forums, including Sri Lanka .NET Forum and SharePoint Sri Lanka. Connect with him on LinkedIn or Facebook.

comments powered by Disqus

Featured

  • Hands On: New VS Code Insiders Build Creates Web Page from Image in Seconds

    New Vision support with GitHub Copilot in the latest Visual Studio Code Insiders build takes a user-supplied mockup image and creates a web page from it in seconds, handling all the HTML and CSS.

  • Naive Bayes Regression Using C#

    Dr. James McCaffrey from Microsoft Research presents a complete end-to-end demonstration of the naive Bayes regression technique, where the goal is to predict a single numeric value. Compared to other machine learning regression techniques, naive Bayes regression is usually less accurate, but is simple, easy to implement and customize, works on both large and small datasets, is highly interpretable, and doesn't require tuning any hyperparameters.

  • VS Code Copilot Previews New GPT-4o AI Code Completion Model

    The 4o upgrade includes additional training on more than 275,000 high-quality public repositories in over 30 popular programming languages, said Microsoft-owned GitHub, which created the original "AI pair programmer" years ago.

  • Microsoft's Rust Embrace Continues with Azure SDK Beta

    "Rust's strong type system and ownership model help prevent common programming errors such as null pointer dereferencing and buffer overflows, leading to more secure and stable code."

  • Xcode IDE from Microsoft Archrival Apple Gets Copilot AI

    Just after expanding the reach of its Copilot AI coding assistant to the open-source Eclipse IDE, Microsoft showcased how it's going even further, providing details about a preview version for the Xcode IDE from archrival Apple.

Subscribe on YouTube

Upcoming Training Events