OdeToCode IC Logo

Thoughts on Angular's Controller As Syntax

Monday, August 11, 2014

I’ve been a bit late to the Angular controller as syntax. I was skeptical of the feature at first, and with an Angular project already in flight, I felt it wasn’t the type of change to make with a significant amount of code already committed.

The controller as syntax allows me to alias a controller in markup.

<div ng-controller="MainController as main">
    {{ main.title }}
</div>

Then instead of injecting a $scope into the controller, model data and behavior is added to the controller instance itself.

app.controller("MainController", function(){
    this.title = “Hello!”;
});

Behind the scenes the controller as syntax adds the controller alias (main in the above example) to a scope object, because Angular still evaluates all binding expressions against a scope object.

Here’s what I think about controller as now.

The Good

- Using the controller alias in a view is a push into the pit of success. View code is more explicit and easier to maintain. Even when using $scope in a controller, I’ve come to view any reliance on prototypal inheritance in the scope chain with suspicion, as the inheritance is brittle, subtle, and often complicates both controller and test code. With a controller alias there is no reliance on scope inheritance hierarchies.

- Not having to inject a $scope makes test code slightly easier.

- Having no access to the $scope API inside a controller is a good thing. I’ve come to view any use of $scope.$watch, $scope.$emit, $scope.$on, and $scope.$* in general with suspicion, at least when inside the controller code for a view. Nearly all the functionality available through the $scope API is better used inside of directives or services that provide a better abstraction.

- Thinking of the controller as a true constructor function instead of a function that adds stuff to $scope is healthier. You can take advantage of the constructor function prototype property to organize code, and this will work well with ES6 class definitions (which presumably will work well with ng 2.0). 

The Bad

- Writing directive controllers is different than writing view controllers. With directive controllers the instance members are often used as an API for intra-controller coordination, and this API should be separate from the model for the view.

- Somewhat related to the above, I’m still not convinced that tangling the controller and view model together is a good idea. I think there is some value in having a dedicated factory for view models.

Summary

The good appears to outweigh the bad, so I’ll switch over to using controller as syntax moving forward. I don’t think controller as is a panacea for complicated$scope code, but it does push people in a better direction.

I also think controller as  highlights the need for Angular 2.0 to make some huge, breaking changes. Once of Angular’s greatest strengths, for me, is that the framework provides enough flexibility to build a variety of apps both large and small. Routing is optional, for example, and most programming can be done with plain old JavaScript objects. However, the surface area of the framework is dangerously close to being a Mirkwood forest of programming techniques. A streamlined API with stronger opinions about how to tie components together would make the framework easier to use.