AngularJS – Introduction



AngularJS – Introduction

0 0


angular-presentation


On Github mravinale / angular-presentation

AngularJS

Introduction

JQuery

  • Simple API and works great
  • Tightly couples AJAX calls, DOM Manipulation and event listening in the app code
  • Does not provide structure recommendation
  • Does not provide two way binding

HTML

STRUCTURE

JS

BEHAVIOR

CSS

PRESENTATION

The Eval JavaScript Empire

AngularJS

puts a heavy emphasis on

Separation of Concerns

HTML

INTERFACE

JS

LOGIC

CSS

PRESENTATION

The New Angular Republic

AngularJS

returns things to where they belong

in their natural forms

  • HTML? Build UI Declaratively!
  • CSS? Animations!
  • JavaScript? Use it the plain old way!

What we'll cover

  • Setup the app
  • Controllers, Scopes, View binding
  • Services
  • Directives & Filters
  • Testing

The App

To get started:

<div ng-app="app">
						  <div ng-view=""></div>
						</div>

  • Setup the app
  • Define container for view templates

Module Definition

angular.module('app', ['app.services', 'app.directives', 'app.controllers', 
  'ngRoute']).config(function($routeProvider, $locationProvider) {
    $routeProvider.when("/accounts/?:userIdOrScreenName?", {
      templateUrl: "/accounts/partials/main_page",
      controller: 'UserDetailsIndexCtrl'
    });
    $routeProvider.otherwise({
      redirectTo: "/accounts/"
    });
    $('.navbar').removeClass('navbar-inverse');
    return $locationProvider.html5Mode(true);
  });

  • Modules encapsulate the app code into a namespace
  • Dependency inject dependencies, by variable name.
  • No Global Variables
  • Routing logic, controller per route, Templates
  • Templates are not limited by mustache :))

Controllers

angular.module('app.controllers', ['app.services']).controller('UserDetailsIndexCtrl', 
  function($scope, userQuery, $location, $routeParams) {
    var onUserDataArrived = function(result) {
      $scope.user = {id: result.data.id, name: result.data.profile.name, screen_name: result.data.profile.screen_name, image: result.data.profile.profile_image_urls.normal.http_url};
    }
    if ($routeParams.userIdOrScreenName) {
      $scope.userIdOrAccount = $routeParams.userIdOrScreenName;
      userQuery.queryUser($routeParams.userIdOrScreenName).then(onUserDataArrived);
    }
    $scope.onSelectUser = function(e) {
      $location.path('/accounts/' + $scope.userIdOrAccount);
    };
}
        
  • Controllers only prepare the model for the view and respond to events
  • Controllers do NOT manipulate the DOM
  • The $scope variable is where the view consumes variables from
  • Event handlers
  • Controllers are re-created on every request

Scopes are hierarchical

  • There is only one $rootScope and every scope inherits from it.
  • Some AngularJS constructs create a new scope, that inherit from the controller's $scope.
  • Scope is a regular POJO. Your models are regular Javascript objects
  • All AngularJS specific variables and functions start with $ to not get serialized

Views & Binding

<form ng-submit="onSelectUser()">
  <input type="text" ng-model="userIdOrAccount" placeholder="User ID or @SN">
</form>
<span class="name">{{user.name}}</span>
        
  • Custom attribute names
  • Custom element names
  • Data binding ({{}} and ng-model)
  • Some attributes/elements also change HTML, such as: ng-repeat

Services

angular.module('app.services', []).factory('userQuery', function($http, $q) {
  return {
    queryUser: function(userIdOrScreenName) {
      return $http.get('/accounts/user_stats/' + userIdOrScreenName.toString());
    }
  };
});
        
  • Services are where the http get/post/put/delete calls go
  • Services are created using factory, since they have only one instance
  • Promises $q - are Angular library like jQuery Deferred
  • $http.get is almost equivalent to $.get

Advanced Topics

To try after mastering the basics

Directives

Directives can be confusing at first. Many ways to construct them.

  • They encapsulate an element with related logic
  • They encauslate 3rd party components

directive('ngConfirmClick', function() {
  return {
    link: function (scope, element, attr) {
      var msg = attr.ngConfirmClick || "Are you sure?";
      var clickAction = attr.confirmedClick;
      element.bind('click',function (event) {
          if ( window.confirm(msg) ) {
              scope.$eval(clickAction)
          }
      });
    }
  };
})
        

Filters

Used for transforming data (pipe).

  • They encapsulate an element with related logic
  • They encauslate 3rd party components

.filter('multiple', function () {
   return function (input) {
       return '' + input + 'X';
   };
})
        
<tr ng-repeat="friend in friends | filter:searchText">
</tr>
<span>{{amount | currency}}</span>
        

Testing

describe('app.controllers::UserDetailsIndexCtrl', function() {
  var $controller, $location, $scope, userQuery, $q, deferred;
  beforeEach(module('app.controllers'));
  beforeEach(inject(function($rootScope, _$location_, _$controller_, _$q_) {
    $scope = $rootScope.$new();
    $location = _$location_;
    return userQuery = {
      queryUser: function() {
        deferred = $q.defer();
        return deferred.promise;
      }
    };
  }));
      

Testing

it('should query user information when submitted with /userid=1', function() {
    spyOn(userQuery, 'queryUser').andCallThrough();
    $controller('UserDetailsIndexCtrl', {
      $scope: $scope,
      $location: $location,
      $routeParams: {
        userIdOrScreenName: 3
      },
      userQuery: userQuery
    });
    expect(userQuery.queryUser).toHaveBeenCalled();
  });
});
        

Testing

  • Testing is best done using Jasmine and run by NodeJS and Karma.
  • Karma live monitors your files and runs tests!

Thank You