AngularJS services are functions or objects that can hold behavior or state throughout application. They are used to implement shared behavior/reusable logic which can be used by other components in your AngularJS application. AngularJS services are singletons, means each service is instantiated only once, so each part of our application gets access to the same instance of the AngularJS service. AngularJS services are lazily instantiated, means Angular only instantiates a service when an application component who depends on it [another service, controller or directive e.g.], gets loaded.
Do note that AngularJS services are different than AngularJS controllers. Controllers are created and destroyed several times while navigating to different views, but services are instantiated only once and then reused everywhere in application.
Common use of Services : Communicating with Server, Repeated behavior, Reusable business logic, application-level stores, shared state, etc.
The whole AngularJS service concept is driven by AngularJS Dependency Injection system. Any service can be injected into another service, controller or directive, by just declaring it as a dependency, and AngularJS will do the rest.
$log, $window, $location, $http are few examples of built-in services. A built-in AngularJS service name starts with $. For complete list, check out the AngularJS documentation.
An AngularJS service can be implemented as a factory, service, or provider. Choosing specially between factory and provider depends on your coding style and preference.
A Factory is created using module.factory
function. It is useful if you follow a functional style of programming and you prefer to return functions and objects.
<html ng-app="myApp"> <head> <title>Factory Demo</title> </head> <body ng-controller="AppController as ctrl"> <label>Name :</label><input type="text" ng-model="ctrl.name" placeholder="Enter your name"/><br/><br/> <span ng-bind="ctrl.message"></span> <br/><br/> <button ng-click="ctrl.hello()"> Hello Message </button> <button ng-click="ctrl.bye()"> Bye Message </button> <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.4/angular.js"> </script> <script> angular.module('myApp',[]) .factory('GreetingService', [function() { return { sayHello : function(name) { return "Hello " + name; }, sayBye : function(name) { return "Bye " + name; } } }]) .controller('AppController', ['GreetingService', function(GreetingService) { var self = this; self.name=''; self.message=''; self.hello = function() { self.message = GreetingService.sayHello(self.name); }; self.bye = function(name) { self.message = GreetingService.sayBye(self.name); }; }]); </script> </body> </html>
In this case, service definition function of factory returns an object [with two methods that can be invoked], which becomes the public API for our service.
A Service is created using module.service
function. It is useful if you follow a Class/OO style of programming, where we define classes and types instead of functions and objects. With service, the function definition is actually a class/type, and AngularJS calls new on it to create an instance of it. But remember. only one instance will be created, as we know that AngularJS services are singletons.
<html ng-app="myApp"> <head> <title>Factory Demo</title> <style>body{font-family:"Arial";background-color:#E2E2DC}</style> </head> <body ng-controller="AppController as ctrl"> <label>Name :</label><input type="text" ng-model="ctrl.name" placeholder="Enter your name"/><br/><br/> <span ng-bind="ctrl.message"></span> <br/><br/> <button ng-click="ctrl.hello()"> Hello Message </button> <button ng-click="ctrl.bye()"> Bye Message </button> <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.4/angular.js"> </script> <script> angular.module('myApp',[]) .service('GreetingService', [function() { this.sayHello = function(name) { return "Hello " + name; }; this.sayBye = function(name) { return "Bye " + name; }; }]) .controller('AppController', ['GreetingService', function(GreetingService) { var self = this; self.name=''; self.message=''; self.hello = function() { self.message = GreetingService.sayHello(self.name); }; self.bye = function(name) { self.message = GreetingService.sayBye(self.name); }; }]); </script> </body> </html>
Take special note that our service definition function is now a JavaScript class function. It doesn’t return anything. AngularJS will perform new GreetingService() (with possible dependencies injected in) , cache it, and then return that instance to all components that depends on GreetingService. Note that since new was used to instantiate the service, the keyword this is valid and refers to the instance.
Interestingly, nothing changes in Controller’s code and in HTML compare to previous Factory example. Only difference between these two examples are use of Factory vs Service or i can say ‘return from function’ vs ‘new service’.
Creating an AngularJS Service using provider is not a very common approach, but comes handy when you want to provide a configuration for your service before it can be used. A provider is used to create a configurable service object. In this approach you usually provide the service configuration using module.config
function. Provider includes a $get
function which gets executed in run phase. It is the return value from the $get function [the service which you configured based on your requirement] that will be cached and injected when the service is requested.
<html ng-app="myApp"> <head> <title>Service Demo</title> <style>body{font-family:"Arial";background-color:#E2E2DC}</style> </head> <body ng-controller="AppController as ctrl"> <label>Name :</label><input type="text" ng-model="ctrl.name" placeholder="Enter your name"/><br/><br/> <span ng-bind="ctrl.message"></span> <br/><br/> <button ng-click="ctrl.hello()"> Hello Message </button> <button ng-click="ctrl.bye()"> Bye Message </button> <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.4/angular.js"> </script> <script> function MessagingService(queueType) { this.getQueueType = function() { return queueType; }; this.sayHello = function(name) { return "Hello " + name +", Sent using "+ queueType; }; this.sayBye = function(name) { return "Bye " + name +", Sent using "+ queueType; }; } angular.module('myApp',[]) .provider('MessagingService', function() { var env=''; this.setEnvironment = function(environment) { env = environment; }; // This function gets any injected dependencies, not the provider above. this.$get = [function() { var queueType = ''; if (env==='DEVELOPMENT') { queueType = 'activeMq'; }else{ queueType = 'WebSphereMq'; } return new MessagingService(queueType); }]; }) .config(['MessagingServiceProvider', function(MessagingServiceProvider) { //Set the environment to a different value to see different behavior. MessagingServiceProvider.setEnvironment('DEVELOPMENT'); //MessagingServiceProvider.setEnvironment('UAT'); }]) .controller('AppController', ['MessagingService', function(MessagingService) { var self = this; self.name=''; self.message=''; self.hello = function() { self.message = MessagingService.sayHello(self.name); }; self.bye = function(name) { self.message = MessagingService.sayBye(self.name); }; }]); </script> </body> </html>
In above provider setup, we have a provider with a set function, which can be used in module.config function to set some configuration. This updated configuration will eventually be used while creating the actual service instance. This instance will be created and returned via $get function. It’s the output from $get which will be injected into our controller.
Angular provides us ways to define data that remains globally available while not really polluting the global namespace. Constant and Values are our options to define globally available data, which can be injected as a dependency into other service or controller.
Constant & Value are similar with few differences:
– A constant can be injected everywhere. The Value of a constant is not meant to be changed, and should never be changed.
var app = angular.module('myApp', []); app.constant('PI', 3.14); app.controller('AppController', ['PI', function(PI) { var self = this; self.r = 2; self.getArea = function(){ return PI * r * r; } }]);
– a Value can be changed. Unlike Constant, A value can not be injected into config phase of application.
var app = angular.module('myApp', []); app.value('loggedinUser', 'SAM'); app.controller('AppController', ['loggedinUser', function(loggedinUser) { var self = this; self.message = 2; self.printMessage = function(){ return 'Welcome '+loggedinUser; } }]);
In above Value example, loggedinUser remain same for all the session, so it’s a good candidate to be declared as VALUE.
That’s it. In the next post AngularJS $http service example-server communication, we will develop a full-fledged live example for server communication using $http service. Stay tune.
If you like tutorials on this site, why not take a step further and connect me on Facebook , Google Plus & Twitter as well? I would love to hear your thoughts on these articles, it will help improve further our learning process.
In this post we will be developing a full-blown CRUD application using Spring Boot, AngularJS, Spring Data, JPA/Hibernate and MySQL,…
Spring Boot complements Spring REST support by providing default dependencies/converters out of the box. Writing RESTful services in Spring Boot…
Being able to start the application as standalone jar is great, but sometimes it might not be possible to run…
Spring framework has taken the software development industry by storm. Dependency Injection, rock solid MVC framework, Transaction management, messaging support,…
Let's secure our Spring REST API using OAuth2 this time, a simple guide showing what is required to secure a…
This post shows how an AngularJS application can consume a REST API which is secured with Basic authentication using Spring…
View Comments
One more question please:
regarding Const and Value...
You mention that "a value can not be injected into config phase of application" and in your example "loggedinUser remain same for all the session, so it’s a good candidate to be declared as VALUE"
If loggedinUser behaves like that why it is NOT a good candidate for CONST?
And in your example loggedinUser is injected in exactly the same manner as PI injected in example above.
So both examples look identical to me :( except for app.value('loggedinUser', 'SAM') line
Can you please clarify why and when do we need a Value?
Thank you so much
Hi Andrey, Both CONSTANT and VALUE refers to something which will remain fixed. They are conceptually different. The way i use them is that something should be declared as CONSTANT if it's value is fixed and should not be changed in any circumstances [Value of PI is fixed, radius of earth is fixed]. On the other hand, if something is going to remain fixed in specific context and change in other, put is as a VALUE. LoggedInUser is the Logged-in user, which will differ for each user. Finally, no-one is stopping you putting loggedInUser as CONSTANT. You as a developer have a choice to decide which one[or both] fits your needs both programatically and conceptually.
Hello, thank you for that wonderful tutorial which makes a lot of Angular concepts much clearer.
Could you please explain what is the purpose of prefixing service attributes with 'this' and controller attributes with 'self'?
What is the difference between those two?
I have seen (at Java Brains course on Angular for example) how controller properties have been prefixed with 'this' as well - when controller name was aliased. So can we use both of them whenever we want or just in specific cases?
Thank you so much in advance
Hi Andrey,
It is preferable to use proxies like 'self' [or 'vm' as some people prefer] instead of using 'this' due to the fact that 'this' keyword in a javascript function can be overridden by anyone calling that function. Now on question of 'self vs this' in 'controller & services', you may want to use 'self' in both cases. I would also recommend Angular Coding Style Guide. Additionally, i would recommend you to have a look at this post which follows the coding guidelines mentioed in the previous link.