Showing posts with label AngularJS. Show all posts
Showing posts with label AngularJS. Show all posts

Friday, 15 April 2016

Service vs provider vs factory


Services


Syntax: module.service( 'serviceName', function );
Result: When declaring serviceName as an injectable argument you will be provided with an instance of the function. In other words new FunctionYouPassedToService().

Factories


Syntax: module.factory( 'factoryName', function );
Result: When declaring factoryName as an injectable argument you will be provided with the value that is returned by invoking the function reference passed to module.factory.

Providers


Syntax: module.provider( 'providerName', function );
Result: When declaring providerName as an injectable argument you will be provided with (new ProviderFunction()).$get(). The constructor function is instantiated before the $get method is called - ProviderFunction is the function reference passed to module.provider.

Providers have the advantage that they can be configured during the module configuration phase.

See here for the provided code.

Here's a great further explanation by Misko:
provide.value('a', 123);

function Controller(a) {
expect
(a).toEqual(123);
}

In this case the injector simply returns the value as is. But what if you want to compute the value? Then use a factory
provide.factory('b', function(a) {
return a*2;
});

function Controller(b) {
expect
(b).toEqual(246);
}

So factory is a function which is responsible for creating the value. Notice that the factory function can ask for other dependencies.

But what if you want to be more OO and have a class called Greeter?
function Greeter(a) {
this.greet = function() {
return 'Hello ' + a;
}
}

Then to instantiate you would have to write
provide.factory('greeter', function(a) {
return new Greeter(a);
});

Then we could ask for 'greeter' in controller like this
function Controller(greeter) {
expect
(greeter instanceof Greeter).toBe(true);
expect
(greeter.greet()).toEqual('Hello 123');
}

But that is way too wordy. A shorter way to write this would be provider.service('greeter', Greeter);

But what if we wanted to configure the Greeter class before the injection? Then we could write
provide.provider('greeter2', function() {
var salutation = 'Hello';
this.setSalutation = function(s) {
salutation
= s;
}

function Greeter(a) {
this.greet = function() {
return salutation + ' ' + a;
}
}

this.$get = function(a) {
return new Greeter(a);
};
});

Then we can do this:
angular.module('abc', []).config(function(greeter2Provider) {
greeter2Provider
.setSalutation('Halo');
});

function Controller(greeter2) {
expect
(greeter2.greet()).toEqual('Halo 123');
}

As a side note, service, factory, and value are all derived from provider.
provider.service = function(name, Class) {
provider
.provide(name, function() {
this.$get = function($injector) {
return $injector.instantiate(Class);
};
});
}

provider
.factory = function(name, factory) {
provider
.provide(name, function() {
this.$get = function($injector) {
return $injector.invoke(factory);
};
});
}

provider
.value = function(name, value) {
provider
.factory(name, function() {
return value;
});
};

Understanding AngularJS scope life-cycle

Scope data goes through a life cycle when the angular app is loaded into the browser. Understanding the scope life cycle will help you to understand the interaction between scope and other AngularJS components.

The scope data goes through the following life cycle phases:


  1. Creation


    This phase initialized the scope. The root scope is created by the $injector when the application is bootstrapped. During template linking, some directives create new child scopes.

    A digest loop is also created in this phase that interacts with the browser event loop. This digest loop is responsible to update DOM elements with the changes made to the model as well as executing any registered watcher functions.


  2. Watcher registration


    This phase registers watches for values on the scope that are represented in the template. These watches propagate model changes automatically to the DOM elements.

    You can also register your own watch functions on a scope value by using the $watch() function.


  3. Model mutation


    This phase occurs when data in the scope changes. When you make the changes in your angular app code, the scope function $apply() updates the model and calls the $digest() function to update the DOM elements and registered watches.

    When you do the changes to scope inside your angular code like within controllers or services, angular internally call $apply() function for you. But when you do the changes to the scope outside the angular code, you have to call $apply() function explicitly on the scope to force the model and DOM to be updated correctly.


  4. Mutation observation


    This phase occurs when the $digest() function is executed by the digest loop at the end of $apply() call. When $digest() function executes, it evaluates all watches for model changes. If a value has been changed, $digest() calls the $watch listener and updates the DOM elements.


  5. Scope destruction


    This phase occurs when child scopes are no longer needed and these scopes are removed from the browser’s memory by using $destroy() function. It is the responsibility of the child scope creator to destroy them via scope.$destroy() API.

    This stop propagation of $digest calls into the child scopes and allow the memory to be reclaimed by the browser garbage collector.

What do you think?


I hope you will enjoy the AngularJS scopes while developing your app with AngularJS. I would like to have feedback from my blog readers. Your valuable feedback, question, or comments about this article are always welcome.

Thursday, 14 April 2016

AngularJS vs jQuery

1. Don't design your page, and then change it with DOMmanipulations


In jQuery, you design a page, and then you make it dynamic. This is because jQuery was designed for augmentation and has grown incredibly from that simple premise.

