Google+

Thursday, September 10, 2015

#11 - How to create your own Custom AngularJS $service

In this article we review how to create your own Custom AngularJS $service,  by developing an Angular App that includes two Views and two Controllers, and share some Model variables by using a  Custom AngularJS $service  .
This is the Lesson #11 in the "AngularJS: From 0 To 100" learning articles written for AngularJS  Beginners. This lessons start at Lesson #1  , if you wish to take a look at them.
<<<<  PREVIOUS LESSON                      NEXT LESSON >>>>


We're using the  "Brackets"  open source Editor , which supports AngularJS Apps . You can see the 5 minutes tutorial about Brackets in this post.

Our AngularJS App will be shown this way :

How to create your own Custom AngularJS $service



How to create your own Custom AngularJS $service



First of all, let's declare our Angular App by referencing the AngularJS framework and Module:

How to create your own Custom AngularJS $service    1



Then we add the bind to an "external" Controller, which just toggle the two Views using the data-ng-switch-when directive : a View representing the list of Music Albums and a web form setting the selected one, and a View showing the chosen Music Album item after the selection:

How to create your own Custom AngularJS $service    2



(copy-paste):

<body data-ng-controller="SwitcherCtl as TabsCtl">    <div data-ng-switch on="TabsCtl.View">    <div data-ng-switch-when="WebFormView"></div><div id="controls"  data-ng-switch-when="SelectedItemView"></div></div></body></html>


Then add the corresponding Controller at the javascript Controllers file:

How to create your own Custom AngularJS $service   3



This javascript just takes care of toggling the two Views according to the user's clicks.

(copy-paste):

angular.module('MusicApp', [])
.controller('SwitcherCtl', [function() {
     
    this.View = 'WebFormView';
    this.open = function(tab) {
        this.View = tab;
    };
}])



Then we add at the first View the code to show the Album's list, and to input the selected Album's user's choice, as we saw at the Lesson #9 :

How to create your own Custom AngularJS $service     4



(copy-paste):  go to  the Lesson #9 .

Take care to add to the former HTML5 from Lesson #9, the following code to be performed when the "Send" submit button is clicked:

How to create your own Custom AngularJS $service     5

Also, append a second Controller to the javascript file, to be bound to the "WebFormView" :

.controller('MusicController', [ '$scope', function ($scope) {
           
            var albums = 
            [
                {id:111,img:"Nocturnal.jpg",name:"Nocturnal Beats",price:"12.50"},
                {id:112,img:"Facts.jpg",name:"The Facts And The Dreams",price:"11.20"},
                {id:113,img:"Voices.jpg",name:"Voices From The Dust Bowl",price:"13.70"},
                {id:114,img:"Pretz.jpg",name:"Soundcastles",price:"14.80"}
            ]
            $scope.albums = albums;
                                 
             
            $scope.submitForm = function() {
                
                
                
            };
}])


Inside the first View, append a button to go to the second View ("SelectedItemView"):

How to create your own Custom AngularJS $service     6

We just send the View's name to where we want to go, as an argument for the Controller's method open() : 
How to create your own Custom AngularJS $service    7



Next, create the second AngularJS View "SelectedItemView" , bound to a "SelectedItemCtl", as follows:

How to create your own Custom AngularJS $service    8

(copy-paste):

<div id="controls"  data-ng-switch-when="SelectedItemView">
    <div class="centered" data-ng-controller="SelectedItemCtl">
        <div class="centered"> 
            <h1>Fragile State Discography</h1>     
            <h2>Selected Music Album</h2>  
        </div>
         
        <table>
            <tr><td>Client Email   : </td><td><input data-ng-model="order.Email" /> </td></tr>        
            <tr><td>Item's Quantity: </td><td><input data-ng-model="order.Quantity" /> </td></tr>
            <tr><td>Item's ID      : </td><td><input data-ng-model="order.album.id" /> </td></tr>
         </table>
        <button data-ng-click="TabsCtl.open('WebFormView')">See Music Album's List</button>
    </div>
</div>

Notice that we have a button to go back to the selection web form.

Append the third Controller to the javascript file as follows:

How to create your own Custom AngularJS $service     9



Now run the AngularJS App to see if everything works, before going on:

How to create your own Custom AngularJS $service    10



Enter some input data, and click the "Send" button :

How to create your own Custom AngularJS $service    11



The user is redirected to the second AngularJS View, but it's empty:

How to create your own Custom AngularJS $service    12

Why is it empty? Because in AngularJS, the Controllers use different $scope s : they don't share state!
For example, the "order" Model belongs ONLY to the "SelectedItemCtl" Controller, and not to other Controllers:

