Angular.ITacademy.dk
on Service, promise, REST-API

Services

Angular services are substitutable objects that are wired together using dependency injection (DI). You can use services to organize and share code across your app.

docs.angularjs.org/guide/services

Angular services are:

  • Lazily instantiated – Angular only instantiates a service when an application component depends on it.

  • Singletons – Each component dependent on a service gets a reference to the single instance generated by the service factory.

See the Pen Simple-angularjs-service by Jalal Hejazi (@Jalalhejazi) on CodePen.

app.js demo

http://opgaver.itacademy.dk/app.js

notificationService

Define

OpgaverService

Define

Using

DataFactory 01

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


app.factory('GridDataFactory', ['$http', '$resource', function ($http, $resource) {  
    return function (type) {

        var REST = 'http://rest.supermobile.dk/' + type + '/:id' + '.json' ;

          return $resource( REST
                                , { id: '@id' }
                                , { 'GET':      { method: 'GET', isArray: false }      }
                                , { 'PUT':      { method: 'PUT' }     }
                                , { 'POST':     { method: 'POST' }    }
                                , { 'DELETE':   { method: 'DELETE' }  }

                          );

    };
}]);


app.directive('grid', function () {  
    return {
        restrict:   'A',
        replace:    false,
        scope:      true,
        templateUrl: 'grid-directive-template.html',
        controller: ['$scope', '$element', '$attrs', 'GridDataFactory','notificationFactory',
                function ($scope, $element, $attrs, GridDataFactory,notificationFactory) {
                    $scope.objects = [];
                    $scope.orderBy = { field: 'id', asc: true };
                    $scope.loading = true;

                $scope.getObject = function (cb) {
                    GridDataFactory($attrs.tableName).GET(function (data) {
                        $scope.objects = data.opgaver;
                        notificationFactory.info("GET $scope.objects.length = " +  $scope.objects.length );    
                        if (cb) cb();
                    });
                };

                 $scope.addObject = function () {
                    notificationFactory.info("$scope.addObject [POST] " );
                    GridDataFactory($attrs.tableName).POST($scope.object, successPostCallback, errorCallback);
                };

                $scope.deleteObject = function (object) {
                    notificationFactory.info("$scope.deleteObject {:" + object.id + "}" );
                    GridDataFactory($attrs.tableName).DELETE({ id: object.id }, successCallback, errorCallback);
                };

                $scope.updateObject = function (object) {
                   notificationFactory.info("$scope.updateObject [PUT] {:" + object.id + "}"); 
                   GridDataFactory($attrs.tableName).PUT({ id: object.id }, object, successCallback, errorCallback);
                };


                $scope.setOrderBy = function (field) {
                    var asc = $scope.orderBy.field === field ? !$scope.orderBy.asc : true;
                    $scope.orderBy = { field: field, asc: asc };
                }


                $scope.toggleAddMode = function () {
                    $scope.addMode = !$scope.addMode;
                };

                $scope.toggleEditMode = function (object) {
                    object.editMode = !object.editMode;
                };

                var successCallback = function (e, cb) {
                    notificationFactory.success();
                    $scope.getObject(cb);
                };

                var successPostCallback = function (e) {
                    successCallback(e, function () {
                        $scope.toggleAddMode();
                        $scope.object = {};
                    });
                };

                var errorCallback = function (e) {
                    notificationFactory.error(e.data.ExceptionMessage);
                };

                $scope.getObject(function () { $scope.loading = false; });
            }]
    }
});

DataFactory 02

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


/*
    http://fdietz.github.io/recipes-with-angular-js/consuming-external-services/consuming-restful-apis.html

    Following some conventions simplifies our code quite a bit. 
    We define the $resource by passing the URL schema only. 
    This gives us a handful of nice methods including 


    query       --> ({params}, successCB, errorCB) 
    get         --> ({params}, successCB, errorCB)
        save    --> ({params}, post_data ,successCB, errorCB)
    remove 
    delete

    By default, all resource actions expect objects, 
                except query which expects arrays.

    example: 
    https://github.com/fdietz/recipes-with-angular-js-examples/blob/master/chapter5/recipe2/public/js/controllers.js


    ELSE-USE: https://github.com/mgonto/restangular    
*/

