In this post I will talk about a few of the benefits of the ControllerAs syntax in Angular.

In my opinion the ControllerAs syntax is a big win over the original $scope based controller definition. In some ways I would almost argue that controllers defined via the $scope pattern aren't even controllers at all. Instead I see them as decorators for building up the $scope object to a point where the $scope object actually becomes the controller.

Granted, I understand that ControllerAs is just a namespace trick. It is still using the original $scope object under the covers. However, it creates a much more intuitive API where methods and properties are associated with the controller instance directly. Instead of the traditional $scope.someMethod(..) syntax you can do myController.someMethod().

For the most part ControllerAs syntax is straight forward, but there are a few tricks you have to know about. One case in particular is attaching a directive's isolate scope properties to a “controllerAs” controller. It turns out that Angular is helping us out by giving us a bindToController property that can be set as part of the directive definition.

The code listing below shows how to declare a directive with isolate scope and tie its scope to the controller

angular.module('greeting-project').controller('greetingController', [ function(){ var vm = this; this.produceGreeting = function(){ vm.greeting = 'Hi there, ' + vm.name; }; } ]); angular.module('greeting-project').directive('greetingDirective',[ function(){ return{ scope:{name:'@'}, templateUrl:'greeting.html', bindToController: true, controller:'greetingController', controllerAs:'greetingController' }; } ]);

By setting bindToController to true Angular will tie the isolate scope to the controller's “this”.

The second win I want to talk about is unit testing. With the old syntax I always found it a bit unintuitive to write unit tests for controllers. Especially since all the functionality was tied to the scope object, so really my tests were not testing the controller, but rather the scope object. With ControllerAs syntax we are able to invoke methods and properties directly on the controller instance. In my opinion this is much more intuitive and readable.

I have added an example in the code listing below

describe('greetingController', function() { var ctrl; beforeEach(module('greeting-project')); beforeEach(inject(function(_$rootScope_, _$controller_){ ctrl = _$controller_('greetingController'); })); it('should add default classes to the element', function() { ctrl.name = 'Joe'; //Calling method directly on the controller instance ctrl.produceGreeting(); expect(ctrl.greeting).toBe('Hi there, Joe'); }); });