But in AngularJS, you must start from the ground up with your architecture in mind. Instead of starting by thinking "I have this piece of the DOM and I want to make it do X", you have to start with what you want to accomplish, then go about designing your application, and then finally go about designing your view.

2. Don't augment jQuery with AngularJS


Similarly, don't start with the idea that jQuery does X, Y, and Z, so I'll just add AngularJS on top of that for models and controllers. This is really tempting when you're just starting out, which is why I always recommend that new AngularJS developers don't use jQuery at all, at least until they get used to doing things the "Angular Way".

I've seen many developers here and on the mailing list create these elaborate solutions with jQuery plugins of 150 or 200 lines of code that they then glue into AngularJS with a collection of callbacks and$applys that are confusing and convoluted; but they eventually get it working! The problem is that inmost cases that jQuery plugin could be rewritten in AngularJS in a fraction of the code, where suddenly everything becomes comprehensible and straightforward.

The bottom line is this: when solutioning, first "think in AngularJS"; if you can't think of a solution, ask the community; if after all of that there is no easy solution, then feel free to reach for the jQuery. But don't let jQuery become a crutch or you'll never master AngularJS.

3. Always think in terms of architecture


First know that single-page applications are applications. They're not webpages. So we need to think like a server-side developer in addition to thinking like a client-side developer. We have to think about how to divide our application into individual, extensible, testable components.

So then how do you do that? How do you "think in AngularJS"? Here are some general principles, contrasted with jQuery.

The view is the "official record"


In jQuery, we programmatically change the view. We could have a dropdown menu defined as a ullike so:
<ul class="main-menu">
    <li class="active">
        <a href="#/home">Home</a>
    </li>
    <li>
        <a href="#/menu1">Menu 1</a>
        <ul>
            <li><a href="#/sm1">Submenu 1</a></li>
            <li><a href="#/sm2">Submenu 2</a></li>
            <li><a href="#/sm3">Submenu 3</a></li>
        </ul>
    </li>
    <li>
        <a href="#/home">Menu 2</a>
    </li>
</ul>

In jQuery, in our application logic, we would activate it with something like:
$('.main-menu').dropdownMenu();

When we just look at the view, it's not immediately obvious that there is any functionality here. For small applications, that's fine. But for non-trivial applications, things quickly get confusing and hard to maintain.

In AngularJS, though, the view is the official record of view-based functionality. Our ul declaration would look like this instead:
<ul class="main-menu" dropdown-menu>
    ...</ul>

These two do the same thing, but in the AngularJS version anyone looking at the template knows what's supposed to happen. Whenever a new member of the development team comes on board, she can look at this and then know that there is a directive called dropdownMenu operating on it; she doesn't need to intuit the right answer or sift through any code. The view told us what was supposed to happen. Much cleaner.

Developers new to AngularJS often ask a question like: how do I find all links of a specific kind and add a directive onto them. The developer is always flabbergasted when we reply: you don't. But the reason you don't do that is that this is like half-jQuery, half-AngularJS, and no good. The problem here is that the developer is trying to "do jQuery" in the context of AngularJS. That's never going to work well. The view is the official record. Outside of a directive (more on this below), you never, ever, neverchange the DOM. And directives are applied in the view, so intent is clear.

Remember: don't design, and then mark up. You must architect, and then design.

Data binding


This is by far one of the most awesome features of AngularJS and cuts out a lot of the need to do the kinds of DOM manipulations I mentioned in the previous section. AngularJS will automatically update your view so you don't have to! In jQuery, we respond to events and then update content. Something like:
$.ajax({
  url: '/myEndpoint.json',
  success: function ( data, status ) {
    $('ul#log').append('<li>Data Received!</li>');
  }
});

For a view that looks like this:
<ul class="messages" id="log">
</ul>

Apart from mixing concerns, we also have the same problems of signifying intent that I mentioned before. But more importantly, we had to manually reference and update a DOM node. And if we want to delete a log entry, we have to code against the DOM for that too. How do we test the logic apart from the DOM? And what if we want to change the presentation?

This a little messy and a trifle frail. But in AngularJS, we can do this:
$http( '/myEndpoint.json' ).then( function ( response ) {
    $scope.log.push( { msg: 'Data Received!' } );
});

And our view can look like this:
<ul class="messages">
    <li ng-repeat="entry in log">{{ entry.msg }}</li>
</ul>

But for that matter, our view could look like this:
class="messages">

class="alert" ng-repeat="entry in log"> {{ entry.msg }}

</div>

And now instead of using an unordered list, we're using Bootstrap alert boxes. And we never had to change the controller code! But more importantly, no matter where or how the log gets updated, the view will change too. Automatically. Neat!

Though I didn't show it here, the data binding is two-way. So those log messages could also be editable in the view just by doing this: <input ng-model="entry.msg" />. And there was much rejoicing.

Distinct model layer


In jQuery, the DOM is kind of like the model. But in AngularJS, we have a separate model layer that we can manage in any way we want, completely independently from the view. This helps for the above data binding, maintains separation of concerns, and introduces far greater testability. Other answers mentioned this point, so I'll just leave it at that.

