Last Updated: March 29, 2021
·
303
· brendt

Why you should use $scope

Why you should use $scope

Components in AngularJS rock!

After reading a few blog posts about avoiding the use of $scope, I was confused. I read here and there about all the bad things that could happen when using $scope in nested controllers, using ng-controller in your HTML. For those who don’t know what I’m talking about, here’s a small example:

<div ng-controller="ParentController">
  ParentController: <input type="text" ng-model="foo" />
  <div ng-controller="ChildController">
    ChildController: <input type="text" ng-model="foo" />
  </div>
</div>

The issue here has to do with the way properties are bound to objects in Javascript. I could very well understand this issue, but why had I never encountered problems before? Because using nested controllers is not the way to go.

Components

To understand the issue I’d recommend reading the blog post I’ve linked before. I’ll stick to explaining why I never had any issues: components. With MVC in mind, working with components is a very intuitive, creates a comprehensible codebase and offers a lot of reusability. Because AngularJS doesn’t really have a coding standard yet, everyone just kinda does his own thing.

Take a look at the following folder structure, based on a project I’ve worked on.

app
├── app.module.js
├── app.routes.js
├── components
│  ├── auth
│  │   ├── auth.controllers.js
│  │   └── views
│  │       ├── login.view.html
│  │       └── logout.view.html
│  └── categories
│  │   ├── category.controllers.js
│  │   └── views
│  │       ├── form.view.html
│  │       └── list.view.html
│  └── materials
│      ├── material.controllers.js
│      └── views
│          ├── form.view.html
│          ├── detail.view.html
│          └── list.view.html
└── shared
   ├── directives
   │  ├── list
   │  │    ├── list.directives.js
   │  │    └── views
   │  │        ├── tableList.view.html
   │  │        └── sortableList.view.html
   ├── filters
   │  ├── html.filters.js
   │  └── date.filters.js
   └── services
      ├── api.services.js
      └── auth.services.js

Using a components-based approach, you should only need one controller at all times. One for each component. As you can see in above example, I split components based on major functionality. Each sub-folder of components actually has multiple components: the controllers.js files contain multiple controllers (hence controllers.js). Every controller is linked via the app.routes.js file to a view. This view really represents a single component. You might want to split your code even further, creating a single file for each controller, which is actually encouraged by the AngularJS team.

app
├── app.module.js
├── app.routes.js
└── components
   └── auth
       ├── login
       │   ├── controller.js
       │   └── view.html
       └── logout
           ├── controller.js
           └── view.html

One could debate what the best way is to name files. Eg. in the first example, I always suffix my files like login.view.html or material.controllers.js. In the second example, I just name them controller.js and view.html, because you could determine the exact functionality based on the path: auth/login/controller.js. I prefer the first way, but I guess there is no real convention about it. One thing is certain though: using components, you only use one controller, combined with one view. These are combined in app.routes.js like so.

.when('/auth/login', {
    controller: 'AuthLoginController',
    templateUrl: 'app/components/auth/login/view.html',
})

I find the argument about not using $scope a sign of rather bad coding, not because of the inheritance argument, but because of the way one’d have to structure his code before this could become an issue.


Links

A component based AngularJS framework

More about components

Read this article on Medium