AngularJS + TypeScript Tip - Controller ViewModel

In my previous post on getting started with AngularJS and TypeScript, I went over some of the gotchas that took me awhile to work through such as minification and scope inheritance. Today I want to look at a tip to help ease the pain you might encounter when trying to use TypeScript with Angular and how to structure your controllers.

You’ve Got Me. Who’s Got You?

In the current version of AngularJS (1.0.7), the $scope is the magic that binds everything together and controllers are where you do most of the work. If you’re like me, because all the AngularJS examples do so, your first instinct is to declare all the necessary functions and such on your $scope. But in TypeScript, this means your constructor is full of ugliness:
class MyController {

constructor($scope) {
    $scope.myVariable = "hello";
    $scope.myFunction = () => {
        window.alert($scope.myVariable);
    };
}

}

See how I instantiated some junk off the $scope, but it’s all done in the constructor? Nasty. Let’s do this instead:
class MyController {

myVariable: string = "hello";

constructor($scope) {
    $scope.viewModel = this;
}

myFunction() {
    window.alert(this.myVariable);
}

}

Now, we’re able to define everything on our controller and reuse it through the viewModel property we defined on our $scope. This may make the concept easier for MVVM developers to grok.

This also gets us the automatic benefit of maintaining the scope inheritance that comes with having primitives directly attached to the scope, which is another problem that can trip up AngularJS newbs.

I’ve updated my TypeScript AngularJS demo code to reflect this tip. Do check it out because it’s got some useful samples in there on how to then use the new viewModel property.

AngularJS 1.2 Changes

In AngularJS 1.2, our solution may look different still as the $scope will no longer be needed and we can work directly with the controller object and its properties. More on that in the future, but it’ll make our TypeScript lives much easier.

Hat tip to @basarat for this idea.