Ben Nadel
On User Experience (UX) Design, JavaScript, ColdFusion, Node.js, Life, and Love.
Ben Nadel at Scotch On The Rock (SOTR) 2010 (London) with: Mark Drew and Reto Aeberli
Ben Nadel at Scotch On The Rock (SOTR) 2010 (London) with: Mark Drew@markdrew ) and Reto Aeberli@aeberli )

AngularJS Code Smell: Defining $scope Methods In Directives

By Ben Nadel on

I've touched on this idea before, in my AngularJS directive mindset post; but, I've seen this happen so many times that I wanted to call it out again, as its own concept. If you define $scope methods inside of your AngularJS directives, you might want to consider this a "code smell." Take a moment to think about what that method is doing and consider moving it into the parent Controller or Service.

NOTE: This does not necessarily apply to AngularJS directives that use the Isolate scope.

In AngularJS, directives are the "glue" that binds the View to the Controller. In one direction, they take the data provided by the Controller and help render some of the View. In the other direction, they take JavaScript events, initiated on the DOM (Document Object Model), and pipe them into the hooks exposed by the Controller. Directives are a conduit of communication, not an origin of behavior.

If you find that you are defining $scope methods in your Directives, you're not facilitating communication - you're exposing behavior to the View. Probably, what you want to do is move that $scope method into the parent Controller and then either invoke it directly in the View; or, create an event handler in the Directive that turns around and consumes said $scope method (calling $apply(), $evalAsync(), or $digest() as needed).

This code smell is based on my own experience with AngularJS and the type of directives that I have written. As my applications evolve, I can feel the pain points of poor decision making. And, to me, defining behavior in my Directives has caused pain when it comes to maintaining and refactoring my AngularJS code. Your mileage may vary.

Reader Comments

@Ben - I'm glad you took my ranting to heart. I just saw some code like this in a directive and thought of this post.

$scope.$parent.newFunction = function(){...};


Reply to this Comment

I'm fairly new to angular, but have also felt a sense of unease when assigning functionality to a shared scope through a directive.

However, by treating a controllers scope as a view model, directives (appear to - due to my limited experience) become a useful/scalable way to compose reusable behaviour onto a scope.

At the moment i'm struggling to see a better way to do this without directives. What would you suggest?

Reply to this Comment

@Ben, I have a scenario where I am using common directive for two controllers.

For the common functionality I have added methods directly to the inherited scope, so that I don't have to duplicate the code in different controller.

What do you suggest in this scenario? What would be the best approach in this case?

Reply to this Comment

Post A Comment

You — Get Out Of My Dreams, Get Into My Comments
Live in the Now
Comment Etiquette: Please do not post spam. Please keep the comments on-topic. Please do not post unrelated questions or large chunks of code. And, above all, please be nice to each other - we're trying to have a good conversation here.