Angular JS

AJSAngularJS is an open source web application framework which is maintained by Google and a community of passionate developers. It helps you in adding dynamic views in your web applications. With Model-View-Whatever (MVW) architecture and components which are commonly used in Rich Internet Applications, it has become a preferred framework for creation of interactive web applications and data-driven apps. AngularJS is a tool-set which interacts with the HTML. Any back end platform such as Node.js can serve the HTML.

Salient features of AngularJS:

  • Ease of use
    • Because of decoupling of DOM manipulation from application logic it is very easy to use.
    • It is excellent for single-page applications (SPA).
    • With features such as directives, filters and automatic data bindings, the developers don’t need to write hundreds of lines of code for simple features, thus making the code more manageable.
  • Cross-Browser Compatibility and Mobile Support
    • For ensuring cross-browser compatibility, you need to implement features differently – however, the directive (aka HTML extensions) take care of the differences. Note that AnugularJS ver. 1.3 and above has dropped the support for IE8 so if your application requires support for that, you should not consider AngularJS.
    • Cross platform native mobile applications or Hybrid apps development is possible with Trigger.io, Cordova or Phonegap integration. One can also use Ionic framework.
    • For developing mobile sites, one can use AngularJS responsive modules such as angular-responsive or angular-deckgrid, UI Bootstrap, AngularJS responsive directives, angular-gestures or the ngTouch library.
  • Architecture
    • The architecture is MVW (Model-View-Whatever). It can also support other patterns such as Model-View-Controller or Model-View-View Mode.
    • It provides support for Dependency Injection and Direct DOM manipulation.
    • Decouple DOM manipulation from application logic. This improves the testability of the code.
    • Regard application testing as equal in importance to application writing. Testing difficulty is dramatically affected by the way the code is structured.
    • Decouple the client side of an application from the server side. This allows development work to progress in parallel, and allows for reuse of both sides.
    • Provide structure for the journey of building an application: from designing the UI, through writing the business logic, to testing.
  • Testing
    • Unit testing of the AngularJS applications is very easy.
    • It supports all the facets of automated testing like unit, integration and functional testing.
    • It comes with its own test runner called Karma which facilitates unit testing.
    • For end-to-end testing, Protractor can be used. Protractor runs tests against the application running in a real browser, interacting with it as a user would.
  • Programming
    • Supports Object-oriented, Functional and Event-driven programming paradigms.
    • Offers support for Dart, CoffeeScript and TypeScript Scripting languages.
    • Does not offer any official IDE Support and IDE field use validation.

Things it does:

  • It manipulates DOM.
  • It allows writing custom HTML declarations.
  • It manages state of model(s).
  • It integrates seamlessly with other UI tools.

 

