Services are one of the important concepts in AngularJS. In general Services are functions that are responsible for specific tasks in an application. AngularJS services are designed based on two principles.
- Lazily instantiated: Angular only instantiates a service when an application component depends on it using dependency injection for making Angular the codes robust and less error prone.
- Singletons: Each component is dependent on a service that gets a reference to the single instance generated by the service factory.
AngularJS supports the concepts of "Separation of Concerns" using a services-oriented architecture and it is at the heart when designing an AngularJS application. Controllers, filters or directives can call them on the basis of requirements. The controller must be responsible for binding model data to views using $scope. It does not contain logic to fetch the data or manipulating it.
Services provide a method to share data across the lifetime of the AngularJS application. It provides a method to communicate data across the controllers in a consistent way. This is a singleton object and it is instantiated only once per application. It is used to organize and share data and functions across the application.
Thus a service is a stateless object that contains some useful functions. These functions can be called from anywhere; Controllers, Directive, Filters and so on. Thus we can divide our application into logical units. The business logic or logic to call HTTP URL to fetch data from the server can be put within a service object.
Putting business and other logic within services has many advantages. First, it fulfils the principle of separation of concerns or segregation of duties. Each component is responsible for its own work making application code more manageable and more testable. Thus we can quickly write tests for our services making them robust and less error-prone.
AngularJS provides many builtin services, for example, $http, $route, $window, $location and so on. Each service is responsible for a specific task, for example, $http is used to make an Ajax call to get the server data. $route defines the routing information and so on. Builtin services are always prefixed with the $ symbol.
AngularJS internal services
AngularJS internally provides many services that we can use in our application. $http is one example. There are other useful services, such as $route, $window, $location and so on. Some of the commonly used services in any AngularJS applications are listed below.
- $window: Provide a reference to a DOM object.
- $Location: Provides reference to the browser location.
- $timeout: Provides a reference to window.settimeout function.
- $Log: Used for logging.
- $sanitize: Used to avoid script injections and display raw HTML in page.
- $Rootscope: Used for scope hierarchy manipulation.
- $Route: Used to display browser based path in browser URL.
- $Filter: Used for providing filter access.
- $resource: Used to work with Restful API.
- $document: Used to access the window. Document object.
- $exceptionHandler: Used for handling exceptions.
- $q: Provides a promise object.
Here, the question arises in our mind that we had window, window.Location, document and timeout in the DOM in JavaScript, so why does $window, $location, $document, $timeout in terms of a services. The reason behind is to support dependency injection and to more easily test using a mocked version of $window, $location, $document and $timeout services.
So what is the mocked version and what is mocking?
Mocking is primarily used in unit testing. An object under test may have dependencies on other (complex) objects. To isolate the behaviour of the object you want to test you replace the other objects by mocks that simulate the behaviour of the real objects. This is useful if the real objects are impractical to incorporate into the unit test.
Let's understand some of the AngularJS internal services.
$window Service
Example-1
- <!DOCTYPE html>
- <html ng-app="WindowsServiceapp">
- <head>
- <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.9/angular.min.js"></script>
- <script>
- angular.module("WindowsServiceapp", [])
- .controller("WindowsServicectrl", function ($scope, $window)
- {
- $scope.dissplayAlert = function (msg)
- {
- $window.open("http://www.google.com", "test", 'height=200,width=550');
- $window.document.write("Testing....");
- $window.alert(msg);
- }
- });
- </script>
- </head>
- <body>
- <div ng-app="WindowsServiceapp">
- <div ng-controller="WindowsServicectrl">
- <div>
- <button name="btn" ng-click="dissplayAlert('clicked')">click me </button>
- </div>
- </div>
- </div>
- </body>
- </html>
Output
Here in the “WindowsServicectrl” $window service is injected and showing an alert and opening pop-up window in the preceding example. Note that $windows is not the same window object. To keep the window object an injectable component for manipulation of AngularJS that has created a wrapper on the window object.
$http ServicesLet us understand the $http service that makes a service call for server communication. Now we will see a simple Http service that is used to fetch the data from a SQL Server database.
We have an employee table that contains some employee information as in the following:
We have a web API that is a source of a data layer that connects to a database and we need to call it using Angular code.
Example 2
- public class EmployeeAPIController: ApiController
- {
- private EmployeeEntities db = new EmployeeEntities();
- public IEnumerable < Employee > GetEmployees()
- {
- return db.Employees.AsEnumerable();
- }
- }
Service
- app.service('EmployeeService', function ($http)
- {
- this.getAllEmployee = function ()
- {
- return $http.get("/api/EmployeeAPI");
- }
- });
Controller
- app.controller('EmployeeController', function($scope, EmployeeService)
- {
- GetAllRecords();
- function GetAllRecords()
- {
- var promiseGet = EmployeeService.getAllEmployee();
- promiseGet.then(function(pl)
- {
- $scope.Employees = pl.data
- },
- function(errorPl)
- {
- $log.error('Some Error in Getting Records.', errorPl);
- });
- }
- });
Module
- var app;
- (function ()
- {
- app = angular.module("EmployeeModule", []);
- })();
HTML Page
- <html ng-app="EmployeeModule">
- <head>
- <style type="text/css">
- table.table-style
- {
- font-family: verdana, arial, sans-serif;
- font-size: 11px;
- color: #333333;
- border-width: 1px;
- border-color: #3A3A3A;
- border-collapse: collapse;
- border: 2px solid gray;
- background-color: #f5f5f5;
- }
- table.table-style th
- {
- border-width: 1px;
- padding: 8px;
- border-style: solid;
- border-color: #FFA6A6;
- background-color: #D56A6A;
- color: #ffffff;
- }
- table.table-style tr:hover td
- {
- cursor: pointer;
- }
- table.table-style tr:nth-child(even) td
- {
- background-color: #F7CFCF;
- }
- table.table-style td
- {
- border-width: 1px;
- padding: 8px;
- border-style: solid;
- border-color: #FFA6A6;
- background-color: #ffffff;
- }
- </style>
- </head>
- <body data-ng-controller="EmployeeController">
- <table class="table-style">
- <tr>
- <th>ID</th>
- <th>Name</th>
- <th>Role</th>
- <th>Birth Day</th>
- <th>Gender</th>
- <th>HireDate</th>
- </tr>
- <tbody data-ng-repeat="emp in Employees">
- <tr>
- <td>
- <span>{{emp.EmployeeID}}</span>
- </td>
- <td>
- <span>{{emp.Name}}</span>
- </td>
- <td>
- <span>{{emp.Title}}</span>
- </td>
- <td>
- <span>{{emp.BirthDate}}</span>
- </td>
- <td>
- <span>{{emp.Gender}}</span>
- </td>
- <td>
- <span>{{emp.HireDate}}</span>
- </td>
- </tr>
- </tbody>
- </table>
- </body>
- </html>
- <script src="~/Scripts/angular.js"></script>
- <script src="~/Scripts/EmployeeScripts/Module.js"></script>
- <script src="~/Scripts/EmployeeScripts/Service.js"></script>
- <script src="~/Scripts/EmployeeScripts/Controller.js"></script>
Output
User Defined ServicesLet us create some of the services that we need to write based on our requirements. We will create a calculation web page that does Addition, Subtraction, Multiplication and Division. We will create a service called "CalculatorService" and call this calculator service in the controller. From the controller the service results are assigned to the Scope object and finally shown to the UI.
Example 3
- <!DOCTYPE html>
- <html ng-app="app">
- <head>
- <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.9/angular.min.js">
- <script>
- var CalculatorService = angular.module('CalculatorService', [])
- .service('Calculator', function ()
- {
- this.Add = function (a, b) { return Number(a) + Number(b) };
- this.Sub = function (a, b) { return Number(a) - Number(b) };
- this.Mul = function (a, b) { return Number(a) * Number(b) };
- this.Div = function (a, b) { return Number(a) / Number(b) };
- });
- var myApp = angular.module('app', ['CalculatorService']);
- myApp.controller('CalculatorController', function ($scope, Calculator) {
- $scope.doAdd = function ()
- {
- $scope.result = Calculator.Add($scope.a, $scope.b);
- }
- $scope.doSub = function ()
- {
- $scope.result = Calculator.Sub($scope.a, $scope.b);
- }
- $scope.doMul = function ()
- {
- $scope.result = Calculator.Mul($scope.a, $scope.b);
- }
- $scope.doDiv = function ()
- {
- $scope.result = Calculator.Div($scope.a, $scope.b);
- }
- });
- </script>
- </head>
- <body>
- <div ng-app="app">
- <div ng-controller="CalculatorController">
- <div>
- <table style="width: 600px; border: 2px solid gray; background-color: #f5f5f5;">
- <tr>
- <td>
- <strong></strong>
- </td>
- <td>
- <strong>Calculator Service</strong>
- </td>
- <td>
- <strong></strong>
- </td>
- <td>
- <strong></strong>
- </td>
- <td>
- <strong></strong>
- </td>
- </tr>
- <tr>
- <td>
- <strong>Enter First Number:</strong>
- </td>
- <td>
- <input type="text" ng-model="a" />
- </td>
- <td></td>
- <td></td>
- <td></td>
- </tr>
- <tr>
- <td>
- <strong>Enter Second Number:</strong>
- </td>
- <td>
- <input type="text" ng-model="b" />
- </td>
- <td></td>
- <td></td>
- <td></td>
- </tr>
- <br />
- <tr>
- <td></td>
- <td>
- <button ng-click="doAdd()">Add</button>
- <button ng-click="doSub()">Subtract</button>
- <button ng-click="doMul()">Multify</button>
- <button ng-click="doDiv()">Divide</button>
- </td>
- <td></td>
- <td></td>
- <td></td>
- </tr>
- <tr>
- <td>
- <strong>The Result from Calculation Service is: </strong>
- <b>{{result}}</b>
- </td>
- </tr>
- </table>
- </div>
- </div>
- </div>
- </body>
- </html>
Output
So we created a service and saw the result of the service.
In general, a service can be created in many ways, they are:
- Service
- Factory
- Provider
- Value
- Constant
Factory: A factory is a simple function that allows you to add some logic before creating the object. It returns the created object.
Example of defining a factory
-
- function app.factory('MyFactory', function()
- {
- var serviceObj = {};
- serviceObj.fun1 = function()
- {
-
- };
- serviceObj.fun2 = function()
- {
-
- };
- return serviceObj;
- });
When to use Factory: It is just a collection of functions like a class. Hence, it can be instantiated in different controllers when you are using it with a constructor function.
Service: A service is a constructor function that creates the object using the new keyword. You can add properties and functions to a service object using this keyword. Unlike factory, it doesn't return anything.
Example of define a service using service()
- function app.service('MyService', function()
- {
- this.func1 = function()
- {
-
- };
- this.fun2 = function()
- {
-
- };
- });
When to use Service: It is a singleton object. Use it when you need to share a single object across the application. For example, authenticated user details, share-able data and so on.
Provider: A provider is used to create a configurable service object. It returns a value using the $get() function.
Example of defining define a provider
- function app.provider('configurable', function()
- {
- var privateName = '';
- this.setName = function(newName)
- {
- privateName = newName;
- };
- this.$get = function()
- {
- return
- {
- name: privateName
- };
- };
- });
-
- function app.config(function(configurableService)
- {
- configurableService.setName('Angular Js Provider sample');
- });
When to use provider: When you need to provide a module-wise configuration for your service object before making it available. You should use the Provider recipe only when you want to expose an API for application-wide configuration that must be made before the application starts.
Value: Values are simple objects that are used to share data globally within a module. A value can be a number, string, date-time, array or object. You can also register a function as a value.
Example 4
- <!DOCTYPE html>
- <html ng-app="app">
- <head>
- <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.9/angular.min.js"></script>
- <script>
- var app = angular.module('app', []);
- app.value('Data',
- {message:"I am data from a service"}
- )
- app.controller('FirstCtrl', function($scope, Data)
- {
- $scope.data = Data;
- console.log($scope.data)
- });
- </script>
- </head>
- <body >
- <div ng-controller="FirstCtrl">
- <input type="text" ng-model="data.message">
- <br>data.message={{data.message}}
- </div>
- </body>
- </html>
Output
Constant: A constant is like a value. The difference between a value and a constant service is that a constant service can be injected into a module configuration function, in other words config() or run() but a value service cannot be.
Example 5
- <!DOCTYPE html>
- <html>
- <head>
- <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.9/angular.min.js"></script>
- <meta charset="utf-8">
- <title>Validated constants</title>
- <script>
-
- angular.module('MyApp.Constants', []);
- angular.module('MyApp', ['MyApp.Constants'])
- .run(function ($rootScope, username)
- {
- // start using constants module
- $rootScope.username = username;
- });
- </script>
- </head>
- <body ng-app="MyApp">
- <script>
- // inject actual values when needed, the module already exists
- angular.module('MyApp.Constants').constant('username', 'World');
- </script>
- <p>Hello, {{ username }}</p>
- </body>
- </html>
Output: Hello, World
We could not provide any default values for the constants. We could not validate the constants passed to the module until much later, or by making a dummy.run call just to validate them.
Let us see a sample wherein we will write 3 ways to return the service by factory, provider and services in three ways as stated earlier.
Example 6
- <!DOCTYPE html>
- <html ng-app="myApp">
- <head>
- <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.9/angular.min.js"></script>
- <script>
- var myApp = angular.module('myApp', []);
- //Creating as service
- myApp.service('helloWorldFromService', function ()
- {
- this.sayHello = function ()
- {
- return "Hello, World!:I am From Service"
- };
- });
- //Creating as factory as a return function
- myApp.factory('helloWorldFromFactory', function ()
- {
- return
- {
- sayHello: function ()
- {
- return "Hello, World!:I am From Factory"
- }
- };
- });
- //Creating as provider as a getter
- myApp.provider('helloWorld', function ()
- {
- this.name = 'Default';
- this.$get = function ()
- {
- var name = this.name;
- return
- {
- sayHello: function ()
- {
- return "Hello, " + name + "!:I am From provider"
- }
- }
- };
- this.setName = function (name)
- {
- this.name = name;
- };
- });
- myApp.config(function (helloWorldProvider)
- {
- helloWorldProvider.setName('World');
- });
- myApp.controller('MyCtrl', function ($scope, helloWorld, helloWorldFromFactory, helloWorldFromService) {
- $scope.hellos = [
- helloWorld.sayHello(),
- helloWorldFromFactory.sayHello(),
- helloWorldFromService.sayHello()];
- });
- </script>
- </head>
- <body ng-app="myApp">
- <div ng-controller="MyCtrl">
- {{hellos}}
- </div>
- </body>
- </html>
Output Both services and factory providers get the same output but the choice of when to use them is important.
We can call services inside a service too. Consider a scenario in a real application with a service called Authentication services and RoleServices that must be determined based on the Authentication services result. On that scenario we need to call services inside services. Let's see a simple example to demonstrate this. We have a service named
MathService and
CalculatorService. The Calculator Service needs
MathService as a dependent service.
Example 7
- <!DOCTYPE html>
- <html ng-app="app">
- <head>
- <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.9/angular.min.js"></script>
- <script type='text/javascript'>
- var app = angular.module('app', []);
- app.service('MathService', function () {
- this.multiply = function (a, b) { return a * b };
- });
- app.service('CalculatorService', function (MathService) {
- this.square = function (a) { return MathService.multiply(a, a); };
- this.cube = function (a) { return MathService.multiply(a, MathService.multiply(a, a)); };
- });
- app.controller('CalculatorController', function ($scope, CalculatorService) {
- $scope.doSquare = function () {
- $scope.answer = CalculatorService.square($scope.number);
- }
- $scope.doCube = function () {
- $scope.answer = CalculatorService.cube($scope.number);
- }
- });
- </script>
- </head>
- <body>
- <div ng-app="app">
- <div ng-controller="CalculatorController">
- Enter a number
- <input type="number" ng-model="number" />
- <button ng-click="doSquare()">X
- <sup>2</sup>
- </button>
- <button ng-click="doCube()">X
- <sup>3</sup>
- </button>
- <div>The Answer is: {{answer}}</div>
- </div>
- </div>
- </body>
- </html>
Output
This is all about the basics of services in AngularJS. In the next article I will return with more on services. I hope you now have a basic knowledge of services.
Thanks for reading.