app.factory('OpgaverService', ['$http', '$resource', function ($http, $resource) {  
    return function () {
        return $resource( 'http://rest.supermobile.dk/opgaver/:action/:data/:id');
    };
}]);



app.factory('notificationFactory', function () {  
    return {
        success: function () {
            toastr.success("Success");
        },
        error: function (text) {
            toastr.error(text, "Error");
        },
        info: function (text) {
            toastr.info(text, "Information");
        }

    };
});

app.directive('opgaver', function () {  
    return {
        restrict:   'AE',
        replace:    false,
        scope:      true,
        templateUrl: 'opgaver-template.html',
        controller: ['$scope', '$element', '$attrs', 'OpgaverService','notificationFactory',
                function ($scope, $element, $attrs, OpgaverService,notificationFactory) {



                    $scope.objects = [];
                    $scope.orderBy = { field: 'id', asc: true };
                    $scope.loading = true;



                $scope.getObject = function (cb) {

                    OpgaverService()
                        .get(function (data) {
                                    $scope.objects = data.opgaver;
                                    $scope.antal   = data.opgaver.length;
                                    //notificationFactory.info("get $scope.antal = " +  $scope.antal );    
                                    if (cb) cb();
                            });
                };




                $scope.resetObject = function () {

                    var params = {action:'delete', data:'reset'};    

                    OpgaverService().query(params, function(){
                        notificationFactory.info("$scope.resetObject <br> clean the service "  );
                        $scope.getObject();

                    });


                };   





                 $scope.addObject = function () {
                    // /opgaver/post/:data
                    var params = {action:'post', data: $scope.object.todo};    

                    OpgaverService().query(params, function(data){
                        notificationFactory.info("$scope.addObject [POST] <br> " + $scope.object.todo );
                            $scope.toggleAddMode();
                            $scope.getObject();
                    });
                };




                $scope.deleteObject = function (object) {

                    // /opgaver/delete/:id
                    var params = {action:'delete', id: object.id};    

                    //OpgaverService().get(params);
                    OpgaverService().query(params, function(data){
                            notificationFactory.info("$scope.deleteObject {:" + object.id + "}" );
                            $scope.getObject();
                        });
                };




                $scope.updateObject = function (object) {
                   notificationFactory.info("$scope.updateObject [PUT] {:" + object.id + "}"); 

                   OpgaverService().PUT({ id: object.id }, object, successCallback, errorCallback);
                };


                $scope.setOrderBy = function (field) {
                    var asc = $scope.orderBy.field === field ? !$scope.orderBy.asc : true;
                    $scope.orderBy = { field: field, asc: asc };
                }


                $scope.toggleAddMode = function () {
                    $scope.addMode = !$scope.addMode;
                };

                $scope.toggleEditMode = function (object) {
                    object.editMode = !object.editMode;
                };


                var successPostCallback = function (e) {
                    successCallback(e, function () {
                        $scope.toggleAddMode();
                        $scope.object = {};
                    });
                };

                var errorCallback = function (e) {
                    notificationFactory.error(e.data.ExceptionMessage);
                     $scope.getObject();

                };

                $scope.getObject(function () { $scope.loading = false; });
            }]
    }
});

DataFactory 03

/*=======================================================
            Implemented by Jalal Hejazi 2015
            To learn how angular CRUD works using SPA
            The backend is using RESTfull Service

            http://rest.supermobile.dk/opgaver/
            http://rest.supermobile.dk/opgaver/:id
            http://rest.supermobile.dk/opgaver/:action
=========================================================*/


/*=======================================
=            Single Page APP            =
=======================================*/

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





/*=====================================================
=            Define global level constants            =
=====================================================*/

app.constant('base_url', 'http://rest.supermobile.dk/opgaver');




/*============================================================================
    Interceptors like a filter to http response
    I use it here to filter out only the top 10 rows. 
    Can also be used to remove any unwanted or bad data from the response !!
    Normally interceptor is used to check for authentication 

=============================================================================*/

app.config(function($httpProvider, $provide, base_url) {  
  $provide.factory('select_top', function() {
    return {
      response: function(config) {
        if( config.config.url === base_url) {
            config.data.opgaver.splice(100); // only return TOP(100) from 100%
        }
        return config;
      }
    }
  });


  $httpProvider.interceptors.push('select_top');
});


