@yearofmoo

http://www.yearofmoo.com

Seven major AngularJS articles.

Great resource to learn about AngularJS.

Link to Slides

yom.nu/ngspring

When dealing with Web Applications

What's the problem?

HTML and JavaScript are too coupled together

Too much of a mix between AJAX and traditional HTTP page refreshes

Too dependent on how the backend works

Testing usually becomes secondary

Code is too brittle

Too much work overall

MVC-style Frameworks Help Out

MVC frameworks are a great approach to this

Smaller amounts of HTML & JavaScript code required

Provide some level of testing and organization

Backend-agnostic HTML code

AngularJS does this and more...

AngularJS

Powerful Front-end JavaScript MVC Framework

Extends HTML to build complex web applications

Organizes JavaScript code into reusable modules

Uses routes and views to structure your application

Dependency-injected code allows for easy testing

The major features of AngularJS

Dynamic templating using standard HTML tags and data bindings

Modular JavaScript code

Dependency injection (services and factories)

Controllers and URL Routing

Multi-level data scoping

Animation hooks

Some examples

Getting Started

Setup a basic HTML index.html file


<html ng-app>
  <body>
    
Hello {{ myName }}
<script type="text/javascript" src="angular.js"></script> </body> </html>

Basic Interactivity


<html ng-app="myApp">
  <body>
    <div ng-controller="AppCtrl">
      <input type="text" ng-model="myName" />
      Hello {{ myName }}
    </div>
    <script type="text/javascript" src="angular.js"></script>
    <script type="text/javascript">
      var app = angular.module('myApp', [])
      app.controller('AppCtrl', function($scope) {
        $scope.myName = '...';
      });
    </script>
  </body>
</html>
            

Modules (HTML)

All AngularJS JavaScript code is stored in modules


  var app = angular.module('superModule', ['otherModule', 'anotherModule']);
            

And a module is attached to a page


  <html ng-app="superModule"> ... </html>
            

Modules (JavaScript)

Modules are used to define services, controllers, directives and filters

Each module member is a constructor which can inject other services


app.factory('myValues', function() {
  return function() {
    return [1,2,3,4,5,6];
  };
});
app.filter('skipFirstValue', function() {
  return function(data) {
    return data.slice(1);
  }
});
app.run(function($rootScope, myValues, skipFirstValueFilter) {
  //this is called when the page is loaded
  $rootScope.values = skipFirstValue(myValues());
});
            

$scope

The scope is the glue between JavaScript and HTML in AngularJS


app.controller('AppCtrl', function($scope) {
  $scope.totalApples = 0;
  $scope.moreApples = function() {
    $scope.totalApples++;
  }
});
            

Anything placed on the $scope object can be referenced in HTML


Hello, so far I have {{ totalApples }} apples.

Think of the scope as the memory for your HTML

$rootScope and nested scopes

$rootScope is the base scope of all scopes

A child scope is a new container within a scope

AngularJS may create additional child scopes to isolate data within a template


<div ng-controller="AppCtrl as outer">
  <div ng-controller="InnerCtrl as inner" ng-init="value='1'">
    {{ inner.value }}
  </div>
  <div ng-controller="InnerCtrl as inner" ng-init="value='2'">
    {{ inner.value }}
  </div>
</div>
            

Controllers and Templates

Controllers are defined inside of a module like all other services


app.controller('AppCtrl', function($scope) { ... });
            

And they can be referenced in HTML using ng-controller.

Or within routes...

Controllers & Routing (JavaScript)

Routes are enabled when ngRoute is set as a dependency

And then $routeProvider is used to define the routing


var app = angular.module('myApp', ['ngRoute']);
app.config(function($routeProvider) {
  $routeProvider.when('/home', {
    controller : 'HomeCtrl',
    templateUrl : 'home.html'
  });
  $routeProvider.when('/contact', {
    controller : 'ContactCtrl',
    templateUrl : 'contact.html'
  });
});
app.controller('HomeCtrl', function() { });
app.controller('ContactCtrl', function() { });
            

Controllers & Routing (HTML)

To display views, use the ng-view element


<html ng-app="myApp">
  <body>
    <div ng-view></div>
    <script type="text/javascript" src="angular.js"></script>
  </body>
</html>
            

Place this in your index.html file

Dynamic Templates

AngularJS provides series of predefined HTML components

These components reduce much of the JavaScript required to make HTML appear dynamic

ngRepeat

ngRepeat renders a list of items from a scope member


var app = angular.module('myApp', []);
app.controller('ColorsCtrl', function($scope) {
  $scope.colors = 'red,green,blue,orange,yellow,purple,gray'.split(',');
  $scope.tooManyColors = function() {
    return $scope.colors.length >= 5;
  };
});
            

<div ng-controller="ColorsCtrl">
  
This application has too many colors!
<div ng-repeat="color in colors"> {{ color }} </div> </div>

