Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Extending a base class in an Angular service

I have a base class that I would like to extend in a service to help get data in to the angular scope. I have searched around the net for a solution, but have not found one that I like. I have a base class that is used to access the File systems of devices

the class structure:

var cOfflineStorageBase = Class.extend({
   init: function(){
   },
   CreateFolderDir: function(){
   },
   DeleteAll: function(){
   },
   DeleteDirectories: function(){
   },
   DeleteItem: function(){
   },
   GetFiles: function(){
   },
   FileExists: function(){
   }, 
   GetPath: function(){
   },
   GetObject: function(){
   },
   SaveObject: function(){
   },   
});

I would like to be able to extend this class in several different angular services (ie offlineCart, offlineCustomLists, ect...) where each service would be able to use the storage base to store the various different data types. I am looking for the best, most appropriate way to do this in angular. In vanilla JavaScript one would just do something like this:

var newClass = cOfflineStorageBase.extend({
   //add new stuff here
});

but I want to do this same thing the angular way.

The approach I have been considering are to use the angular.extend functionality, but I am not sure this is appropriate or would something like this be a more appropriate approach:

app.factory('someChild', ['$http' , 'cOfflineStorageBase', 
            function($http, cOfflineStorageBase){
  var SomeClass = cOfflineStorageBase.extend({
     init: function(){
        this._super.init()
     },
     //Add more stuff here
  });
  return SomeClass;
}]);

I would like some advice if theses approaches are correct or if there might be another that is better for what I am wanting to accomplish. I would also like or rather need to use promises in much of this code as it would be async.

like image 676
Jared Reeves Avatar asked May 23 '14 20:05

Jared Reeves


2 Answers

I pulled off this trick recently.

I will start by defining a plain JavaScript constructor. This does not need to be an angular service. What I do is that, later, the extending constructors can pass any necessary injections by parameter. So, this will be the base "class" of my angular services. This is where I would expose anything I want all angular services to inherit.

function ParentService($http) {
   this.$http = $http;
}

ParentService.prototype.foo = function () {
    alert("Hello World");
};

Then I will proceed to define a child constructor using prototypal inheritance. This constructor will indeed be an angular service (you can tell by my use of $inject at the end).

function ChildService($http) {
    Parent.call(this, $http);
}

ChildService.prototype = new ParentService();
ChildService.prototype.baz = function() {
   return this.$http.get('/sample/rest/call');
}
ChildService.$inject = ['$http'];

Then I will proceed to register the services à la carte in the corresponding angular modules:

var app = angular.module('SampleApp', []);
app.service('child', ChildService);

Finally, in my controller I will simply inject my service, which will be an instance of my ChildService constructor, which in turn extends my ParentService constructor:

app.controller('MainCtrl', ['$scope', 'child', function ($scope, child) {
    child.foo(); //alert("Hello World")
    var promise = child.bar();
}]);

You can see a JSFiddle here

Also there is an interesting video in Youtube from ngConf called Writing A Massive Angular App which covers some of these topics and a few other ideas on code reusability with angular.

like image 173
Edwin Dalorzo Avatar answered Sep 28 '22 01:09

Edwin Dalorzo


This question was asked, and answered, 18 months ago. I recently went through the same issue on a project. I wanted to have a base Model defined that I could use to build factories off of. Angular has a very simple Provider to assist with this called the Value Provider, which Angular implements using the Value Recipe.

I'm not sure what version of Angular you may have been using at the time, but this dates back (AFAIK) to version 1.3.0. (As of this writing, current stable is 1.4.8)

I'm also using John Resig's Simple Inheritance Script. http://ejohn.org/blog/simple-javascript-inheritance/

Here's a snippet of my code (with most of the application specific logic removed).

var MyApp = angular.module( 'MyApp',['ngResource','ngAnimate','ngSanitize'] );

/* ==================================================================================== */
// -   Base Model Class   -------------------------------------------------------------
/* ==================================================================================== */

MyApp

/**
 * BaseModel - Value Provider
 * 
 */
.value( 'BaseModel',Class.extend({

    attribs: {},

    init: function(){

        var self = this;

        _active = true;

        _new = true;

        _origs = {};

        _loadByObject = function( obj ){ ... }
    },

    get: function( key ){ ... },
    set: function( key,val ){ ... },

    isNew: function(){ ... },
    keep: function(){ ... },
    remove: function(){ ... },

    load: function( obj ){ ... }
    verify: function(){ ... },      
    save: function(){ ... },

}))

.factory( 'UserFactory', 
    [ '$http', '$q', 'BaseModel', 
    function( $http, $q, BaseModel ){

    var UserFactory = BaseModel.extend({

        init: function(){

            this._super( false );

            _fields = [
                'first', 'last', 'email', 
                'phone', 'password', 'role'
            ];

            _permitted = [
                'first', 'last', 'email', 
                'phone', 'password', 'role'
            ];

            _required = [
                'first', 'last', 'email', 'role'
            ];

            _resource = "users";

            _api = "users";

        }

    });

    return UserFactory;

}])

I'd love to hear anyone's feedback, too.

Here's the Angular Docs: https://code.angularjs.org/1.3.0/docs/guide/providers

like image 26
user2977468 Avatar answered Sep 28 '22 02:09

user2977468