SharePoint 2013 Apps and AngularJS – The Basics

AngularJS-large

Technorati Tags:

Some time ago I’ve heard the word(s) AngularJS at the client and what it can do. It all sounded very promising but sadly I didn’t had the time to look at it.

Now that things are bit calmer I’ve took the time today to look at this awesome framework and I must say: “this in combination with Apps, can be VERY promising”.

I’ve just followed a very simple example and created it in HTML. After that I’ve modded it to SharePoint Apps and I’ll write out all the steps I did below.

First question: What is AngularJS and why should you use it?

Well to be short, it’s a framework that extends the HTML vocabulary. HTML wasn’t build to handle dynamic views, now with AngularJS you are able to build dynamic views and the framework is fully extensible so that you can make it fit your needs.

You can test a small angularJS app below. Just fill in something in the textbox 🙂

 
  Hello {{yourName}}!
 
Basics
 
First we have to understand the basics.
ng-app: We need to define a root scope as from where the framework is “active”.
ng-controller: the content will be managed under this node using a js class defined in the custom javascript file.
ng-repeat: this is used to unroll a collection, angularJS will create a new copy of the template li node
 
tutorial_02
 
The image above gives you a visual indication and as you can see, AngularJS incorporates the basic principles behind the original MVC design pattern.
 
Example
 
First I’ve created a basic html page with some links to some CSS and angularJS-min.js.
After that I’ve added another link to my own custom javascript file.
 
Without Angular directives.
 
   1:  <!DOCTYPE html>
   2:  <html>
   3:  <head>
   4:      <meta charset='utf-8' />
   5:      <title>Things to do</title>
   6:      <link rel='stylesheet' href='bootstrap/css/bootstrap.css' />
   7:      <link rel='stylesheet' href='todo.css' />
   8:      <script src='Libs/angular.js'></script>
   9:      <script src='Libs/angular-resource.js'></script>
  10:      <script src='todo.js'></script>
  11:  </head>
  12:  <body class='well'>
  13:      <h1> Meligo's todo list </h1>
  14:      <p>
  15:          remaining <strong> XXX </strong> of <strong> XXX </strong> , [ <a href>ARCHIVE</a> ]
  16:      </p>
  17:   
  18:      <ul class='unstyled'>
  19:          <li> <input type='checkbox'>Item 1</li>
  20:          <li> <input type='checkbox'>Item 2</li>
  21:          <li> <input type='checkbox'>Item 3</li>
  22:      </ul>
  23:   
  24:      <form>
  25:          <input>
  26:          <button class='btn btn-primary'> Add </button>
  27:      </form>
  28:  </body>
  29:  </html>

With Angular directives (notice the ng- stuff)

   1:  <!DOCTYPE html>
   2:  <html ng-app='todoApp'>
   3:  <head>
   4:      <meta charset='utf-8' />
   5:      <title>Things to do</title>
   6:      <link rel='stylesheet' href='bootstrap/css/bootstrap.css' />
   7:      <link rel='stylesheet' href='todo.css'/>
   8:      <script src='Libs/angular.js'></script>
   9:      <script src='Libs/angular-resource.js'></script>
  10:      <script src='todo.js'></script>
  11:  </head>
  12:  <body class='well' ng-controller='AppCtrl'>
  13:      <h1> {{userName}}'s todo list </h1>
  14:      <p>
  15:          remaining <strong> XXX </strong> of <strong> XXX </strong> , [ <a href>ARCHIVE</a> ]
  16:      </p>
  17:      
  18:      <ul class='unstyled' >
  19:          <li ng-repeat ='item in items'> {{item.done}}<input ng-model='item.done' type='checkbox'>{{item.text}}</li>
  20:      </ul>
  21:      
  22:      <form>
  23:          <input>
  24:          <button class='btn btn-primary'> Add </button>
  25:      </form>
  26:  </body>
  27:  </html>
 

As you can see my code is a lot shorter. I don’t need to list all the li’s and the username can be filled in dynamically.

