⚠️ This lesson is retired and might contain outdated information.

AngularJS Architecture: Prefer the 'controller as' syntax

Lukas Ruebbelke
InstructorLukas Ruebbelke
Share this video with your friends

Social Share Links

Send Tweet

As of Angular 1.2, the use of $scope injectable has been greatly reduced in favor of the "controller as syntax". We are going to take a quick look at cleaning up Eggly to follow this best practice.

[00:02] Hello. In this lesson, we are going to press pause for just a moment, address the issue of scope inheritance, and then do a quick refactor to fix it before we get into our models. Let's see what the problem is. Let's hop into our bookmarks.js file.

[00:23] You can see that we are only binding to one property on scope. That is currentCategoryName. With that in mind, let's hop into the bookmarks template. You can see that we are binding to this property, currentCategory, right here.

[00:44] The question is "What about all these other things that we're binding to?" For instance, this bookmarks collection in ng-repeat or these methods that we're binding to in ng-click. Where do those exist? Obviously, they're not in the bookmarks controller.

[01:05] The answer to that question is they are in this main controller here. You can see the bookmarks collection, these different methods that we're making available onto the main controller and then making it available on the body tag. It's the top-most controller.

[01:28] In AngularJS, scope objects prototypically inherit from their parent scope object all the way up to root scope. This creates an interesting situation where the main controller is the parent controller to the bookmarks controller.

[01:51] We are implicitly attaching the scope object or the properties or methods from main controller onto the scope object of the bookmarks controller. This may seem convenient at first, but when you have an application that's growing in size and complexity, this implicit inheritance is just a recipe for unintended consequences.

[02:19] For instance, what would happen if I changed a property on this bookmarks collection and this URL property actually got changed to local URL or some other property?

[02:35] This template would break, and you wouldn't be able to understand why by looking at the bookmarks controller because you have this implicit scope inheritance. You're actually pulling from a property that is much further up the prototype chain.

[02:52] We are going to fix this problem using the "controller as" syntax. This allows us to convert our controller to appear JavaScript object, and we no longer have to use scope as the glue between our controller and our view.

[03:13] The first thing we're going to do is jump into our state definition and just go "BookmarksCtrl as bookmarks." In our bookmarks controller, we are going to delete the scope object.

[03:29] I am going to create a variable called "bookmarks" and just assign it to "this." This is just a convention that I like to use. It also keeps track of the top-level JavaScript scope in case you have nested callbacks or closures. We'll just go here.

[03:47] Now, we have assigned currentCategory to bookmarks. Let's go back to our template. It's now bookmarks.currentCategoryName. Now, this reads a little bit better, and it's a little bit more precise of where currentCategoryName is coming from.

[04:12] It's on the bookmarks object that we defined in our state definition. It's "BookmarksCtrl as bookmarks," and then we're referencing this property, currentCategoryName, on bookmarks. Let's refresh the page. Let's go to Development. You can see that this is still working.

[04:36] The interesting thing is the implicit inheritance chain is broken. Now, we're no longer reaching out of our controller into a parent controller and pulling down the bookmarks collection, which is why in the next lesson we are going to actually explicitly provide that to our bookmarks controller in the bookmarks model and make that available. Stay tuned for the next lesson. I'll see you then.