ngInclude

ngInclude works to render content like ngView does


<div ng-controller="AppCtrl as app">
  <select ng-model="app.templateValue">
    <option value="'frame1.html'">Frame 1</option>
    <option value="'frame2.html'">Frame 2</option>
  </select>
  <div ng-include="app.templateValue"></div>
</div>
            

ngShow / ngHide

ngShow and ngHide show and hide an element on screen


<div ng-controller="AppCtrl as app">
  <button ng-click="app.showMe=true">
    Show
  </em>
  <button ng-click="app.showMe=false">
    Hide
  </em>
  <div ng-show="app.showMe">
    I am visible...
  </div>
</div>
            

AJAX using $http

Use $http to perform an AJAX request


var app = angular.module('myApp', []);
app.controller('ColorsCtrl', function($scope, $http) {
  $scope.colors = $http.get('/api/colors.json');
});
            

The scope will automatically update itself when $http returns gets a response

AJAX using $resource

Use $resource to push and pull data from a RESTful API


var app = angular.module('myApp', ['ngResource']);
app.factory('Color', function($resource) {
  return $resource('/api/colors', {
    id : '@id'
  }, {
    find : { method : 'GET' },
    query : { method : 'GET', isArray: true },
    create : { method : 'POST' },
    update : { method : 'PUT' },
    destroy : { method : 'DELETE' }
  });
});
app.controller('ColorsCtrl', function($scope, Color) {
  $scope.colors = Color.query();
});
            

Directives

Special custom components in HTML


<div my-special-element></div>
            

Which are then handled in JavaScript via DOM manipulation


app.directive('mySpecialElement', function() {
  return function($scope, element, attrs) {
    element.bind('click', function() {
      alert('clicked');    
    });
  }; 
});
            

Directives, $scope and Templates

Something more advanced...


app.directive('mySpecialElement', function() {
  return {
    scope : { times : 0 },
    template : 'You have been clicked {{ times }}',
    controller : function($scope) {
      $scope.$on('clicked', function() {
        $scope.times++;
      });
    },
    link : function($scope, element, attrs) {
      element.bind('click', function() {
        $scope.$apply(function() {
          $scope.$emit('clicked');
        });
      });
    }
  }
});
            

Unit Testing

Unit testing is available via the angular-mocks.js file

Both Jasmine and Mocha are supported


describe('Test colors', function() {
  it('should have a green color by default',
    inject(function($rootScope, $controller) {
      var ctrl = $controller('AppCtrl', {
        $scope : $rootScope
      });
      expect(ctrl.colors.indexOf('green')).toBe(true);
  }));
});
            

E2E Testing

Supported currently by using angular-scenario.js and soon to be with Protractor.

Uses a working web URL and performs assertions using a Jasmine-style matcher system


describe('Test Home Page', function() {
  it('should have a welcome message on the home page', function() {
    browser().navigateTo('#/home');
    expect(browser().location().path()).toBe("/home");
    expect(element('[ng-view]').html()).toContain('welcome to the home page!');
  });
});
            

Animations

Supported with the latest release of AngularJS (v1.2-rc2)

Include the ngAnimate module as a dependency for your app module.


var app = angular.module('myApp', ['ngRoute', 'ngAnimate','ngResource']);
            

Animations work with ng-* directives automatically via CSS and/or JavaScript hooks

CSS-enabled Animations

CSS3 Transitions + CSS3 Keyframe Animations are automatically triggered and rendered

Just include a CSS class on the ngView element


<div ng-view class="my-view"></div>
            

.my-view.ng-enter, .mv-view.ng-leave {
  transition:1s linear all;
}

.my-view.ng-leave.ng-leave-active {
.my-view.ng-enter {
  opacity:0;
}

.my-view.ng-enter.ng-enter-active {
.my-view.ng-leave {
  opacity:1;
}
            

JavaScript-enabled Animations

JavaScript callbacks are available for more advanced animations

Include a CSS class just as before and map that to a JavaScript animation


app.animation('.my-view', function() {
  return {
    enter : function(element, done) {
      jQuery(element).animate({
        opacity:1
      }, done);
    },
    leave : function(element, done) {
      jQuery(element).animate({
        opacity:0
      }, done);
    }
  };
});
            

Demo Repo

Here is a full-fledged demo of AngularJS with just about all the features from the presentation

yom.nu/springone-demo

And the Github repo for that is located at:

yom.nu/springone-code

Some things I missed

The $promise API

Form Validation

$scope Events

More about testing

Helpful Resources

angularjs.org - Docs + Guides

egghead.io - The best AngularJS screencasts website

https://github.com/jmcunningham/AngularJS-Learning - A great list of helpful AngularJS resources

yearofmoo.com - Helpful articles on AngularJS (Testing and Animations)

Thank you!

Thank you for making this possible

@yearofmoo

Feel free to contact me via matias@yearofmoo.com