Comparing Directive Scope Options in AngularJS

When defining directives in AngularJS, there are three different ways to pass in variables: no scope, inherited scope, or isolated scope. Whether or not you’re using the “controller as” syntax (and I hope you are), you still have to decide which one to use. In this post, I’ll explain the differences and suggest why you might—or might not—want to use each one.

No Scope

 scope: false 

Using this type of directive scope is usually a bad practice that should be avoided. When you choose this option, you are specifying that your directive has no scope of its own and shares a scope with its parent controller. Anything the parent controller mutates or adds to the scope will be present on the directive, and vice versa.

My previous blog post demonstrated a positive example of using scope: false in directives. In this example, I used it to cleanly swap out DOM in the template of my top level directive, and all of the directives were serving the same simple purpose (switching superheroes) in my application. I think scope: false can be a great way to introduce organization and readability in a template, but beyond that, using it can be a slippery slope to spaghetti code that’s difficult to understand.

Inherited Scope

scope: true

Inherited scope is much safer for your parent controller’s data than no scope. As with the scope: false option, everything that exists on the parent controller’s scope is present in the directive. However, anything the directive adds to the scope is not shared with the parent scope. This protects the parent controller’s data while allowing it to be shared with the directive.

scope: true is useful in situations where the child directive serves the purpose of mutating data on the parent scope. While safer than scope:false, using inherited scope, especially repeatedly, is an architectural smell.

Isolated Scope

scope: {
  myProperty: '='

Isolated scope is the best practice of them all. With this option, the programmer defines which attributes are passed to the directive. Nothing else is shared between parent controller and directive.

Isolated scope encourages (and enforces) good SPA architecture and the development of small, focused components. Using isolated scope (especially with the “controller as” syntax) is a sign of good architecture, and it results in a directive that will be easy to convert to an Angular 2.0 component.

…So, Which Do I Use?

It all depends! In a perfect Angular application, you would use isolated scope in all of your directives. However, not all applications are perfect, and not all rules are absolute.

  • Using no scope can be helpful to organize your templates.
  • Using inherited scope can help you refactor no scope directives. It’s also useful for managing architectures that focus on mutating data down the directive tree rather than returning small pieces of updated data up the tree back to the parent controller.
  • For smooth Angular 2.0 migration, you should start working towards only using isolated scope in your application.