Separation of concerns


And all of the above tie into this over-arching theme: keep your concerns separate. Your view acts as the official record of what is supposed to happen (for the most part); your model represents your data; you have a service layer to perform reusable tasks; you do DOM manipulation and augment your view with directives; and you glue it all together with controllers. This was also mentioned in other answers, and the only thing I would add pertains to testability, which I discuss in another section below.

Dependency injection


To help us out with separation of concerns is dependency injection (DI). If you come from a server-side language (from Java to PHP) you're probably familiar with this concept already, but if you're a client-side guy coming from jQuery, this concept can seem anything from silly to superfluous to hipster. But it's not. :-)

From a broad perspective, DI means that you can declare components very freely and then from any other component, just ask for an instance of it and it will be granted. You don't have to know about loading order, or file locations, or anything like that. The power may not immediately be visible, but I'll provide just one (common) example: testing.

Let's say in our application, we require a service that implements server-side storage through a RESTAPI and, depending on application state, local storage as well. When running tests on our controllers, we don't want to have to communicate with the server - we're testing the controller, after all. We can just add a mock service of the same name as our original component, and the injector will ensure that our controller gets the fake one automatically - our controller doesn't and needn't know the difference.

Speaking of testing...

4. Test-driven development - always


This is really part of section 3 on architecture, but it's so important that I'm putting it as its own top-level section.

Out of all of the many jQuery plugins you've seen, used, or written, how many of them had an accompanying test suite? Not very many because jQuery isn't very amenable to that. But AngularJS is.

In jQuery, the only way to test is often to create the component independently with a sample/demo page against which our tests can perform DOM manipulation. So then we have to develop a component separately and then integrate it into our application. How inconvenient! So much of the time, when developing with jQuery, we opt for iterative instead of test-driven development. And who could blame us?

But because we have separation of concerns, we can do test-driven development iteratively in AngularJS! For example, let's say we want a super-simple directive to indicate in our menu what our current route is. We can declare what we want in the view of our application:
<a href="/hello" when-active>Hello</a>

Okay, now we can write a test for the non-existent when-active directive:
it( 'should add "active" when the route changes', inject(function() {
    var elm = $compile( '<a href="/hello" when-active>Hello</a>' )( $scope );

    $location.path('/not-matching');
    expect( elm.hasClass('active') ).toBeFalsey();

    $location.path( '/hello' );
    expect( elm.hasClass('active') ).toBeTruthy();
}));

And when we run our test, we can confirm that it fails. Only now should we create our directive:
.directive( 'whenActive', function ( $location ) {
    return {
        scope: true,
        link: function ( scope, element, attrs ) {
            scope.$on( '$routeChangeSuccess', function () {
                if ( $location.path() == element.attr( 'href' ) ) {
                    element.addClass( 'active' );
                }
                else {
                    element.removeClass( 'active' );
                }
            });
        }
    };
});

Our test now passes and our menu performs as requested. Our development is both iterative andtest-driven. Wicked-cool.

5. Conceptually, directives are not packaged jQuery


You'll often hear "only do DOM manipulation in a directive". This is a necessity. Treat it with due deference!

But let's dive a little deeper...

Some directives just decorate what's already in the view (think ngClass) and therefore sometimes do DOM manipulation straight away and then are basically done. But if a directive is like a "widget" and has a template, it should also respect separation of concerns. That is, the template too should remain largely independent from its implementation in the link and controller functions.

AngularJS comes with an entire set of tools to make this very easy; with ngClass we can dynamically update the class; ngModel allows two-way data binding; ngShow and ngHideprogrammatically show or hide an element; and many more - including the ones we write ourselves. In other words, we can do all kinds of awesomeness without DOM manipulation. The less DOM manipulation, the easier directives are to test, the easier they are to style, the easier they are to change in the future, and the more re-usable and distributable they are.

I see lots of developers new to AngularJS using directives as the place to throw a bunch of jQuery. In other words, they think "since I can't do DOM manipulation in the controller, I'll take that code put it in a directive". While that certainly is much better, it's often still wrong.

Think of the logger we programmed in section 3. Even if we put that in a directive, we still want to do it the "Angular Way". It still doesn't take any DOM manipulation! There are lots of times when DOM manipulation is necessary, but it's a lot rarer than you think! Before doing DOM manipulationanywhere in your application, ask yourself if you really need to. There might be a better way.

Here's a quick example that shows the pattern I see most frequently. We want a toggleable button. (Note: this example is a little contrived and a skosh verbose to represent more complicated cases that are solved in exactly the same way.)
.directive( 'myDirective', function () {
    return {
        template: '<a class="btn">Toggle me!</a>',
        link: function ( scope, element, attrs ) {
            var on = false;

            $(element).click( function () {
                on = !on;
                $(element).toggleClass('active', on);
            });
        }
    };
});

