AngularJS From Beginning: Global Object Service - Part Six

In this article, we will discuss how to use AngularJS Global Object services. This is part six of the series.

I am here to continue the discussion around AngularJS. Today, we will discuss about the global objects service with AngularJS. Also in case you have not had a look at our previous articles of this series, go through the following links:

In this article, we will discuss about the built-in service which AngularJS provides for accessing global objects, dealing with exceptions, displaying dangerous data, and processing expressions.

Why and When to Use the Global Object Services

The main reason that AngularJS includes these services is to make testing easier. We will discuss about unit testing in AngularJS in the next article, but an important facet of unit testing is the need to isolate a small piece of code and test its behavior without testing the components it depends on—in essence, creating a focused test. The DOM API exposes functionality through global objects such as document and window. These objects make it hard to isolate code for unit testing without also testing the way that the browser implements its global objects. Using services such as $document allows AngularJS code to be written without directly using the DOM API global objects and allows the use of AngularJS testing services to configure specific test scenarios. The followings are the services that exposes DOM API features.

Name

Descriptions

$anchorScroll

Scrolls the browser window to a specified anchor

$document

Provides a jqLite object that contains the DOM window.document object

$interval

Provides an enhanced wrapper around the window.setInterval function

$location

Provides access to the URL

$log

Provides a wrapper around the console object

$timeout

Provides an enhanced wrapper around the window.setITimeout function

$window

Provides a reference to the DOM window object

Accessing the Window Object

The $window service is simple to use, and declaring a dependency on it gives you an object that is a wrapper around the global window object. AngularJS doesn’t enhance or change the API provided by this global object, and you access the methods that the window object defines just as you would if you were working directly with the DOM API.
 
For demonstrate window object, we create the below program -
 
App.js
  1. var testApp = angular.module('TestApp', []);  
Window.html
  1. <!DOCTYPE html>  
  2. <html ng-app="TestApp">  
  3. <head>  
  4.     <title>AngularJS Window Objects</title>  
  5.     <script src="angular.js"></script>  
  6.     <link href="../../RefStyle/bootstrap.min.css" rel="stylesheet" />  
  7.     <script src="app.js"></script>  
  8.     <script src="Window.js"></script>  
  9.   
  10. </head>  
  11. <body ng-controller="testController" class="well">  
  12.     <button class="btn btn-primary" ng-click="displayAlert('Clicked!')">Click Me</button>  
  13. </body>  
  14. </html>  
Window.js
  1. testApp.controller("testController"function ($scope, $window) {  
  2.   
  3.     $scope.displayAlert = function (msg) {  
  4.         $window.alert(msg);  
  5.     }  
  6. });  
The output of the above code is as below -
 
 Accessing the Document Object

The $document service is a jqLite object containing the DOM API global window.document object. Since the service is presented via jqLite, you can use it to query the DOM using the methods.

Document.html
  1. <!DOCTYPE html>  
  2. <html ng-app="TestApp">  
  3. <head>  
  4.     <title>AngularJS Document Objects</title>  
  5.     <script src="angular.js"></script>  
  6.     <link href="../../RefStyle/bootstrap.min.css" rel="stylesheet" />  
  7.     <script src="app.js"></script>  
  8.     <script src="document.js"></script>  
  9.   
  10. </head>  
  11. <body ng-controller="testController" class="well">  
  12.     <button class="btn btn-primary" ng-click="displayAlert('Clicked!')">Click Me</button>  
  13.   
  14.     <button class="btn btn-primary">Click Me - Document</button>  
  15.   
  16.     <button class="btn btn-primary">Click Me - Document2</button>  
  17. </body>  
  18. </html>  
Document.js
  1. testApp.controller("testController"function ($scope, $window, $document) {  
  2.   
  3.     $scope.displayAlert = function (msg) {  
  4.         $window.alert(msg);  
  5.     }  
  6.   
  7.     $document.find("button").on("click"function (event) {  
  8.         $window.alert(event.target.innerText);  
  9.     });  
  10. });  
The output is as follows,



Using Intervals and Timeouts

The $interval and $timeout services provide access to the window.setInterval and window.setTimeout functions, with some enhancements that make it easier to work with AngularJS. Below Table shows the arguments that are passed to these services.