Getting Started

      1. Install Node JS from http://nodejs.org/
      2. Install Bower in IntelliJ bower install
      3. Download the AngularJS framework at http://angularjs.org or in IntelliJ project bower install angular
      4. Create HTML page.
        • Reference the Angular.js or Angular.min.js <script src=“bower_components/angular/angular.js”>
        • Addng-app directive:<html ng-app>
        • Reference the Javascript file which contains your Angular JS Module<script src="js/controllers.js"></script>
        • Attach a controller to any HTML element within the scope of the controller<body ng-controller="PhoneListCtrl">
        • Add Angular repeater directive and bind to the data model variable, curly braces ({{phone.name}}and{{phone.snippet}}) will be replaced by the value of the expressions
          <ul>
            <li ng-repeat="phone in phones">
              <span>{{phone.name}}</span>
              <p>{{phone.snippet}}</p>
            </li>
          </ul>
      5. Ceate Javascript controller.
        • Declare a controller called PhoneListCtrl and register it in an AngularJS module, phonecatApp
          var phonecatApp = angular.module('phonecatApp', []);
        • Define controller function for the ngController directive,
          phonecatApp.controller('PhoneListCtrl', function ($scope) {}
        • Add data model to the $scope. The PhoneListCtrl controller attaches the phone data to the $scope that was injected into our controller function. This scope is a prototypical descendant of the root scope that was created when the application was defined

 

How it works

Here is an explanation and full source code for getting started.

View and Template

In Angular, the view is a projection of the model through the HTML template. This means that whenever the model changes, Angular refreshes the appropriate binding points, which updates the view.

The view component is constructed by Angular from this template:

app/index.html:

<html ng-app="phonecatApp">
<head>
  ...
  <script src="bower_components/angular/angular.js"></script>
  <script src="js/controllers.js"></script>
</head>
<body ng-controller="PhoneListCtrl">

  <ul>
    <li ng-repeat="phone in phones">
      <span>{{phone.name}}</span>
      <p>{{phone.snippet}}</p>
    </li>
  </ul>

</body>
</html>

Model and Controller

The data model (a simple array of phones in object literal notation) is now instantiated within the PhoneListCtrl controller. The controller is simply a constructor function that takes a $scope parameter:

app/js/controllers.js:

var phonecatApp = angular.module('phonecatApp', []);

phonecatApp.controller('PhoneListCtrl', function ($scope) {
  $scope.phones = [
    {'name': 'Nexus S',
     'snippet': 'Fast just got faster with Nexus S.'},
    {'name': 'Motorola XOOM™ with Wi-Fi',
     'snippet': 'The Next, Next Generation tablet.'},
    {'name': 'MOTOROLA XOOM™',
     'snippet': 'The Next, Next Generation tablet.'}
  ];
});

Scope

The concept of a scope in Angular is crucial. A scope can be seen as the glue which allows the template, model and controller to work together. Angular uses scopes, along with the information contained in the template, data model, and controller, to keep models and views separate, but in sync. Any changes made to the model are reflected in the view; any changes that occur in the view are reflected in the model.

To learn more about Angular scopes, see the angular scope documentation.

 

Filtering Repeaters

Add HTML <input> tag and used Angular’s filter function to process the input for the ngRepeat directive.

app/index.html:

<div class="container-fluid">
  <div class="row">
    <div class="col-md-2">
      <!--Sidebar content-->

      Search: <input ng-model="query">

    </div>
    <div class="col-md-10">
      <!--Body content-->

      <ul class="phones">
        <li ng-repeat="phone in phones | filter:query">
          {{phone.name}}
          <p>{{phone.snippet}}</p>
        </li>
      </ul>

    </div>
  </div>
</div>

 

  • Data-binding: This is one of the core features in Angular. When the page loads, Angular binds the name of the input box to a variable of the same name in the data model and keeps the two in sync.In this code, the data that a user types into the input box (named query) is immediately available as a filter input in the list repeater (phone in phones | filter:query). When changes to the data model cause the repeater’s input to change, the repeater efficiently updates the DOM to reflect the current state of the model.

  • Use of the filter filter: The filter function uses the query value to create a new array that contains only those records that match the query.ngRepeat automatically updates the view in response to the changing number of phones returned by the filter filter. The process is completely transparent to the developer.

 

Two-way Data Binding

Creating a new model property, wiring it together with the repeater.

  • Add a <select> html element named orderProp
  • Then chain the filter filter with orderBy filter to further process the input into the repeater. orderBy is a filter that takes an input array, copies it and reorders the copy which is then returned.

app/index.html:

Search: <input ng-model="query">
Sort by:
<select ng-model="orderProp">
  <option value="name">Alphabetical</option>
  <option value="age">Newest</option>
</select>


<ul class="phones">
  <li ng-repeat="phone in phones | filter:query | orderBy:orderProp">
    <span>{{phone.name}}</span>
    <p>{{phone.snippet}}</p>
  </li>
</ul>

app/js/controllers.js:

var phonecatApp = angular.module('phonecatApp', []);

phonecatApp.controller('PhoneListCtrl', function ($scope) {
  $scope.phones = [
    {'name': 'Nexus S',
     'snippet': 'Fast just got faster with Nexus S.',
     'age': 1},
    {'name': 'Motorola XOOM™ with Wi-Fi',
     'snippet': 'The Next, Next Generation tablet.',
     'age': 2},
    {'name': 'MOTOROLA XOOM™',
     'snippet': 'The Next, Next Generation tablet.',
     'age': 3}
  ];

  $scope.orderProp = 'age';
});

We set orderProp to 'age' in the controller. So the binding works in the direction from our model to the UI. Angular creates a two way data-binding between the select element and the orderProp model. orderProp is then used as the input for the orderBy filter.

XHRs & Dependency Injection

This fetches a larger dataset from our server using one of Angular’s built-in services called $http. We will use Angular’s dependency injection (DI) to provide the service to the PhoneListCtrl controller. Consider the JSON file as the data:

app/phones/phones.json

[
 {
  "age": 13,
  "id": "motorola-defy-with-motoblur",
  "name": "Motorola DEFY\u2122 with MOTOBLUR\u2122",
  "snippet": "Are you ready for everything life throws your way?"
  ...
 },
...
]

Use Angular’s $http service in our controller to make an HTTP request to your web server to fetch the data in the app/phones/phones.json file. $http is just one of several built-in Angular services that handle common operations in web apps. Angular injects these services for you where you need them.

app/js/controllers.js:

var phonecatApp = angular.module('phonecatApp', []);

phonecatApp.controller('PhoneListCtrl', function ($scope, $http) {
  $http.get('phones/phones.json').success(function(data) {
    $scope.phones = data;
  });

  $scope.orderProp = 'age';
});

The $http service returns a promise object with a success method. We call this method to handle the asynchronous response and assign the phone data to the scope controlled by this controller, as a model called phones. Notice that Angular detected the json response and parsed it for us!

To use a service in Angular, you simply declare the names of the dependencies you need as arguments to the controller’s constructor function, as follows:

phonecatApp.controller('PhoneListCtrl', function ($scope, $http) {...}

Angular’s dependency injector provides services to your controller when the controller is being constructed.

$ Prefix Naming Convention

As a naming convention, Angular’s built-in services, Scope methods and a few other Angular APIs have a $ prefix in front of the name.

The $ prefix is there to namespace Angular-provided services. To prevent collisions it’s best to avoid naming your services and models anything that begins with a $.

If you inspect a Scope, you may also notice some properties that begin with $$. These properties are considered private, and should not be accessed or modified.

 

Routing & Multiple Views

Create multiple views by adding routing, using an Angular module called ‘ngRoute’. E.g navigate to app/index.html, you are redirected to app/index.html/#/phones and the phone list appears in the browser.

Application routes in Angular are declared via the $routeProvider, which is the provider of the $route service. This service makes it easy to wire together controllers, view templates, and the current URL location in the browser. Using this feature, we can implement deep linking, which lets us utilize the browser’s history (back and forward navigation) and bookmarks.

  1. Add dependencies by adding ngRoute module inbower.json configuration file.
    {
      "name": "angular-phonecat",
      "description": "A starter project for AngularJS",
      "version": "0.0.0",
      "homepage": "https://github.com/angular/angular-phonecat",
      "license": "MIT",
      "private": true,
      "dependencies": {
        "angular": "1.4.x",
        "angular-mocks": "1.4.x",
        "jquery": "~2.1.1",
        "bootstrap": "~3.1.1",
        "angular-route": "1.4.x"
      }
    }

     The new dependency "angular-route": "1.4.x" tells bower to install a version of the angular-route component that is compatible with version 1.4.x. We must tell bower to download and install this dependency.

    If you have bower installed globally, then you can run bower install but for this project, we have preconfigured npm to run bower install for us:npm install

  2. Create the template. The $route service is usually used in conjunction with the ngView directive. The role of the ngView directive is to include the view template for the current route into the layout template. This makes it a perfect fit for our index.html template. app/index.html:
    <!doctype html>
    <html lang="en" ng-app="phonecatApp">
    <head>
    ...
      <script src="bower_components/angular/angular.js"></script>
      <script src="bower_components/angular-route/angular-route.js"></script>
      <script src="js/app.js"></script>
      <script src="js/controllers.js"></script>
    </head>
    <body>
    
      <div ng-view></div>
    
    </body>
    </html>

     

  3. Create template section file that gets pull in by ng-view directive, app/partials/phone-list.html:
    <div class="container-fluid">
      <div class="row">
        <div class="col-md-2">
          <!--Sidebar content-->
    
          Search: <input ng-model="query">
          Sort by:
          <select ng-model="orderProp">
            <option value="name">Alphabetical</option>
            <option value="age">Newest</option>
          </select>
    
        </div>
        <div class="col-md-10">
          <!--Body content-->
    
          <ul class="phones">
            <li ng-repeat="phone in phones | filter:query | orderBy:orderProp" class="thumbnail">
              <a href="#/phones/{{phone.id}}" class="thumb"><img ng-src="{{phone.imageUrl}}"></a>
              <a href="#/phones/{{phone.id}}">{{phone.name}}</a>
              <p>{{phone.snippet}}</p>
            </li>
          </ul>
    
        </div>
      </div>
    </div>

     We also added a placeholder template for the phone details view:

    app/partials/phone-detail.html:

    TBD: detail view for <span>{{phoneId}}</span>

    Note how we are using the phoneId expression which will be defined in the PhoneDetailCtrl controller.

  4. Create the App Angular Module, making use of Angular’s ngRoute module and we’ve moved the controllers into their own module phonecatControllers.Notice the second argument passed to angular.module, ['ngRoute', 'phonecatControllers']. This array lists the modules that phonecatApp depends on.app/js/app.js:
    var phonecatApp = angular.module('phonecatApp', [
      'ngRoute',
      'phonecatControllers'
    ]);
    
    phonecatApp.config(['$routeProvider',
      function($routeProvider) {
        $routeProvider.
          when('/phones', {
            templateUrl: 'partials/phone-list.html',
            controller: 'PhoneListCtrl'
          }).
          when('/phones/:phoneId', {
            templateUrl: 'partials/phone-detail.html',
            controller: 'PhoneDetailCtrl'
          }).
          otherwise({
            redirectTo: '/phones'
          });
      }]);

     Using the phonecatApp.config() method, we request the $routeProvider to be injected into our config function and use the $routeProvider.when() method to define our routes.

    Our application routes are defined as follows:

    • when('/phones'): The phone list view will be shown when the URL hash fragment is /phones. To construct this view, Angular will use the phone-list.html template and the PhoneListCtrl controller.
    • when('/phones/:phoneId'): The phone details view will be shown when the URL hash fragment matches ‘/phones/:phoneId’, where :phoneId is a variable part of the URL. To construct the phone details view, Angular will use the phone-detail.html template and the PhoneDetailCtrl controller.
    • otherwise({redirectTo: '/phones'}): triggers a redirection to /phones when the browser address doesn’t match either of our routes.
    • Note the use of the :phoneId parameter in the second route declaration. The $route service uses the route declaration — '/phones/:phoneId' — as a template that is matched against the current URL. All variables defined with the : notation are extracted into the $routeParams object.
  5. Create Javascript controller with PhoneListCtrl and new PhoneDetailCtrl.app/js/controllers.js:
    var phonecatControllers = angular.module('phonecatControllers', []);
    
    phonecatControllers.controller('PhoneListCtrl', ['$scope', '$http',
      function ($scope, $http) {
        $http.get('phones/phones.json').success(function(data) {
          $scope.phones = data;
        });
    
        $scope.orderProp = 'age';
      }]);
    
    phonecatControllers.controller('PhoneDetailCtrl', ['$scope', '$routeParams',
      function($scope, $routeParams) {
        $scope.phoneId = $routeParams.phoneId;
      }]);

    We created a new module called phonecatControllerswith PhoneListCtrl and new PhoneDetailCtrl

  6. In addition to phones.json, the app/phones/ directory also contains one JSON file for each phone. app/phones/nexus-s.json:
    {
      "additionalFeatures": "Contour Display, Near Field Communications (NFC),...",
      "android": {
          "os": "Android 2.3",
          "ui": "Android"
      },
      ...
      "images": [
          "img/phones/nexus-s.0.jpg",
          "img/phones/nexus-s.1.jpg",
          "img/phones/nexus-s.2.jpg",
          "img/phones/nexus-s.3.jpg"
      ],
      "storage": {
          "flash": "16384MB",
          "ram": "512MB"
      }
    }

    New controller…… PhoneDetailCtrl by using the $http service to fetch the JSON files. This works the same way as the phone list controller. app/js/controllers.js:

    var phonecatControllers = angular.module('phonecatControllers',[]);
    
    phonecatControllers.controller('PhoneDetailCtrl', ['$scope', '$routeParams', '$http',
      function($scope, $routeParams, $http) {
        $http.get('phones/' + $routeParams.phoneId + '.json').success(function(data) {
          $scope.phone = data;
        });
      }]);

     To construct the URL for the HTTP request, we use $routeParams.phoneId extracted from the current route by the $route service.

  7. New Template TBD placeholder line has been replaced with lists and bindings that comprise the phone details. Note where we use the Angular {{expression}} markup and ngRepeat to project phone data from our model into the view.

    app/partials/phone-detail.html:

    <img ng-src="{{phone.images[0]}}" class="phone">
    
    <h1>{{phone.name}}</h1>
    
    <p>{{phone.description}}</p>
    
    <ul class="phone-thumbs">
      <li ng-repeat="img in phone.images">
        <img ng-src="{{img}}">
      </li>
    </ul>
    
    <ul class="specs">
      <li>
        <span>Availability and Networks</span>
        <dl>
          <dt>Availability</dt>
          <dd ng-repeat="availability in phone.availability">{{availability}}</dd>
        </dl>
      </li>
        ...
      <li>
        <span>Additional Features</span>
        <dd>{{phone.additionalFeatures}}</dd>
      </li>
    </ul>

     

Filters

Custom output filters to customise display of output text or format.The syntax for using filters in Angular templates is as follows:

{{ expression | filter }}

Some of the built-in Angular filters

  • {{ "lower cap string" | uppercase }}
  • {{ {foo: "bar", baz: 23} | json }}
  • {{ 1304375948024 | date }}
  • {{ 1304375948024 | date:"MM/dd/yyyy @ h:mma" }}

Filtered binding to element:

<input ng-model="userInput"> Uppercased: {{ userInput | uppercase }}

Create a custom filter to convert text strings into glyphs: ✓ for “true”, and ✘ for “false” and register your custom filter with this Angular module: app/js/filters.js:

angular.module('phonecatFilters', []).filter('checkmark', function() {
  return function(input) {
    return input ? '\u2713' : '\u2718';
  };
});

The name of our filter is “checkmark”. The input evaluates to either true or false, and we return one of the two unicode characters we have chosen to represent true (\u2713 -> ✓) or false (\u2718 -> ✘).

Inject into app/js/app.js:

...
angular.module('phonecatApp', ['ngRoute','phonecatControllers','phonecatFilters']);
...

Include the app/js/filters.js file, we need to include this file in our layout template.app/index.html:

...
 <script src="js/controllers.js"></script>
 <script src="js/filters.js"></script>
...

Add the filter expression in the template HTMLapp/partials/phone-detail.html:

...
    <dl>
      <dt>Infrared</dt>
      <dd>{{phone.connectivity.infrared | checkmark}}</dd>
      <dt>GPS</dt>
      <dd>{{phone.connectivity.gps | checkmark}}</dd>
    </dl>
...

 

Directives ng-xxx

AngularJS directives allow the developer to specify custom and reusable HTML-like elements and attributes that define data bindings and the behavior of presentation components.

<div ng-repeat="(key, value) in myObj"> ... </div>

Some of the most commonly used directives are:

ng-app
Declares the root element of an AngularJS application, under which directives can be used to declare bindings and define behavior.

There are 3 important things that happen during the app bootstrap:

  1. The injector that will be used for dependency injection is created.
  2. The injector will then create the root scope that will become the context for the model of our application.
  3. Angular will then “compile” the DOM starting at the ngApp root element, processing any directives and bindings found along the way.

 

ng-bind
Sets the text of a DOM element to the value of an expression. For example, will display the value of ‘name’ inside the span element. Any changes to the variable ‘name’ in the application’s scope are reflected instantly in the DOM.
ng-model
Similar to ng-bind, but establishes a two-way data binding between the view and the scope.
ng-model-options
Allows tuning how model updates are done.
ng-class
Allows class attributes to be dynamically loaded.
ng-controller
Specifies a JavaScript controller class that evaluates HTML expressions.
ng-repeat
Instantiate an element once per item from a collection.
ng-show & ng-hide
Conditionally show or hide an element, depending on the value of a boolean expression. Show and hide is achieved by setting the CSS display style.
ng-switch
Conditionally instantiate one template from a set of choices, depending on the value of a selection expression.
ng-view
The base directive responsible for handling routes that resolve JSON before rendering templates driven by specified controllers.
ng-if
Basic if statement directive which allow to show the following element if the conditions are true. When the condition is false, the element is removed from the DOM. When true, a clone of the compiled element is re-inserted
ng-aria
A module for accessibility support of common ARIA attributes.

ng-src

Specifies source url using angular expression. Using Angular markup like {{hash}} in a src attribute doesn’t work right: The browser will fetch from the URL with the literal text {{hash}} until Angular replaces the expression inside {{hash}}.Any string which can contain {{}} markup

<img ng-src="http://www.gravatar.com/avatar/{{hash}}" alt="Description" />

https://docs.angularjs.org/api/ng/directive/ngSrc

ng-click

Click event handler that calls a function.

<img ng-src="{{img}}" ng-click="setImage(img)">
app/js/controllers.js:
    $scope.setImage = function(imageUrl) {
      $scope.mainImageUrl = imageUrl;
    };

 

Website

  • AngularJS — Superheroic JavaScript MVW Framework

    AngularJS is what HTML would have been, had it been designed for building web-apps. Declarative templates with data-binding, MVW, MVVM, MVC, dependency injection and great testability story all implemented with pure client-side JavaScript!

    Source: angularjs.org/

  • AngularJS

    AngularJS is what HTML would have been, had it been designed for building web-apps. Declarative templates with data-binding, MVC, dependency injection and great testability story all implemented with pure client-side JavaScript!

    Source: docs.angularjs.org/api

  • AngularJS

    AngularJS is what HTML would have been, had it been designed for building web-apps. Declarative templates with data-binding, MVC, dependency injection and great testability story all implemented with pure client-side JavaScript!

    Source: docs.angularjs.org/guide/services

  • johnpapa/angular-styleguide · GitHub

    angular-styleguide – Angular Style Guide: A starting point for Angular development teams to provide consistency through good practices.

    Source: github.com/johnpapa/angular-styleguide

  • angular/angular-seed · GitHub

    angular-seed – Seed project for angular apps.

    Source: github.com/angular/angular-seed

  • Advanced Testing and Debugging in AngularJS – yearofmoo.com

    Learn to test, debug and prepare the test code on your AngularJS application like a Pro using Jasmine unit testing and Protractor integration testing

    Source: www.yearofmoo.com/2013/09/advanced-testing-and-debugging-in-angularjs.html

  • yearofmoo/angularjs-seed-repo · GitHub

    Contribute to angularjs-seed-repo development by creating an account on GitHub.

    Source: github.com/yearofmoo/angularjs-seed-repo

 

Tutorials

  • Drinks Demo App – show how to setup Controllers, Services factory, ng-repeat, ng-change, ng-model, dialog.messagebox
  • Activities App – show how to add or remove items in the ng-model list with ng-repeat
  • AngularJS Tutorial | Metro-North Train Schedule App

    AngularJS Tutorial | Metro-North Train Schedule App

    Source: glebche.appspot.com/static/angularjs-tutorial/angularjs-metro-north-tutorial.html

  • AngularJS

    AngularJS is what HTML would have been, had it been designed for building web-apps. Declarative templates with data-binding, MVC, dependency injection and great testability story all implemented with pure client-side JavaScript!

    Source: docs.angularjs.org/tutorial

  • Introduction to Angular.js in 50 Examples (part 1) – YouTube

    Code at https://github.com/curran/screencasts/tree/gh-pages/introToAngular An introduction to Angular.js covering single-page-app concepts, related libraries…

    Source: www.youtube.com/watch?v=TRrL5j3MIvo

References