There are a few things wrong with this:

  1. First, jQuery was never necessary. There's nothing we did here that needed jQuery at all!

  2. Second, even if we already have jQuery on our page, there's no reason to use it here; we can simply use angular.element and our component will still work when dropped into a project that doesn't have jQuery.

  3. Third, even assuming jQuery was required for this directive to work, jqLite (angular.element) will always use jQuery if it was loaded! So we needn't use the $ - we can just use angular.element.

  4. Fourth, closely related to the third, is that jqLite elements needn't be wrapped in $ - the elementthat is passed to the link function would already be a jQuery element!

  5. And fifth, which we've mentioned in previous sections, why are we mixing template stuff into our logic?

This directive can be rewritten (even for very complicated cases!) much more simply like so:
.directive( 'myDirective', function () {
    return {
        scope: true,
        template: '<a class="btn" ng-class="{active: on}" ng-click="toggle()">Toggle me!</a>',
        link: function ( scope, element, attrs ) {
            scope.on = false;

            scope.toggle = function () {
                scope.on = !scope.on;
            };
        }
    };
});

Again, the template stuff is in the template, so you (or your users) can easily swap it out for one that meets any style necessary, and the logic never had to be touched. Reusability - boom!

And there are still all those other benefits, like testing - it's easy! No matter what's in the template, the directive's internal API is never touched, so refactoring is easy. You can change the template as much as you want without touching the directive. And no matter what you change, your tests still pass.

w00t!

So if directives aren't just collections of jQuery-like functions, what are they? Directives are actuallyextensions of HTML. If HTML doesn't do something you need it to do, you write a directive to do it for you, and then use it just as if it was part of HTML.

Put another way, if AngularJS doesn't do something out of the box, think how the team would accomplish it to fit right in with ngClick, ngClass, et al.

Summary


Don't even use jQuery. Don't even include it. It will hold you back. And when you come to a problem that you think you know how to solve in jQuery already, before you reach for the $, try to think about how to do it within the confines the AngularJS. If you don't know, ask! 19 times out of 20, the best way to do it doesn't need jQuery and to try to solve it with jQuery results in more work for you.

Wednesday, 13 April 2016

Understanding $watch(), $watchgroup() and $watchCollection() methods ofscope

Angular uses $watch APIs to observe model changes on the scope. Angular registered watchers for each variable on scope to observe the change in its value. If the value, of variable on scope is changed then the view gets updated automatically. $watch APIs has following methods to observe model changes on the scope.


$watch


This function is used to observe changes in a variable on the $scope. It accepts three parameters: expression, listener and equality object, where listener and equality object are optional parameters.

  1. $watch(watchExpression, listener, [objectEquality])

Here, watchExpression is the expression in the scope to watch. This expression is called on every $digest() and returns the value that is being watched.

The listener defines a function that is called when the value of the watchExpression changes to a new value. If the watchExpression is not changed then listener will not be called.

The objectEquality is a boolean type which is used for comparing the objects for equality using angular.equals instead of comparing for reference equality.


  1. scope.name = 'shailendra';

  2. scope.counter = 0;

  3.  

  4. scope.$watch('name', function (newVal, oldVal) {

  5. scope.counter = scope.counter + 1;

  6. });


$watchgroup


This function is introduced in Angular1.3. This works the same as $watch() function except that the first parameter is an array of expressions to watch.

  1. $watchGroup(watchExpression, listener)

