OOP Inheritance for AngularJS

First, the caveat – I’ve just gotten this example to work. I will try using it in some larger code shortly, but I thought I’d document while everything seemed clear.

I’ve been working with Angular for a few months now, and am now doing reasonably complex things. As someone who has been coding for way too long, I like some of the things that Object Oriented programming gives you that Angular does not support (at least in a straightforward way). Primary among this is inheritance. I ran into this problem when I needed to make two mostly similar web pages that really didn’t lend themselves to multiple services/factories but could have been very cleanly built by extending a base class.

In Java/C++/Actionscript, etc, you have the capability to build base classes that can be extended. An example is setting up a particle base class that is extended to a moving particle class inherits from (Using Java here):

public class Particle{
    private vec3 position;
    public function setPosition(vec3 p){
        // code...
    }
    public function draw(){
        // code...
   }
}

To make the particle move, we need to add some kind of velocity and an update function that increments the position as a function of the velocity and time.

public class MovingParticle extends Particle{
    private vec3 velocity;
    public function setVelocity(vec3 p){
        // code...
    }
    public function update(double elapsed){
        // code...
   }
}

JavaScript has nothing like this and neither does Angular. YUI did, but that’s not supported any more. But through some contortions, JavaScript can handle inheritance. A pattern that I like is Parasitic Combination Inheritance, which I learned about in Professional JavaScript for Web Developers. I combined that with the Revealing Module Pattern, to get inheritance to work in a clean way. A fully working version of the code below is up at plunker. Some sections of the code below have been stripped out for clarity.

First, the base class:

var baseLogic = (function(window, undefined) {
    function ParentFn(globalsService) {
        this.myText = "Hello, World";
        this.myText2 = globalsService.getHello();
    }

    ParentFn.prototype.makeAlert = function() {
        alert(this.myText2);
    };

    return {
        parentPtr: ParentFn
    }
})(window);

Note that the baseLogic object is a function expression where the only accessible attribute is parentPtr, which points to the hidden function declaration ParentFn.

The child class uses a similar pattern. I pass in the baseLogic object just to keep things cleaner. Additionally, I pass in a globals object (created just like baseLogic) that contains a function that handles the mechanics of Parasitic Combination Inheritance.

var myLogic = (function(window, base, gbl, undefined) {
    //function ChildFn(){
    function ChildFn(globalsService) {
        var self = this;
        base.parentPtr.call(self, globalsService);
        self.myText = "Hello, World2";
        self.instanceAlert = function() {
            alert("instanceAlert = " + self.myText);
        }
    }

    gbl.inheritPrototype(ChildFn, base.parentPtr);

    ChildFn.prototype.makeAlert2 = function() {
        alert("ChildFn.prototype.makeAlert2");
    };

    return {
        childPtr: ChildFn,
    }

})(window, baseLogic, globals);

These can then be incorporated in Angular pretty trivially. The globalsService that is an argument in both the parent and child objects is created in the same way:

(function(angular, ml, undefined) {
    angular.module('globalsApp', [])
            .factory('GlobalsService', [ml.factoryPtr]);

    angular.module('inheritApp', ['globalsApp'])
            .controller('MainCtrl', ['GlobalsService', ml.childPtr]);
})(angular, myLogic);

The nice thing about this approach is that any component (controller, link functions in directives, factory, service) can all be built using OO techniques this way.

Here’s hoping it works on something more than my toy example

So here we are, several days later. Everything works like I hoped. Now all the angular code for a module is in one place, which looks nice and readable (example). And although it’s kind of messy (programming for school, rather than work), here’s the base class and the derived class that is used in the

.controller('MainCtrl', ['$http', '$timeout', '$document', 'PostService', postControllers.turkPostPtr])

call in the above example.

Woohoo!

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s