Angular JS Primer

This is a text to help you get up to speed pretty fast with angular.js. It is not complete and I don't want to say it is correct. It is the result of what I studied from one of the books existent on the market and I rush to write this article before I forget what I just learned. Read on...

Installation

Angular.js comes as a javascript library. The best thing is to download the zip file because this contains all the js files you need. Normally the only file needed is angular.js, for production of course there is the minimum version, however if you need other modules for example routing, then you need to import those as well.

Here is the template for my test application

  1.  
  2. <!DOCTYPE html>
  3. <html ng-app="todoApp">
  4. <!-- InstanceBegin template="/Templates/template.dwt" codeOutsideHTMLIsLocked="false" -->
  5. <head>
  6. <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
  7. <title>Title</title>
  8. <script src="js/angular.js"></script>
  9. <script src="js/angular-route.min.js"></script>
  10. <script src="js/application.js"></script>
  11. </head>
  12.  
  13. <body ng-controller="mainCtrl">
  14. <p>Editor</p>
  15. <p>
  16. This is the header for the editor with the general info: <strong ng-bind="model.title"></strong>
  17. </p>
  18. <p>
  19. <a href="#/list">list</a> <a href="#/add">add</a> <a href="#/delete">delete</a>
  20. </p>
  21.  
  22. <ng-view />
  23. </body>
  24. </html>
  25.  

Note the following:

  • angular.js is imported before the angular-route.min.js. The second one is needed if you want to have different urls in the application and to use the ng-view directive
  • application.js contains all the javascript written by me. Normally you got more than one file. Does not matter how many files you got, please don't write javascript in the html templates

Application

An application is defined as follows in the javascript:

  1.  
  2. var todoApp = angular.module("todoApp", ['ngRoute']);
  3.  

Most of the time the array is empty. Don't forget the array even empty. The call creates the module called todoApp. If you call it twice you get an error. If you call the function without the latest parameter it returns the previously created module. If there is no previously created module, you get an error.

Look at the html template above in the opening html tag to see how I linked the module to the document.

Controller

The controller contains the data you keep in page for rendering, for caching etc and the functions where you go when you click on a button, etc. Look at the file to see how I defined the controller, linked to the body element. You can link it to whatever element you need, and the controller and functionality will only apply for that element and its children.

Here is the model

  1.  
  2. todoApp.controller("mainCtrl", function($scope){
  3. var model = {
  4. title: "this is the title",
  5. templateUrl: 'list.html',
  6. data : [
  7. {selected: false, id: "id_1", name: "name 0", value: "15"},
  8. {selected: false, id: "id_2", name: "name 1", value: "16"},
  9. {selected: true, id: "id_3", name: "name 2", value: "17"},
  10. {selected: false, id: "id_4", name: "name 3", value: "18"},
  11. {selected: false, id: "id_5", name: "name 4", value: "19"},
  12. {selected: false, id: "id_6", name: "name 5", value: "20"}
  13. ]
  14. };
  15.  
  16. $scope.model = model;
  17.  
  18. $scope.editData = {
  19. id: null,
  20. name: null,
  21. value: null
  22. }
  23.  
  24. $scope.clearEdit = function(){
  25. this.editData.id = "";
  26. this.editData.name = "";
  27. this.editData.value = "";
  28. }
  29.  
  30. $scope.add = function(){
  31. this.clearEdit();
  32.  
  33. model.templateUrl = "edit.html";
  34. }
  35.  
  36. });
  37.  
  38.  

$scope is an injected object where you put all the artifacts you need to access in page. For example when you say or {{alfa}} probably you got an attribute called $scope.alfa. When you have something like that <input type="button" ng-click="add()"> surely you got a function defined like in the example above, part of the $scope.

  • You can define a number of controllers
  • One is the top controller and then you got one in each page
  • You have access to the top controller for data
  • There are many possible injected variables, $scope is the most used one, however there are many others. For example $rootScope is the root scope - you can pass variables there for passing data between sibling pages

Routing

Normally you can run an angular.js application from one url - the context url. However sometimes you neeed to have some url like that http://localhost/alfa/showItem/1213 - so localhost is the machine, port is 80, alfa is the context then showItem is the url and 1213 is the item id. Why do you need to work with something like that: if you want to bookmark a location, you need to have an url that fully defines that particular location so that you fire up your browser and go there directly.

Here is how you do it:

In the javascript you add a configuration

  1.  
  2. todoApp.config(function ($routeProvider) {
  3.  
  4. $routeProvider.when("/add", {
  5. templateUrl: "/edit.html"
  6. });
  7.  
  8. $routeProvider.otherwise({
  9. templateUrl: "/list.html"
  10. });
  11. });
  12.  

Then in the place where you need to have imported these files in the template, you put <ng-view/>. The way the files are defined, they are in the root folder of the web application.

How you access them: put a # in front of the resource. So http://localhost/alfa/#/add will load the edit.html when ng-view directive is triggered.

Ajax

When the controller is defined, you inject the object $http and then use it:

  1.  
  2. $http.get(baseUrl).success(function (data) {
  3. $scope.products = data;
  4. });
  5.  
  • A http asynch request was sent
  • It was sent at the url baseUrl probably defined somewhere else
  • The function returns a "promise" that will trigger a callback function when the response comes back
  • success is the promise attribute where the function called in case of success is being called
  • Instead of get you can have all the http predicates and for some of them - like post - you need to pass additional parameters that will be embedded in the request body

Loops

There are a lot of directives in angular.js, for controlling how you render the html. Here is how the loops are done, I put this here only to give you the idea. Once you know what to look for, refer to the angular documentation.

Here is one for our setup (see above how the controller data is structured)

	<tr ng-repeat="item in model.data">
		<td><input type="checkbox" ng-model="item.selected" ><span ng-bind="item.selected"></span></td>
		<td ng-bind="item.name"></td>
		<td ng-bind="item.value"></td>
	</tr>
  • model is an attribute in the $scope of the active controller
  • data is an attribute in model, so model.data is a valid construct
  • ng-bind can be replaced with {{value}}

Bindings

Bindings links values stored in attributes in $scope to values rendered on your screen. The theory is much more complicated, but what I use the most:

One way bindings - a value in $scope is transferred one way to a construct in the page. When the value changes in $scope, the value changes on your screen.

So let's say you got the $scope.title value, if you say <span ng-bind="title"></span> the value inside span will be populated with whatever you got in the title attribute. You can put instead {{title}} instead of all the span construct. One more thing - the way it is above works, span empty tag like that <span ng-bind="title" /> does not work.

Two way bindings - between the $scope value and the form control

<input type="text" ng-model="title"> does two way binding. It works very well and you will always have the $scope bound values in synch with what you see on the screen.