PortiBlog

SharePoint hosted app single page application with Angular - Part 1

21 augustus 2015

I've  created a Single page application sharepoint hosted app using Angular and I want to share this experience. This post will consist of 3 parts.

In part 1, this part, I will explain the basic setup of my app.

In part 2 I will show the implemention of the controllers, the views and services using angular and jsom.

Part 3 will be much the same like part 2 except for that I am going to use the SharePoint rest services to communicate with SharePoint instead of jsomn.


The basic setup

The first thing you need is a sharepoint environment with a developer site on which you can deploy your app. This can be an on-premises environment or an Office 365 environment.
If you haven't got a SharePoint environment to deploy your app you can get a trial Office 365 environment.

The second thing you can't do without is Visual Studio, preferably 2013 or later.

If you got these you can start building an app.
First start your Visual Studio create a new project and choose the project type App for SharePoint.

2015-06-30_15-21-12

Next you will be asked the url of your SharePoint site and the kind of App you want to create. Fill in your SharePoint URL and the kind of App you want to create, I want to create a SharePoint hosted App so I choose SharePoint hosted. The techniques I use in this post can also be used for a provider hosted app. Don't use autohosted it's been discontinued.

2015-06-30_15-21-59

You wil now have a SharePoint App project in Visual Studio.
The main page, and only aspx page, is default.aspx. Open up this page.

Dependencies

First we need to declare our dependencies, see code below.

I want to highlight the following:
If you want to use full jQuery functionality make sure jQuery is referenced before Angular.
sp.js and sp.runtime.js are needed for jsom.
SP.RequestExecutor.js is needed to perform calls to the host web. So if you want to do anything on the host web, read create etc, you need this reference.
angular.route.js is needed for for the routeprovider to create a single page application.
app.js, sharepointservice.js, frietdataservice.js and controllers.js are my own js files. In a real world scenario its better to minimize these files into one file however for this post i have kept them seperate.


<asp:Content ContentPlaceHolderID="PlaceHolderAdditionalPageHead" runat="server">
	<script type="text/javascript" src="../scripts/jquery-1.9.1.min.js"></script>
	<script type="text/javascript" src="../scripts/bootstrap.min.js"></script>
	<script type="text/javascript" src="/_layouts/15/sp.runtime.js"></script>
	<script type="text/javascript" src="/_layouts/15/sp.js"></script>
	<script type="text/javascript" src="/_layouts/15/SP.RequestExecutor.js"></script>
	<script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/angularjs/1.3.14/angular.js"></script>
	<script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/angularjs/1.3.14/angular-route.js"></script>
	<script type="text/javascript" src="../scripts/ui-bootstrap-0.13.0.js"></script>

	<!-- Add your CSS styles to the following file -->
	<link href="../Content/bootstrap.min.css" rel="stylesheet" />
	<link href="../Content/bootstrap-theme.min.css" rel="stylesheet" />
	<link href="../Content/bootstrap-theme.min.css" rel="stylesheet" />
	<link href="../Content/FrietApp.css" rel="stylesheet" />
	<!-- Add your JavaScript to the following file -->

	<script type="text/javascript" src="../scripts/app.js"></script>
	<script type="text/javascript" src="../scripts/SharePointService.js"></script>
	<script type="text/javascript" src="../scripts/frietdataService.js"></script>
	<script type="text/javascript" src="../scripts/Controllers.js"></script>

	<meta name="WebPartPageExpansion" content="full" />
</asp:Content>

Furthermore I make use of https://angular-ui.github.io/bootstrap/. This offer some widgets like datepicker etc for use with angular and bootstrap.
For this the template files and fonts must be uploaded to the pages folder, this will look like this. (a bit ugly)
2015-06-30_17-33-30

Initialize Angular App

Notice the ng-app="FrietApp" attribute on the main div tag. This lets Angular know that this part of the html is controlled by the app FrietApp.
Furthermore notice the ng-view attribute. This lets angular know that the view should be rendered here.
The attribute is empty. This is because we will use a routeprovider to set the selected view.

<%-- The markup and script in the following Content element will be placed in the <body> of the page --%>

<asp:Content ContentPlaceHolderID="PlaceHolderMain" runat="server">

	<div class="mainapp FrietApp" ng-app="FrietApp" id="FrietApp" >

		<nav class="navbar navbar-default">
			<div class="container-fluid">
				<!-- Collect the nav links, forms, and other content for toggling -->
				<div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
					<ul class="nav navbar-nav">
						<li class="active"><a href="#EditOrder/">Mijn bestelling</a></li>
						<li class="active"><a href="#Bestellingen/">Bestellingen </a></li>
					</ul>
				</div>
			</div>
	  </nav>

		<div ng-view="" class="maincontent">
		</div>
	</div>
</asp:Content>

Now in our app.js we will initialize our angular app with the following line of code.
      var frietApp = angular.module('FrietApp', ['ngRoute', 'ui.bootstrap']);

this line tells angular to create an app called FrietApp, which we saw earlier in our html code, and that this app has 2 dependencies ngRoute and ui.bootstrap.
ngRoute is used for routing which we will see next.
ui.bootstrap is a library that has a nice control collection that can be used in combination with angular and bootstrap. more information about this can be found at https://angular-ui.github.io/bootstrap/

Routeprovider

Below the javascript to initialize the angular app and configure the routes.


var frietApp = angular.module('FrietApp', ['ngRoute', 'ui.bootstrap']);

frietApp.config(['$routeProvider', function ($routeProvider) {
    $routeProvider.
      when('/Bestellingen', {
        templateUrl: '../content/pages/Bestellingen.html',
        controller: 'BestellingenController'
      }).
      when('/EditBestelling/:ID', {
        templateUrl: '../content/pages/EditBestelling.html',
        controller: 'EditBestellingController'
      }).
      when('/EditOrder/:ID', {
        templateUrl: '../content/pages/index.html',
        controller: 'EditOrderController'
      }).

      otherwise({
        redirectTo: 'EditOrder'
      });
}]);
 

As you can see i deployed my angular views to content/pages folder.
In the routes you can also see the references to this view.

2015-07-01_12-39-42

For example an url with a hash of #/bestellingen/ will show the view ../content/pages/bestellingen.html
The Editbesteling and the EditOrder view also have a parameter (:ID). This will make angular redirect any parameter after the route to the controller with the name ID.

Below the edit initialization of the editbestellingController. Notice the depency on $routeparams. This will allow the controller to get the ID using  $routeParams.ID.


frietApp.controller('EditBestellingController', ['$scope', "$http", "$q", "$routeParams" , "frietDataService", function ($scope, $http, $q, $routeParams, frietDataService) {
       var ID = $routeParams.ID;

Next parts

In part 2 of this post I'll discuss the controller and the SharePoint service communicating to SharePoint with jsom.

In part 3 of this post I'll discuss how to do the same using rest services instead of jsom.

Submit a comment