/*======================================================
=            OpgaverService-Factory pattern            =
======================================================*/


/*
    query       --> ({params}, successCB, errorCB) 
    get         --> ({params}, successCB, errorCB)
        save    --> ({params}, post_data ,successCB, errorCB)
    remove 
    delete

    By default, all resource actions expect objects, 
                except query which expects arrays.
*/

app.factory('OpgaverService', ['$http', '$resource','base_url', function ($http, $resource,base_url) {  
    return function () {
        return $resource(  base_url + '/:action/:data/:id',{},
                            { 'PUT':      { method: 'PUT' , isArray: true}     }
                        );
    };
}]);









/*====================================================
=            notification Factory pattern            =
====================================================*/


app.factory('notificationFactory', function () {  
    return {
        success: function () {
            toastr.success("Success");
        },
        error: function (text) {
            toastr.error(text, "Error");
        },
        info: function (text) {
            toastr.info(text, "Information");
        }

    };
});




/*=======================================================================
            directive to take care of CRUD in VM of 'MVVM'  
            in angular the vm is the $scope          
            as element: <opgaver> or as attribute: <div opgaver="">
            Binding between the View and the Model
            The View is the templateUrl: 'opgaver-template.html'
            The View needs data from OpgaverService-business-logic

========================================================================*/



app.directive('opgaver', function () {  
    return {
        restrict:   'AE',
        replace:    false,
        scope:      true,
        templateUrl: 'opgaver-template.html',
        controller: ['$scope', '$element', '$attrs', 'OpgaverService','notificationFactory',
                function ($scope, $element, $attrs, OpgaverService,notificationFactory) {

                    var vm = $scope ;    
                    vm.objects = [];
                    vm.orderBy = { field: 'id', asc: true };
                    vm.loading = true;


                //GET data using HTTP get and using promise    
                vm.getObject = function (cb) {

                        vm.antal_done = 0;
                        vm.antal_todo = 0;

                          OpgaverService()
                          //.get({userName:'jh',userToken:'secret'}) // ?parameters
                          .get()  

                          .$promise   // using $promise from $http

                          .then(function(success){
                                vm.objects =  success.opgaver;
                                vm.antal   =  success.opgaver.length;

                                angular.forEach(success.opgaver, function(opg){
                                     if (opg.done) {
                                        vm.antal_done += 1;
                                     }else{
                                        vm.antal_todo += 1;
                                     }

                                });

                            })

                          .finally(function(){
                                if (cb) cb();
                          })


                };


                 // CREATE using action post  
                 vm.addObject = function () {
                    // /opgaver/post/:data
                    var params = {action:'post', data: vm.object.todo};    
                    OpgaverService().query(params,successPostCallback,errorCallback) ;

                };

                // DELETE using action delete
                vm.deleteObject = function (object) {
                    // /opgaver/delete/:id
                    var params = {action:'delete', id: object.id};    
                    OpgaverService().query(params, successCallback,errorCallback);
                };

                //UPDATE using HTTP PUT
                vm.updateObject = function (object) {
                    OpgaverService().PUT({ id: object.id }, object, successCallback,errorCallback);
                };


                // RESET using action delete and reset the service with default 
                vm.resetObject = function () {
                    var params = {action:'delete', data:'reset'};    

                    OpgaverService().query(params, function(){
                        notificationFactory.info("vm.resetObject <br> clean the service "  );
                        vm.getObject();

                    });


                };   



                vm.setOrderBy = function (field) {
                    var asc = vm.orderBy.field === field ? !vm.orderBy.asc : true;
                    vm.orderBy = { field: field, asc: asc };
                }

                vm.toggleAddMode = function () {
                    vm.addMode = !vm.addMode;
                };

                vm.toggleEditMode = function (object) {
                    object.editMode = !object.editMode;
                };

                var successCallback = function (e, cb) {
                    // notificationFactory.success();
                    vm.getObject(cb);
                };

                var successPostCallback = function (e) {
                    successCallback(e, function () {
                        vm.toggleAddMode();
                        vm.object = {};
                    });
                };

                var errorCallback = function (e) {
                    notificationFactory.error(e.data.ExceptionMessage);
                };


                vm.getObject(function () { 
                    vm.loading = false; 
                    notificationFactory.info('OpgaverService loaded !');

                });
            }]
    }
});