The listener is passed as an array with the new and old values for the watched variables. The listener is called whenever any expression in the watchExpressions array changes.


  1. $scope.teamScore = 0;

  2. $scope.time = 0;

  3. $scope.$watchGroup(['teamScore', 'time'], function(newVal, oldVal) {

  4. if(newVal[0] > 20){

  5. $scope.matchStatus = 'win';

  6. }

  7. else if (newVal[1] > 60){

  8. $scope.matchStatus = 'times up';

  9. });


$watchCollection


This function is used to watch the properties of an object and fires whenever any of the properties change. It takes anobject as the first parameter and watches the properties of the object.

  1. $watchCollection(obj, listener)

The listener is called whenever anything within the obj has been changed.


  1. $scope.names = ['shailendra', 'deepak', 'mohit', 'kapil'];

  2. $scope.dataCount = 4;

  3.  

  4. $scope.$watchCollection('names', function (newVal, oldVal) {

  5. $scope.dataCount = newVal.length;

  6. });


What do you think?


I hope you will enjoy the watchers in AngularJS while developing your app with AngularJS. I would like to have feedback from my blog readers. Your valuable feedback, question, or comments about this article are always welcome.

Tuesday, 12 April 2016

Understanding ng-if, ng-switch and ng-repeat directives

AngularJS provides you ng-if, ng-switch directives to display HTML elements based on conditions or cases. ng-repeat directive is used to generate HTML from a collection of items.



ng-if


This directive can add / remove HTML elements from the DOM based on an expression. If the expression is true, it add HTML elements to DOM, otherwise HTML elements are removed from the DOM.


  1. ng-controller="MyCtrl">


  2. ng-if="data.isVisible">ng-if Visible

  3. </div>

  4.  


  5. var app = angular.module("app", []);

  6. app.controller("MyCtrl", function ($scope) {

  7. $scope.data = {};

  8. $scope.data.isVisible = true;

  9. });



ng-switch


This directive can add / remove HTML elements from the DOM conditionally based on scope expression.


  1. ng-controller="MyCtrl">


  2. ng-switch on="data.case">


  3. ng-switch-when="1">Shown when case is 1


  4. ng-switch-when="2">Shown when case is 2


  5. ng-switch-default>Shown when case is anything else than 1 and 2

  6. </div>

  7. </div>

  8.  


  9. var app = angular.module("app", []);

  10. app.controller("MyCtrl", function ($scope) {

  11. $scope.data = {};

  12. $scope.data.case = true;

  13. });



ng-repeat


This directive is used to iterate over a collection of items and generate HTML from it.


  1. ng-controller="MyCtrl">


  2. ng-repeat="name in names">

  3. {{ name }}



  4.  


  5. var app = angular.module("app", []);

  6. app.controller("MyCtrl", function ($scope) {

  7. $scope.names = ['Shailendra', 'Deepak', 'Kamal'];

  8. });



What do you think?


I hope you will enjoy the ng-if, ng-switch and ng-repeat directives in AngularJS while developing your app with AngularJS. I would like to have feedback from my blog readers. Your valuable feedback, question, or comments about this article are always welcome.

Understanding AngularJS Routing

Routing is a mechanism which helps you to divide your single page application into multiple views and bind these views to corresponding controllers. In this article, you will learn how to configure angular routing.

An angular route is specified within the URL by using # sign and enables you to show a specific view. Some example of angular routes are given below:

  1. http://yourdomain.com/index.html#users

  2. http://yourdomain.com/index.html#orders

  3. http://yourdomain.com/index.html#books

  4. http://yourdomain.com/index.html#games

AngularJS Route Module


The routing functionality is provided by the angular's ngRoute module, which is the part of angular-route.jsJavaScript file. Hence, include angular-route.js file into your AngularJS application for using routing. You have to add ngRoute module as an dependent module as given below:

  1. var app = angular.module("app", ['ngRoute']);

Configuring the $routeProvider


The routes in your angular application are declared with the help of $routeProvider which is the provider of the $route service. The $routeProvider is configured in your app module's config() function.

Syntax to configure Routing




  1. appmodule.config(['$routeProvider',

  2. function($routeProvider) {

  3. $routeProvider.

  4. when('/route1', {

  5. templateUrl: 'template-1.html',

  6. controller: 'RouteController1'

  7. }).

  8. when('/route2:param', {

  9. templateUrl: 'template-2.html',

  10. controller: 'RouteController2'

  11. }).

  12. otherwise({ // if no route paths matches

  13. redirectTo: '/'

  14. });

  15. }]);


  16.  

  17. <!-- And links should be defined as: -->

  18.  

  19. <a href="#/route1">Route 1</a><br/>

  20. <a href="#/route2:123">Route 2</a><br/>

The when() function takes a route path and a JavaScript object as parameters. The route path is matched against the part of the URL after the # sign. The otherwise() function redirects to the specified route if no route paths matches.

The ngView Directive


The ngView directive renders the template of the current route into the main layout (index.html) file. Every time, when the current route changes, the ngView directive view changes based on the new route path settings.


  1. ng-view>

An Example of Routing


index.html



  1. <!DOCTYPE html>

  2. <html>

  3. <head>

  4. <title>AngularJS Routing</title>

  5. src="lib/angular.js">

  6. src="lib/angular-route.js">

  7.  


  8. var app = angular.module("app", ['ngRoute']);

  9.  

  10. app.controller("homeController", function ($scope) {

  11.  

  12. $scope.message = "Welcome to Home Page!";

  13. });

  14.  

  15. app.controller("aboutController", function ($scope) {

  16.  

  17. $scope.message = "Welcome to About Page!";

  18. });

  19.  

  20. app.controller("contactController", function ($scope) {

  21.  

  22. $scope.message = "Welcome to Contact Page!";

  23. });


  24. app.config(['$routeProvider', function ($routeProvider) {

  25. $routeProvider.when("/", {

  26. templateUrl: "templates/pages/home.html",

  27. controller: "homeController"

  28. }).when("/about", {

  29. templateUrl: "templates/pages/about.html",

  30. controller: "aboutController"

  31. }).when("/contact", {

  32. templateUrl: "templates/pages/contact.html",

  33. controller: "contactController"

  34. }).otherwise({

  35. redirectTo: 'index.html'

  36. });

  37. }]);

  38.  


  39. </head>

  40. <body ng-app="app">


  41. href="#">Home |

  42. href="#contact">Contact |

  43. href="#about">About



  44. ng-view>

  45. </body>

  46. </html>

home.html



  1. <h1>Home Page</h1>

  2. <h2>{{message}}</h2>

about.html



  1. <h1>About Page</h1>

  2. <h2>{{message}}</h2>

contact.html



  1. <h1>Contact Page</h1>

  2. <h2>{{message}}</h2>

What do you think?

I hope you will enjoy the AngularJS Routing while developing your app with AngularJS. I would like to have feedback from my blog readers. Your valuable feedback, question, or comments about this article are always welcome.

Sunday, 3 April 2016

Understanding AngularJS Factory, Service and Provider

In AngularJS, services are reusable singleton objects that are used to organize and share code across your app. They can be injected into controllers, filters, directives. AngularJS provides you three ways : service, factory and provider to create a service.


Factory


A factory is a simple function which allows you to add some logic before creating the object. It returns the created object.

Syntax



  1. app.factory('serviceName',function(){ return serviceObj;})

Creating service using factory method




  1. //creating module

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

  3.  

  4. //define a factory using factory() function

  5. app.factory('MyFactory', function () {

  6.  

  7. var serviceObj = {};

  8. serviceObj.function1 = function () {

  9. //TO DO:

  10. };

  11.  

  12. serviceObj.function2 = function () {

  13. //TO DO:

  14. };

  15.  

  16. return serviceObj;

  17. });


When to use


It is just a collection of functions like a class. Hence, it can be instantiated in different controllers when you are using it with constructor function.

Service


A service is a constructor function which creates the object using new keyword. You can add properties and functions to a service object by using this keyword. Unlike factory, it doesn’t return anything.

Syntax



  1. app.service('serviceName',function(){})

Creating service using service method




  1. //creating module

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

  3.  

  4. //define a service using service() function

  5. app.service('MyService', function () {

  6. this.function1 = function () {

  7. //TO DO:

  8. };

  9.  

  10. this.function2 = function () {

  11. //TO DO:

  12. };

  13. });


When to use


It is a singleton object. Use it when you need to share a single object across the application. For example, authenticated user details.

Provider


A provider is used to create a configurable service object. It returns value by using $get() function.

Syntax



  1. //creating a service

  2. app.provider('serviceName',function(){});

  3.  

  4. //configuring the service

  5. app.config(function(serviceNameProvider){});

Creating service using provider method




  1. //define a provider using provider() function

  2. app.provider('configurableService', function () {

  3. var name = '';

  4. this.setName = function (newName) {

  5. name = newName;

  6. };

  7. this.$get = function () {

  8. return name;

  9. };

  10. });

  11.  

  12. //configuring provider using config() function

  13. app.config(function (configurableService) {

  14. configurableService.setName('www.dotnet-tricks.com');

  15. });


When to use


When you need to provide module-wise configuration for your service object before making it available.

AngularJS : Factory, Service and Provider with example



  1. <html>

  2. <head>

  3. <title>AngularJS Service Factory and Providers</title>

  4. src="lib/angular.js">

  5. </head>

  6. <body>


  7. class="container" style="padding-top:20px;">


  8. ng-app="myApp" ng-controller="myController">

  9.  From Service: {{serviceName}}

  10.  From Factory: {{factoryName}}

  11.  From Provider: {{providerName}}

  12.  </div>

  13. //defining module

  14. var app = angular.module('myApp', []); 

  15. //defining service

  16. app.service('myService', function () {

  17. this.name = '';

  18. this.setName = function (newName) {

  19. this.name = newName;

  20. return this.name;

  21. };

  22. });

  23.  

  24. //defining factory

  25. app.factory('myFactory', function () {

  26. var serviceObj = {};

  27. serviceObj.name = '';

  28. serviceObj.setName = function (newName) {

  29. serviceObj.name = newName;

  30. };

  31. return serviceObj;

  32. });

  33.  

  34. //defining provider

  35. app.provider('configurable', function () {

  36. var privateName = '';

  37. this.setName = function (newName) {

  38. privateName = newName;

  39. };

  40. this.$get = function () {

  41. return {

  42. name: privateName

  43. };

  44. };

  45. });

  46.  

  47. //configuring provider

  48. app.config(function (configurableProvider) {

  49. configurableProvider.setName("Saksham Chauhan");

  50. });

  51.  

  52. //defining controller

  53. app.controller('myController', function ($scope, myService, myFactory, configurable) {

  54. $scope.serviceName = myService.setName("Saksham Chauhan");

  55.  

  56. myFactory.setName("Saksham Chauhan");

  57. $scope.factoryName = myFactory.name;

  58.  

  59. $scope.providerName = configurable.name;

  60. });


  61. </body>

  62. </html>

jQuery Vs AngularJS

jQuery


jQuery is a lightweight and feature-rich JavaScript Library that helps web developers by simplifying the usage of client-side scripting for web applications using JavaScript. It extensively simplifies using JavaScript on a website and it’s lightweight as well as fast.

So, using jQuery, we can:

  • easily manipulate the contents of a webpage

  • apply styles to make UI more attractive

  • easy DOM traversal

  • effects and animation

  • simple to make AJAX calls and

  • utilities and much more… etc.

As mentioned earlier, jQuery is a JavaScript library, so we can use this library in our application partially/fully to fulfill a single or many of the features it provides (as listed above). For example, we can simply use jQuery library in our application to give some effects and animations or simply making AJAX-based calls or using all of the above listed features. It’s just like a plugin.

AngularJS


AngularJS is a product by none other the Search Engine Giant Google and it’s an open source MVC-based framework (considered to be the best and only next generation framework). AngularJS is a great tool for building highly rich client-side web applications.

As being a framework, it dictates us to follow some rules and a structured approach. It’s not just a JavaScript library but a framework that is perfectly designed (framework tools are designed to work together in a truly interconnected way).

In comparison of features jQuery Vs AngularJS, AngularJS simply offers more features:

  • Two-Way data binding

  • REST friendly

  • MVC-based Pattern

  • Deep Linking

  • Template

  • Form Validation

  • Dependency Injection

  • Localization

  • Full Testing Environment

  • Server Communication

When to Use jQuery or AngularJS?


Most of the time, people fail to comprehend the real value of these technologies during application development. AngularJS is best suited for the web application development as it works on the HTML code and JSON data which helps in developing for interactive and robust applications but using the same for a simple website development results in slow loading and quite erratic websites.

While jQuery is a fast and feature-rich language which has a a commendable JavaScript library and a great tool for creating feature-rich websites. It has in-built features such as HTML document traversal, event handling, manipulation, animation and Ajax support and others which make it easier and simpler to develop hardcore websites. Therefore before utilizing any of these highly intuitive and robust languages, it is necessary to frame a sound approach dedicated either to develop an advanced web application or website development.

Don’t Use AngularJS in jQuery Fashion


jquery enjoys a huge presence of plugins which makes it easier for the developer to plug these in the websites and let it do the remaining job. On the other hand, AngularJS possesses a completely different structure which makes it harder to find any plugins or to create one which can be simply placed on the website and left for good. AngularJS has jqLite which possess the jQuery functionalities and it can be used for developing different plugins as per the need of websites but stay away for developing or patching codes of old plugins and embedding it on the website.

Dependency injection in AngularJS

Dependency injection in AngularJS is supremely useful, and the key to making easily testable components. This article explains how Angular's dependency injection system works.

The Provider ($provide)


The $provide service is responsible for telling Angular how to create new injectable things; these things are called services. Services are defined by things called providers, which is what you're creating when you use $provide. Defining a provider is done via the provider method on the$provide service, and you can get hold of the $provide service by asking for it to be injected into an application's config function. An example might be something like this:

myMod.config(function($provide) {
  $provide.provider('greeting', function() {
    this.$get = function() {
      return function(name) {
        alert("Hello, " + name);
      };
    };
  });
});


Here we've defined a new provider for a service called greeting; we can inject a variable namedgreeting into any injectable function (like controllers, more on that later) and Angular will call the provider's $get function in order to return a new instance of the service. In this case, the thing that will be injected is a function that takes a name parameter and alerts a message based on the name. We might use it like this:

myMod.controller('MainController', function($scope, greeting) {
  $scope.onClick = function() {
    greeting('Ford Prefect');
  };
});


Now here's the trick. factory, service, and value are all just shortcuts to define various parts of a provider--that is, they provide a means of defining a provider without having to type all that stuff out. For example, you could write that exact same provider just like this:

myMod.config(function($provide) {
  $provide.factory('greeting', function() {
    return function(name) {
      alert("Hello, " + name);
    };
  });
});


It's important to understand, so I'll rephrase: under the hood, AngularJS is calling the exact same code that we wrote above (the $provide.provider version) for us. There is literally, 100% no difference in the two versions. value works just the same way--if whatever we would return from our $get function (aka our factory function) is always exactly the same, we can write even less code using value. For example, since we always return the same function for our greetingservice, we can use value to define it, too:

myMod.config(function($provide) {
  $provide.value('greeting', function(name) {
    alert("Hello, " + name);
  });
});


Again, this is 100% identical to the other two methods we've used to define this function--it's just a way to save some typing.

Now you probably noticed this annoying myMod.config(function($provide) { ... }) thing I've been using. Since defining new providers (via any of the given methods above) is so common, AngularJS exposes the $provide methods directly on the module object, to save even more typing:

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

myMod.provider("greeting", ...);
myMod.factory("greeting", ...);
myMod.service("greeting", ...);
myMod.value("greeting", ...);


These all do the same thing as the more verbose app.config(...) versions we used previously.

The one injectable I've skipped so far is constant. For now, it's easy enough to say that it works just like value. We'll see there's one difference later.

To review, all these pieces of code are doing the exact same thing:

myMod.provider('greeting', function() {
  this.$get = function() {
    return function(name) {
      alert("Hello, " + name);
    };
  };
});

myMod.factory('greeting', function() {
  return function(name) {
    alert("Hello, " + name);
  };
});

myMod.service('greeting', function() {
  return function(name) {
    alert("Hello, " + name);
  };
});

myMod.value('greeting', function(name) {
  alert("Hello, " + name);
});


The Injector ($injector)


The injector is responsible for actually creating instances of our services using the code we provided via $provide (no pun intended). Any time you write a function that takes injected arguments, you're seeing the injector at work. Each AngularJS application has a single $injectorthat gets created when the application first starts; you can get a hold of it by injecting $injectorinto any injectable function (yes, $injector knows how to inject itself!)

Once you have $injector, you can get an instance of a defined service by calling get on it with the name of the service. For example,

var greeting = $injector.get('greeting');
greeting('Ford Prefect');


The injector is also responsible for injecting services into functions; for example, you can magically inject services into any function you have using the injector's invoke method;

var myFunction = function(greeting) {
  greeting('Ford Prefect');
};
$injector.invoke(myFunction);


It's worth noting that the injector will only create an instance of a service once. It then caches whatever the provider returns by the service's name; the next time you ask for the service, you'll actually get the exact same object.

So, it stands to reason that you can inject services into any function that is called with$injector.invoke. This includes

  • controller definition functions

  • directive definition functions

  • filter definition functions

  • the $get methods of providers (aka the factory definition functions)

Since constants and values always return a static value, they are not invoked via the injector, and thus you cannot inject them with anything.

Configuring Providers


You may be wondering why anyone would bother to set up a full-fledged provider with the providemethod if factory, value, etc. are so much easier. The answer is that providers allow a lot of configuration. We've already mentioned that when you create a service via the provider (or any of the shortcuts Angular gives you), you create a new provider that defines how that service is constructed. What I didn't mention is that these providers can be injected into config sections of your application so you can interact with them!

First, Angular runs your application in two phases--the config and run phases. The configphase, as we've seen, is where you can set up any providers as necessary. This is also where directives, controllers, filters, and the like get set up. The run phase, as you might guess, is where Angular actually compiles your DOM and starts up your app.

You can add additional code to be run in these phases with the myMod.config and myMod.runfunctions--each take a function to run during that specific phase. As we saw in the first section, these functions are injectable--we injected the built-in $provide service in our very first code sample. However, what's worth noting is that during the config phase, only providers can be injected (with the exception of the services in the AUTO module--$provide and $injector).

For example, the following is not allowed:

myMod.config(function(greeting) {
  // WON'T WORK -- greeting is an *instance* of a service.
  // Only providers for services can be injected in config blocks.
});


What you do have access to are any providers for services you've made:

myMod.config(function(greetingProvider) {
  // a-ok!
});


There is one important exception: constants, since they cannot be changed, are allowed to be injected inside config blocks (this is how they differ from values). They are accessed by their name alone (no Provider suffix necessary).

Whenever you defined a provider for a service, that provider gets named serviceProvider, whereservice is the name of the service. Now we can use the power of providers to do some more complicated stuff!

myMod.provider('greeting', function() {
  var text = 'Hello, ';

  this.setText = function(value) {
    text = value;
  };

  this.$get = function() {
    return function(name) {
      alert(text + name);
    };
  };
});

myMod.config(function(greetingProvider) {
  greetingProvider.setText("Howdy there, ");
});

myMod.run(function(greeting) {
  greeting('Ford Prefect');
});


Now we have a function on our provider called setText that we can use to customize our alert; we can get access to this provider in a config block to call this method and customize the service. When we finally run our app, we can grab the greeting service, and try it out to see that our customization took effect.

Since this is a more complex example, here's a working demonstration:http://jsfiddle.net/BinaryMuse/9GjYg/

Controllers ($controller)


You can inject things into controllers, but you can't inject controllers into things. That's because controllers aren't created via the provider. Instead, there is a built-in Angular service called$controller that is responsible for setting up your controllers. When you callmyMod.controller(...), you're actually accessing this service's provider, just like in the last section.

For example, when you define a controller like this:

myMod.controller('MainController', function($scope) {
  // ...
});


What you're actually doing is this:

myMod.config(function($controllerProvider) {
  $controllerProvider.register('MainController', function($scope) {
    // ...
  });
});


Later, when Angular needs to create an instance of your controller, it uses the $controller service (which in turn uses the $injector to invoke your controller function so it gets its dependencies injected too).

Filters and Directives


filter and directive work exactly the same way as controller; filter uses a service called$filter and its provider $filterProvider, while directive uses a service called $compile and its provider $compileProvider. Some links:

As per the other examples, myMod.filter and myMod.directive are shortcuts to configuring these services.




Summary


So, to summarize, any function that gets called with $injector.invoke can be injected into. This includes, but is not limited to:

  • controller

  • directive

  • factory

  • filter

  • provider $get (when defining provider as an object)

  • provider function (when defining provider as a constructor function)

  • service

The provider creates new services that can be injected into things. This includes:

  • constant

  • factory

  • provider

  • service

  • value

That said, built-in services like $controller and $filter can be injected, and you can use those services to get hold of the new filters and controllers you defined with those methods (even though the things you defined aren't, by themselves, able to be injected into things).

Other than that, any injector-invoked function can be injected with any provider-provided service--there is no restriction (other than the config and run differences listed herein).

Adapted from this Stack Overflow answer