AngularJS

GETTING STARTED

Owen Cliffe, 2015

Code on Github

Getting Started

Simple Page
<!DOCTYPE html>
<html>
<head>
</head>
<body>
HI I'm a web page
</body>
</html>

Load Angular

<!DOCTYPE html>
<html ng-app="app">
<head>
<script type="text/javascript" src="angular.js"></script>
</head>
<body>
HI I'm a web page
</body>
<script type="text/javascript">
var app = angular.module("app", []);
</script>
</html>

Basic Concepts

Model : Some JSON 
View : Angular Template & Directives
Controller : JS code 

Angular Models

Are just plain old JS objects (POJSO? :) ) 
(Fields, Lists, Primitives, other Objects)  
// Simple values
"some value"

// Lists of stuff
["a","list", "of ", "stuff"]

// complex objects
{
    "name" : "Transactions By Currency",
    "output" : [{"field" : "txn_count", "agg": "SUM"},
                {"field" : "txn_curr_code", "agg": "NONE"}]
}

Angular Views

Are HTML templates,
 they use {{handleBars}} style bindings

<div>
<div> Hello I am : <b>{{greeting}}</b></div>
</div>
</body>
                

These are dynamically compiled by angular in the browser

Angular Controllers

Are objects/functions which bind your model to your view

Via a  view model ($scope) 

<div ng-controller="SimpleController">
<div> Hello I am : <b>{{greeting}}</b></div>
</div>
</body>
<script type="text/javascript">
// Define the app  and it's dependencies
var app = angular.module("app", []);
// Register a controller
app.controller("SimpleController", function ($scope) {
                    $scope.greeting =
                      ["A Little Teapot", "Spartacus",
                       "An Angular Web App"]
                              [Math.floor(Math.random() * 3)];
});
</script>

Controller E.G

2-Way Binding

Binding can go from the model to view {{model.value}}
Or from the view to the model (e.g. via ng-model)
<div ng-controller="SimpleController">
<div> Hello I am : <b>{{greeting}}</b></div>
<div> Input: <input ng-model="greeting"></div>
</div>
</body>
<script type="text/javascript">
    var app = angular.module("app", []);
    app.controller("SimpleController", function ($scope) {
        $scope.greeting = "an empty page";
    });
</script>
                
Input Binding is triggered by inputs from bound elements
Angular figures out what to do each time

2 Way Binding EG


Binding: External Changes

Angular picks up changes on bound inputs, otherwise you have to $apply the   $scope

<div ng-controller="SimpleController">
<div> The Time is  : <b>{{currentTime}}</b></div>
</div>
</body>
<script type="text/javascript">
var app = angular.module("app", []);

app.controller("SimpleController", function ($scope) {
$scope.currentTime = new Date();

setInterval(function(){
$scope.currentTime = new Date();
       $scope.$apply();
           },1000);
});
</script>

Apply EG


Filtering

Values in template substitutions can be filtered using filters

<div> The Time is  : <b>{{currentTime | reverse }}</b></div>

Useful for rendering static data, internationalisation etc.


More complex models and views

Bindings can be complex & iterative

Todo List:
<div ng-repeat="item in todoList" >
    Item : {{item.name}} Priority: {{item.priority}}
    <input type="checkbox" ng-model="item.done"/>
</div>
$scope.todoList =
   [{name: "Wash Cat", priority: "HIGH" , done : true},
    {name: "Take out Cat Loan", priority: "Medium",done : false},
    {name: "Find Cat", priority: "LOW",done : true}
];
 app.controller("SimpleController", function ($scope) {
    $scope.newItem = {name: "", priority: "LOW", done: false};
    $scope.todoList = [];
    $scope.addItem = function(){
        $scope.todoList.push($scope.newItem);
        $scope.newItem = {name: "", priority: "LOW", done: false};
    };
});
<div ng-controller="SimpleController">
    Todo List:
    <div ng-repeat="item in todoList">
        Item : {{item.name}} Priority: {{item.priority}}
        <input type="checkbox" ng-model="item.done"/>
    </div>
    New Item : <input ng-model="newItem.name">
