Embedding Angular 2 in SharePoint with a Script Editor Web Part

Scot Hillier

by Scot Hillier on 1/18/2016

Share this:

Article Details

Date Revised:

Applies to:
Angular 2, CDN Manager, components, JavaScript Promise, JSOM, observables, Script Editor web part, services, SharePoint

Angular is a powerful framework for creating client-side applications, but when it comes to SharePoint, not everyone is creating full-blown applications. In fact, a lot of solutions are created by embedding JavaScript directly in the page, which is a technique that has been around the SharePoint world forever. In this article, I’m going to show you how to embed Angular 2 code into SharePoint pages using the Script Editor web part. This is a great way to see the basic framework in action as well as open up possibilities for future solutions.

Begin with the end in mind

The solution for this article is a simple web part that welcomes the current user as shown in Figure 1. Although the concept is trivial, displaying a personalized welcome message will actually exercise many of the core Angular 2 principles such as components, services, and observables. Because the entire solution is simply a chunk of HTML and JavaScript, I’m going to start the article with a full listing of the solution. Then I’ll use the rest of the article to go over the code.

Welcome message: embed Angular 2 in SharePoint with a Script Editor Web Part
Figure 1, The welcome message

Listing 1, Complete embedded JavaScript



CDNManager.getScript(['angular2-all.umd.min.js'], function () {

  var myApp = window.myApp || {};
  myApp.AppService =
      constructor: function() {},
      getCurrentUser: function() {
        return Rx.Observable.create(function(observer){
          this.ctx = new SP.ClientContext.get_current();
          this.user = this.ctx.get_web().get_currentUser();
              Function.createDelegate(this,function() {
                observer.next("Welcome, " + this.user.get_title() + "!");
              Function.createDelegate(this,function(sender, args) {

  myApp.AppComponent =
      selector: 'hello-angular2',
      template: '<h1>{{greeting | async}}</h1>'
      constructor: [myApp.AppService, function(svc) {
	 this.greeting = svc.getCurrentUser();
    ng.platform.browser.bootstrap(myApp.AppComponent, [myApp.AppService]);



Setting JavaScript references

Unless you are doing a very simple demo or exclusively use the JavaScript client object model (JSOM), chances are you are going to need some references to additional JavaScript libraries as part of your solution. This is certainly true for Angular 2 development so you’ll need a way to reference the core libraries, shims, and polyfills within your existing SharePoint page. While there are different approaches to setting these references – such as creating a custom master page, or simply adding them into the Script Editor web part directly – I prefer to use the CDN Manager, which is available from the Microsoft Patterns and Practices GitHub repository. The CDN Manager is a SharePoint app that injects CDN references into the current site. If you are unfamiliar with the CDN Manager, you can read a complete article on IT Unity. Using the CDN Manager, I provided site-wide references to the following JavaScript libraries.

Table 1, Required CDN References


CDN Reference

Angular 2 Core


Angular 2 Polyfills


ECMA Script 2015 shim


Reactive Extensions


The CDN Manager also allows me to set up dependencies between libraries guaranteeing they are all loaded before my custom script executes. This is possible because the CDN Manager provides a single object and method to guarantee a script is loaded. Then a callback function fires indicating the script load has completed. Looking in Listing 1, you’ll see the entire code block is contained within the call back function.

CDNManager.getScript(['angular2-all.umd.min.js'], function () {});

Creating the Angular 2 service

Just like in Angular 1.x apps, Angular 2 makes use of services for providing common functionality that can be used anywhere in the application. Angular 2 has several built-in services, such as the HTTP service, that provide support for common activities, such as making RESTful calls to web services. You can also create your own service. For this sample, I created a service that returns a welcome message after getting the display name for the current user. My service makes use of JSOM and Observables.

Examining the service definition in Listing 1, you can see the classic JSOM code for retrieving the current user. Because this is so common, I’m going to assume you already understand it. What’s new in the code, however, is the creation of an Observable through the following code.


Observables are the new promises in Angular 2. In Angular 1.x, we made extensive use of the JavaScript Promise object to handle asynchronous calls to web services. While promises did a great job for us, they had some limitations, which are addressed by observables. Observables, for example, do not execute unless a client subscribes. Furthermore, the client subscription can be cancelled mid-flight. While a full discussion of observables is beyond the scope of this article, I can show the basics in my service.

When creating the observable, a callback function is defined that passes in an observer object. The observer supports next, error, and completed methods. When an asynchronous value returns successfully, it can be passed to the calling client through the next method. Errors are propagated through the error method, and the completed method tells the caller that the operation is over. Clients can then subscribe to the observable passing in functions corresponding to success, failure, and completion. In Angular 2, we can even skip explicitly subscribing by declaring the value as async in our HTML template. You can see that declaration in the consuming component in Listing 1, and I’ll cover it again when I discuss the component definition.

template: '<h1>{{greeting | async}}</h1>'

Moving out from the JSOM code and the observable, you can see that the service is defined as a class using the ng.core.Class method. This method takes a JSON object that defines the class including a constructor and the getCurrentUser method. An instance of the service is subsequently made available to the entire app through the bootstrapping process at the end of Listing 1. Services are injected into the app as an array of values as shown.

ng.platform.browser.bootstrap(myApp.AppComponent, [myApp.AppService]);

Creating the component

Once the service is defined, the consuming component must be created. The component is defined using the ng.core.Component method. A component is similar to a controller in Angular 1.x in that it associates some JavaScript functionality with an area of HTML on the page. The selector specifies the element on the page that should be handled by the component. In the sample, the element tag is <hello-angular2></hello-angular2>, which you can see at the top of Listing 1 and in the component definition.

The template defines the HTML that should be used to render content within the selector. Here you can see the familiar “mustache syntax” (now called “interpolation”) that indicates the greeting property should be used to dynamically place text within the h1 element. The value of the property is set in the class constructor, where an instance of the custom service is injected into the component.

constructor: [myApp.AppService, function(svc) {
   this.greeting = svc.getCurrentUser();

If you examine the constructor carefully, you’ll notice that the return value from the service is assigned directly to the greeting property. However, the return value from the service is actually an observable – not a text welcome message. As I called out when discussing the service, this is possible because the template has the piped value async in it. This tells Angular 2 that it should subscribe to this value and reflect any changes.

Once the component is created, we can launch the app through the bootstrapping process I mentioned earlier. During this process, the services are injected, but also the launching component is specified. In our case the custom component launches.

ng.platform.browser.bootstrap(myApp.AppComponent, [myApp.AppService]);

When the component launches, it’s constructor runs, calling the service. When the observable returns with the greeting message, the page is updated to display the text.


Angular 2 is a deep and powerful framework with significant support from Microsoft and Google. There is no doubt that Office and SharePoint developers will be using it to create large-scale enterprise apps. However, it can also be used to create simple solutions based on embedded JavaScript in SharePoint pages. Using the code from this article, you can get started with some basics solutions while learning the larger framework.

Topic: JavaScript and jQuery

Sign in with

Or register

  • Correct me if I'm wrong, but that looks like javascript code not typescript. Do you have that in ts?
  • Comments removed my angle brackets, but you get the idea...

    script src="https://code.angularjs.org/2.0.0-beta.0/angular2-all.umd.min.js"
    script src="https://code.angularjs.org/2.0.0-beta.0/angular2-polyfills.min.js"
    script src="https://cdnjs.cloudflare.com/ajax/libs/es6-shim/0.34.1/es6-shim.min.js"
    script src="https://code.angularjs.org/2.0.0-beta.0/Rx.umd.js"
    • Thanks, Scot! I did that but "angular2-polyfills.min.js" seems to overwrite some SharePoint JS function and cause errors ("Uncaught TypeError: fnRef.apply is not a function"). Please see the github issue: https://github.com/angular/angular/issues/6377 Thanks!
    • Scott, what sequence and namespaces are you using for each script in CDN Manager?
  • If you add the references manually, just put something like the following in the Script Editor or your custom master page:

  • Great article, Scot! As we cannot use the CDNManager in our environment, could you kindly provide an example without it? When I tried to load the "angular2-polyfills.js" library in SharePoint directly it caused a conflict. I have filed an issue here: https://github.com/angular/angular/issues/6377. Thanks!