Arguments

Descriptions

fn

A function whose execution will be delayed

delay

The number of milliseconds before fn will be executed

count

The number of times that the delay / execute cycle will be repeated only. The default value is zero, which means there is no limit

 
Interval.html
  1. <!DOCTYPE html>  
  2. <html ng-app="TestApp">  
  3. <head>  
  4.     <title>AngularJS Interval Objects</title>  
  5.     <script src="angular.js"></script>  
  6.     <link href="../../RefStyle/bootstrap.min.css" rel="stylesheet" />  
  7.     <script src="app.js"></script>  
  8.     <script src="interval.js"></script>  
  9.   
  10. </head>  
  11. <body ng-controller="testController" class="well">  
  12.     <div class="panel panel-default">  
  13.         <h4 class="panel-heading">Time</h4>  
  14.         <div class="panel-body">  
  15.             The time is (UTC Format): {{time}}  
  16.         </div>  
  17.         <div class="panel-body">  
  18.             The time is : {{time | date:'HH:mm:ss'}}  
  19.         </div>  
  20.     </div>  
  21. </body>  
  22. </html>  
Interval.js
  1. testApp.controller("testController"function ($scope, $interval) {  
  2.   
  3.     $interval(function () {  
  4.         $scope.time = new Date().toTimeString();  
  5.     }, 1000);  
  6. });  
The output is as follows,

 

Accessing the URL

The $location service is a wrapper around the location property of the global window object and provides access to the current URL. The $location service operates on the part of the URL following the first # character, which means it can be used for navigation within the current document but not to navigate to new documents. This may seem odd, but you rarely want the user to navigate away from the main document because it unloads your web application and discards your data and state. Below table describes the method defined by the $location service.

Name

Descriptions

absUrl()

Returns the complete URL of the current document, including the parts before the first # character (http://mydomain.com/app.html#/cities/london?select=hotels#north).

hash()hash(target)

Gets or sets the hash section of the URL—see earlier.

host()

Returns the hostname component of the URL (mydomain.com).

path()path(target)

Gets or sets the path component of the URL—see earlier.

port()

Returns the port number. This is implied in my example URL and defaults to 80.

protocol()

Returns the protocol component of the URL (http)

replace()

When called on an HTML5 browser, the change in the URL replaces the most recent entry in the browser history rather than creating a new one.

url()

url(target)

Gets or sets the path, query string, and hash together.

 
location.html
  1. <!DOCTYPE html>  
  2. <html ng-app="TestApp">  
  3. <head>  
  4.     <title>AngularJS Location Objects</title>  
  5.     <script src="angular.js"></script>  
  6.     <link href="../../RefStyle/bootstrap.min.css" rel="stylesheet" />  
  7.     <script src="app.js"></script>  
  8.     <script src="location.js"></script>  
  9.   
  10. </head>  
  11. <body ng-controller="testController" class="well">  
  12.     <div class="panel panel-default">  
  13.         <h4 class="panel-heading">URL</h4>  
  14.         <div class="panel-body">  
  15.             <p>The URL is: {{url}}</p>  
  16.             <div class="btn-group ">  
  17.                 <button class="btn btn-primary" ng-click="setUrl('reset')">Reset</button>  
  18.                 <button class="btn btn-primary" ng-click="setUrl('path')">Path</button>  
  19.                 <button class="btn btn-primary" ng-click="setUrl('hash')">Hash</button>  
  20.                 <button class="btn btn-primary"  
  21.                         ng-click="setUrl('search')">  
  22.                     Search  
  23.                 </button>  
  24.                 <button class="btn btn-primary" ng-click="setUrl('url')">URL</button>  
  25.             </div>  
  26.         </div>  
  27.     </div>  
  28.     <br />  
  29.     <div class="panel panel-default">  
  30.         <h4 class="panel-heading">URL</h4>  
  31.         <div class="panel-body">  
  32.             <p id="top">This is the top</p>  
  33.             <button class="btn btn-primary" ng-click="show('bottom')">  
  34.                 Go to Bottom  
  35.             </button>  
  36.             <p>  
  37.                 <ul>  
  38.                     <li ng-repeat="item in items">{{item}}</li>  
  39.                 </ul>  
  40.             </p>  
  41.             <p id="bottom">This is the bottom</p>  
  42.             <button class="btn btn-primary" ng-click="show('top')">Go to Top</button>  
  43.         </div>  
  44.     </div>  
  45. </body>  
  46. </html>  