How to create your own Custom AngularJS $service    13

To solve the problem, and share the "order" variable state between the two Controllers, we will define a custom "SharingService"  $service, and inject it in the two Controllers using Dependency Injection.
So, append an AngularJS Factory to create the custom $service, containing just two methods : get() and set(). These methods will get and set the shared "Order" variable, as follows:

How to create your own Custom AngularJS $service   14

Notice that we also used Dependency Injection to insert the custom AngularJS Service inside the two Controller's constructors. 
In AngularJS, Factories just create the single object which represents a $service to the rest of the AngularJS application, and can be inserted in the constructors of every other Service.
You can read more about AngularJS Factories at the official AngularJS web site.

(copy-paste):

.controller('MusicController', [ '$scope', 'SharingService', function ($scope,SharingService) {
           
            var albums = 
            [
                {id:111,img:"Nocturnal.jpg",name:"Nocturnal Beats",price:"12.50"},
                {id:112,img:"Facts.jpg",name:"The Facts And The Dreams",price:"11.20"},
                {id:113,img:"Voices.jpg",name:"Voices From The Dust Bowl",price:"13.70"},
                {id:114,img:"Pretz.jpg",name:"Soundcastles",price:"14.80"}
            ]
            $scope.albums = albums;
                                 
             
            $scope.submitForm = function() {
                
                SharingService.set($scope.order); 
                
            };
}])
.controller('SelectedItemCtl', ['$scope', 'SharingService','$log', function($scope,SharingService,$log) {
    
    $scope.order = SharingService.get(); 
    $log.info($scope.order);
    
}])
.factory('SharingService', [function() {
    
    var oSelectedItem;
    return {
        get: function() {
            return oSelectedItem;
        },
        set: function(item) {
           oSelectedItem = item;
        }
    };
}]);

Note that we also injected the $log $service in order to output some info to the Console, as we saw at the previous Lesson #10.
Again, enter some data in the web form, and click "Send":

How to create your own Custom AngularJS $service    15



This time, the data has been read at the second Controller:

How to create your own Custom AngularJS $service    16



We added the $log service as follows, to see the "Order" object in the Console:

How to create your own Custom AngularJS $service   17



(copy-paste):

.controller('SelectedItemCtl', ['$scope', 'SharingService','$log', function($scope,SharingService,$log) {
    
    $scope.order = SharingService.get(); 
    $log.info($scope.order);
    
}])


Now if you send again the selected item, you could see the "Order" JSON object :


How to create your own Custom AngularJS $service   18


As you see, "Order" includes several properties like "Email", "Quantity" , and "Album". This later includes an "ID" property with the identity of the Music album selected. The state has been shared when passing from one AngularJS View and Controller , to the other.


That's All!!! You have begun using custom AngularJS Services with Dependency Injection in AngularJS , in order to share state between Controllers . In the next article we will continue to learn Step by Step how to make HTTP GET requests to an OData RESTful web service , using the $http AngularJS service
If you liked the CSS3 style, here you have the code to copy:

 div[id^=controls]{padding:5px 5px 5px 25px;margin:10px 15px 15px 25px;font:900 12px Comic Sans MS;opacity:0.9;background:#fed;    border:10px solid #ddd;    border-radius: 10px;box-shadow:10px 10px 2px #c0c0c0;}button,input[type=submit] {padding:5px 5px 5px 5px;margin:10px 15px 15px 15px;width:220px;text-align: center;background:#ddd; font:900 14px Comic Sans MS;opacity:0.9;border:1px solid #c0c0c0;    border-radius: 10px;box-shadow:10px 10px 2px #c0c0c0;}ul{list-style:none;    }input {padding:5px 5px 5px 5px;margin:10px 15px 15px 15px;width:150px;text-align: center;background:#fea; font:900 12px Comic Sans MS;opacity:0.9;border:7px solid #ddd;    border-radius: 10px;box-shadow:10px 10px 2px #c0c0c0;}select{padding:5px 5px 5px 5px;margin:10px 15px 15px 15px;width:250px;text-align: center;background:#fea; font:900 12px Comic Sans MS;opacity:0.9;border:1px solid #fe9;    border-radius: 10px;box-shadow:10px 10px 2px #c0c0c0;}div.centered{ text-align:center   }.errorMessage{ color:red;   }}


<<<<  PREVIOUS LESSON                     NEXT LESSON >>>>

Enjoy AngularJS.....

      by Carmel Schvartzman


כתב: כרמל שוורצמן