For this demo I’ve put everything in my own custom JS file.

   1:  var todoApp = angular.module('todoApp', ['ngResource']);
   2:   
   3:  todoApp.controller('AppCtrl', function AppCtrl($scope) {
   4:      $scope.userName = 'Meligo';
   5:      //define model 
   6:      var items = [
   7:          { text: 'task 1+', done: false },
   8:          { text: 'task 2+', done: true },
   9:          { text: 'task 3+', done: false }
  10:      ]
  11:      // publish it on scope
  12:      $scope.items = items;
  13:      //computed propety
  14:      $scope.remaining = function () {
  15:          return items.reduce(function (count, item) {
  16:              return item.done ? count : count + 1;
  17:          }, 0);
  18:      };
  19:      //event handler 
  20:      $scope.add = function (newItem) {
  21:          var item = { text: newItem.text, done: false };
  22:          items.push(item);
  23:          newItem.text = '';
  24:      };
  25:      }
  26:  )

First line you can see the ‘todoApp’ , I have a reference to it placed on the <html ng-app=”todoApp”> node. So I define the root scope, in this case the entire page.

After that you see ‘appCtrl’ , this is the controller that has all the data and the controller is place on the <body ng-controller=”AppCtrl”> node. I’ve put it all in a constructor with an argument ‘$scope’ ($scope is like a context).

Here you can see that I add ‘userName’ and ‘items’ to the scope so that I can use them in the html file.

In the body node I’ve placed ‘{{userName}}’ you can also do ‘{{userName | uppercase” }}’ is you want to display what is in the userName as uppercase. AngularJS will interpret the DOM and will replace {{userName}} with what is in the scope.

Below the line where I put ‘meligo’ in the ‘userName’, I’ve created a collection with text values and done boolean values. And that collection is again bind to the ‘$scope’.

 

Below is the image that is the result of both files.

htmlExample

Now it’s time to put what we’ve learned into a SharePoint App.

Basically it’s just the same.  Link the javascript files in the “PlaceHolderAdditionalPageHead”:

 

   1:      <script type='text/javascript' src='../Scripts/angular.js'></script>
   2:      <script type='text/javascript' src='../Scripts/AngularDemoScript.js'></script>
   3:      <script type='text/javascript' src='../Scripts/angular-resource.js'></script>

 

And put in the “placeholdermain” the following codesnippet:

 

   1:   <div ng-app='todoApp'>
   2:          <div ng-controller='AppCtrl'>
   3:   
   4:              <p id='message'>
   5:                  <!-- The following content will be replaced with the user name when you run the app - see App.js -->
   6:                  initializing...
   7:              </p>
   8:   
   9:              <p >
  10:                  <h1>{{userName}}'s todo list </h1>
  11:                  <p>
  12:                      remaining <strong>XXX </strong>of <strong>XXX </strong>, [ <a href>ARCHIVE</a> ]
  13:                  </p>
  14:   
  15:                  <ul class='unstyled'>
  16:                      <li ng-repeat='item in items'>{{item.done}}<input ng-model='item.done' type='checkbox'>{{item.text}}</li>
  17:                  </ul>
  18:   
  19:                  <panel>
  20:                      <input>
  21:                      <button class='btn btn-primary'> Add </button>
  22:                  </panel>
  23:   
  24:              </p>
  25:   
  26:          </div>
  27:      </div>

As you see I’ve almost done the same, of course I don’t have a “<html> or <body>” tag so I’ve used div’s instead. The result you can see below 🙂

Fun thing is, if you deselect the checkbox than “true” becomes “false”. and if you select them than the value is “true” again. So you can see that it is bound to the collection item.

 

image

That’s it for now, I’ll try to create a serie out of this subject. I really think that this can really make your apps much more better and it’s also better coding if you split everything into the MVC design pattern.

I’ve uploaded the 2 examples to my skydrive .

Most of the information that I’ve got is from http://angularjs.org .

Questions or remarks you can always leave a comment 🙂

Leave a Reply

Your email address will not be published. Required fields are marked *