location.js
  1. testApp.controller("testController"function ($scope, $location, $anchorScroll) {  
  2.   
  3.     $scope.$on("$locationChangeSuccess"function (event, newUrl) {  
  4.         $scope.url = newUrl;  
  5.     });  
  6.     $scope.setUrl = function (component) {  
  7.         switch (component) {  
  8.             case "reset":  
  9.                 $location.path("");  
  10.                 $location.hash("");  
  11.                 $location.search("");  
  12.                 break;  
  13.             case "path":  
  14.                 $location.path("/cities/london");  
  15.                 break;  
  16.             case "hash":  
  17.                 $location.hash("north");  
  18.                 break;  
  19.             case "search":  
  20.                 $location.search("select""hotels");  
  21.                 break;  
  22.             case "url":  
  23.                 $location.url("/cities/london?select=hotels#north");  
  24.                 break;  
  25.         }  
  26.     }  
  27.   
  28.     $scope.itemCount = 50;  
  29.     $scope.items = [];  
  30.     for (var i = 0; i < $scope.itemCount; i++) {  
  31.         $scope.items[i] = "Item " + i;  
  32.     }  
  33.     $scope.show = function (id) {  
  34.         $location.hash(id);  
  35.     }  
  36. });  
The output of the above program is as below,



Performing Logging

AngularJS provides the $log service, which is a wrapper around the global console object. The $log service defines debug, error, info, log, and warn methods that correspond to those defined by the console object.

Exception Service

AngularJS uses the $exceptionHandler service to handle any exceptions that arise during the execution of an application. The default implementation calls the error method defined by the $log service, which in turn calls the global console.error method. I think of exceptions in two broad categories. The first category includes those that occur during coding and testing, which are a natural part of the development cycle and help you shape the application you are building. The other category includes those that the user sees after you have released the application to the world. The way that you deal with these categories is different, but what’s needed in both situations is a consistent way of capturing those exceptions so that they can be responded to and, ideally, logged for future analysis. That’s where the $exceptionHandler service comes in. By default, it simply writes details of exceptions to the JavaScript console and allows the application to continue running (if that’s possible), but, as you’ll see, it can also be used to perform more sophisticated tasks, such as the ones you’ll need to keep your users happy and frustration-free when things go wrong after deployment.

Although AngularJS will automatically pass exceptions to the $exceptionHandler service, you can provide more context information by working directly with the service in your code. The $exceptionHandler service object is a function that takes two arguments: the exception and an optional string describing the exception’s cause. There can be only one cause of the exception in my example, so the cause argument isn’t that useful, but if you catch an exception in a loop processing data items, for example, it can be helpful to pass details of the data item that causes the problem as the cause.
exception.html
  1. <!DOCTYPE html>  
  2. <html ng-app="TestApp">  
  3. <head>  
  4.     <title>AngularJS Location Objects</title>  
  5.     <script src="angular.js"></script>  
  6.     <link href="../../RefStyle/bootstrap.min.css" rel="stylesheet" />  
  7.     <script src="app.js"></script>  
  8.     <script src="exception.js"></script>  
  9.   
  10. </head>  
  11. <body ng-controller="testController" class="well">  
  12.     <div class="panel panel-default">  
  13.         <div class="panel-body">  
  14.             <button class="btn btn-primary" ng-click="throwEx()">Throw Exception</button>  
  15.         </div>  
  16.     </div>  
  17. </body>  
  18. </html>  
exception.js
  1. testApp.controller("testController"function ($scope, $exceptionHandler) {  
  2.   
  3.     $scope.throwEx = function () {  
  4.         try {  
  5.             throw new Error("Triggered Exception");  
  6.         } catch (ex) {  
  7.             $exceptionHandler(ex.message, "Button Click");  
  8.         }  
  9.     }  
  10. });  
 The output of the program is as below,