controllerAs
syntax is a good first step into being able to have some sort of sense of hierarchy in applications. However, large controllers can still get unwieldy. We can move towards controlling our controllers with angular.extend
.
TL;DR
Put all your controller properties into an object literal, and extend that object into this
:
After that, always use this
to refer to controller properties (don’t use vm.whatever
).
A brief overview of controllerAs
Skip to the next section if you already know how to use this.
Basically, if you have a parent controller and a child controller nested within, you have to explicitly refer to $scope.$parent
to access the parent controller from the child controller.
However, with controllerAs
syntax, we get a namespace.
But then in your controller, you might have to deal with this:
Also, wondering why we’re using vm
? Check out John Papa’s AngularJS Style Guide.
Now imagine that, 1000x, when you have a controller full of lots and lots of stuff. Really, you could argue that you should consider leveraging directives and services for most of your business logic, but sometimes it’s difficult to do.
By the way, controllerAs
still knows about $scope
. This fake “namespace” simply happens internally by attaching an object to $scope
. So in the above example, our parent controller $scope
would look like this:
In fact, if you were to inject $scope
into that controller and ask for $scope.parent
, you’d see all those properties. There’s nothing fancy about it.
Extending the view model
Ever heard of angular.extend
? It’s pretty nifty. It basically just puts properties from one object into another object, without overwriting any properties. AngularJS already attempts to protect us from this by delimiting internal properties with $
or $$
, so it’s not really a concern anyway, but it’s a nice added touch.
So, we can just make our controller look like this:
However, you’ll notice that it’ll usually be better from then on to continue to refer to controller properties with this
rather than vm
, because any changes through data-binding will propogate only to this
(our namespaced controller), and not to our vm
object reference. You can leverage things like Function.prototype.bind
if you get into hairy contexts (like forEach
loops, etc.).