OOooo… TypeScript Classes with AngularJS

Let’s add TypeScript to the mix. I like typing – basically because I hate making unforced errors. I like interfaces for the same reason – they allow defining complex types before they get used.

I’ve known about TypeScript for a while, but I wasn’t good enough with JavaScript to really understand what it was doing. It just didn’t seem like a good idea to add yet another abstraction to the already shaky tower of JavaScript, Angular and threeJS.

But now I’ve been working with some reasonably complex JavaScript and have enough comprehension to understand the conversions that TypeScript makes. I might even be consciously competent:

TypeScript has been used with Angular before, and it’s also part of the plan for Angular 2.0. Sean Hess has a nice angular with typescript video. The key points are really around 15:00 in, where the controllers and factories are built. His github repository for the demo code is here. It was great to see that TypeScript and Angular can be combined, but I really wanted something as simple as possible, so I got a copy of TypeScript Essentials and started with the basics.

With that in mind, I’ve tried to make a very simple TypeScript class and incorporate it into the angular framework using a second TypeScript class. In the interest of maximum simplicity, there are only classes and typing – no interfaces (other than the ones from definitely typed) and no modules. No inheritance either. All these will be in a later post.

So, without any more introduction, here are the results:

  • First, plain old angular HTML:
<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title></title>
</head>
<body ng-app="simpleApp">
<div ng-controller="MainCtrl as mc">
    <p>String = {{mc.myString}}</p>
</div>

<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.10/angular.min.js"></script>
<script src="simple.js"></script>

</body>
</html>
  • Next, the TypeScript (simple.ts):
/// <reference path="../definitelytyped/angularjs/angular.d.ts" />

class TestClass{
   myString:string;

   constructor(){
      this.myString = "Hello, TypeScript4";
   }
}

class AngularMain{
   myModule:ng.IModule;
   myController:ng.IModule;
   public doCreate(angular:ng.IAngularStatic, sfn:Function){
      this.myModule = angular.module('simpleApp', []);
      this.myController = this.myModule.controller('MainCtrl', [sfn]);
   }
}

new AngularMain().doCreate(angular, TestClass);
  • Last, the generated JavaScript code (simple.js):
/// <reference path="../definitelytyped/angularjs/angular.d.ts" />
var TestClass = (function () {
    function TestClass() {
        this.myString = "Hello, TypeScript4";
    }
    return TestClass;
})();
var AngularMain = (function () {
    function AngularMain() {
    }
    AngularMain.prototype.doCreate = function (angular, sfn) {
        this.myModule = angular.module('simpleApp', []);
        this.myController = this.myModule.controller('MainCtrl', [sfn]);
    };
    return AngularMain;
})();
new AngularMain().doCreate(angular, TestClass);
//# sourceMappingURL=simple.js.map

I’ve put a running example up here.

Happy coding!

Advertisements

OO inheritance for AngularJS factories

AngularJS  services and factories require a return object. As such, the parasitic combination inheritance calls mentioned in the previous post need to be changed a bit so that the return object from the call to the parent class is stored so that it can be returned from the child class in a way that Angular likes. Here’s what it looks like when using my ‘utility’ inheritance tools:

function QueryServiceFn2($http){
   var retObj = QueryServiceFn.call(this, $http);
   globalU.inheritPrototype(this, QueryServiceFn);
   return retObj;
}

So that works just fine. Closure also works the way that I think it should – methods referenced in the parent class have visibility to the ‘hidden’ parent objects. Here’s full example of inheriting a factory object (full version here – the child class is at the bottom of the file):

globalUtils.appMap.phpFactories2 = (function(globalU, base){
   "use strict";
   function QueryServiceFn($http){
      var retObj = base.call(this, $http);
      globalU.inheritPrototype(this, base);
      return retObj;
   }

   return{
      queryServicePtr: QueryServiceFn
   };
})(globalUtils, globalUtils.appMap.phpFactories.queryServicePtr);

To override a function, simply declare it normally and then set the pointer in retObj to point at the new version. The only thing to watch out for is that closure won’t hold. If you need access to an item in the base class that’s accessed through closure, you’ll probably have to copy it.

OOPs! Inheritance for AngularJS redux…

So it turned out that what I thought was parasitic combination inheritance was just parasitic. The globalUtils.inheritPrototype() function was being called before the function/objects were being called, thus inheriting nothing.. I think that this is because Angular is calling the functions after the other JavaScript is called. Since (I think!) the code has to be structured in this decoupled way to allow flexible use of OO, I had to look again at how all the pieces fit together. It turns out that a properly configured function object that inherits from a base class looks like this:

function ChildFn3(globalService) {
    console.log("Start ChildFn3");
    ChildFn2.call(this, globalService);
    globalU.inheritPrototype(this, ChildFn2);
    console.log("Finish ChildFn3");
}

we can adjust inherited values such as arrays without ‘static’ behaviors as well:

function ChildFn4(globalService) {
    console.log("Start ChildFn4");
    ChildFn2.call(this, globalService);
    globalU.inheritPrototype(this, ChildFn2);
    this.colors.push('black');
    console.log("Finish ChildFn4");
}

Here’s the better, running example: http://philfeldman.com/inheritance/inherit3.html

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!