<select ng-model="newItem.priority">
    <option value="HIGH">HIGH</option>
    <option value="MEDIUM">MEDIUM</option>
    <option value="LOW">LOW</option>
</select>
    <button ng-click="addItem()" >Add</button>
</div>

Services, Injection and Coupling

If you are familiar with Spring Contexts, it's quite easy to understand Angular DI

there are many out of the box (and pluggable) services around

$http : the HTTP client
$cookies Browser cookies
$animate : animators
$q : the promise factory
and many more

DI and services

Pass the dependency reference as a named parameter to the object definition

app.controller("SimpleController", function ($http,$scope) {
$http.get("/testData")
      .then(function (resp) {
          console.log("got HTTP Response ",resp);
          $scope.remoteContent = resp.data.serverUptime;
          $scope.$apply();
      })
      .catch(function(e){
          console.log("an errror occured",e);
      });
    });
app.controller("SimpleController",
                  ["$http","$scope", function ($http,$scope) {
service

Defining new injectable things

app.factory("UptimeService", function ($http) {
        return {
            getUpTime: function () {
                return $http.get("/testData").catch(function (e) {
                    console.log("an http error occured", e);
                    throw e;
                }).then(function(resp){
                    return resp.data.serverUptime;
                });
            }
        }
    });
app.controller("SimpleController",
    function (UptimeService, $scope) {
      UptimeService.getUpTime().then(function (uptime) {
          $scope.remoteContent = uptime;
      });

Service, Prototype, Repository, Factory, Constant : WTF?

All different ways of creating injectable things, with variations in :

  • How they are constructed
  • When they are constructed
  • Whether they are singletons or not

Directives

A chunk of code that (contributes to) managing a part of the view

May or may not be associated with a scope

E.g. a widget

Massively over-used in the some projects

app.directive("owensDirective",function(){
    return {
        scope: true,
        restrict: 'AE',
        replace: 'true',
        template: '<blink>Owen Is {{adjective}} Awesome</blink>'
    };
});
app.controller("SimpleController", function ( $scope) {
    $scope.adjective ="super";
});
<div owens-directive/>

Modules and scaling up

Angular projects can use third party modules:

 var app = angular.module("app", []);
 var app = angular.module('app', [
    # Angular modules
    'ngRoute',
    'ngAnimate',
    # 3rd Party Modules
    'ui.bootstrap',
    'easypiechart',
     ...

imports directives, services etc from other modules

Modularising your app

Modularise by feature not by type of object:

Be wise.

Build it

Lots of new tools

  • npm
  • bower
  • karma
  • grunt

NPM : Node Package Manager

Defines depenencies for your build via package.json

{
  "name": "supercool-app",
  "version": "3.1.0",
  "description": "Like totally the best app ever",
  "homepage": "http://mybestapp.com",
  "subdomain": "app",
  "devDependencies": {
    "grunt-contrib-qunit": "~0.5.2",
    "grunt-contrib-jshint": "~0.6.4",
  ...
  }
}
$ npm install   

Bower : Client Package Manager

Defines depenencies for your app via bower.json

{
  "name": "nuportal-client",
  "version": "1.0.0",
  "dependencies": {
    "jquery": "~2.1.0",
    "angular": "~1.2.0",
    "angular-resource": "~1.2.0",
    "angular-cookies": "~1.2.0",
    "angular-sanitize": "~1.2.0",
    "angular-route": "~1.2.0",
    "angular-animate": "~1.2.0"
   }
}
$ bower install   

Grunt

Executes build tasks

module.exports = function (grunt) {
  require('load-grunt-tasks')(grunt);
  require('time-grunt')(grunt);

  grunt.initConfig({
      livereload: {
        options: {
          livereload: '<%= connect.options.livereload %>'
        }
     }
   });
  grunt.registerTask('server', function (target) {
    if (target === 'dist') {
      return grunt.task.run(['build', 'connect:dist:keepalive']);
    }

    grunt.task.run([
      'clean:server',
      'concurrent:server',
      'autoprefixer',
      'connect:livereload',
      'watch'
    ]);
  });
}
$ grunt server   

Karma

Runs your tests

Actually, that's pretty much it