October 27, 2015
Angular Directives - Link vs Controller
A little over a year ago I started working at Priceline.com as a Front End Developer. This was my first professional developer position out of Dev Bootcamp (DBC), and it is where I am still working today.
Immediately from day one I began learning AngularJS as the team I was brought in on, was in the process of migrating the stack from jQuery to Angular. Coming from DBC, where there was a heavy focus on jQuery, I felt comfortable for the first few weeks writing A/B tests for the jQuery stack while it was still live in production. However shortly into 2015, the jQuery site was deprecated, and the new stack was completely shifted to Angular.
For the following example I will be using a side project I am working on for which integrates the Spotify API to allow a user to search for an artist, and return a list of their most popular tracks.The following code snippets are the logic behind the search box used for searching for an artist based on search criteria.
Note: This has not been designed!
My early controllers:
When I first started learning Angular, I wasn’t all that comfortable with building directives and I would end up putting the majority (if not all of the functionality) for a page into that page’s controller. If there were directives they would inherit from that controller’s $scope.
A controller may have looked something like this:
(And while functional, this is breaking several best practices)
Messy! – I know! I was putting logic for a feature that could be extrapolated into a component into the page’s controller and therefore bogging down the controller and $scope… I knew something had to change.
I then became more familiar with the ‘link’ function that directives come with so I began moving all the functionality from my page’s controller to the link function. Regardless if the code was meant to manipulate the DOM, change $state, or simply run some logic, I would put everything in the link function. This still didn’t feel right…
While I knew the directives were working, as I continued reading blog posts, and doing more research, I found that I wasn’t following best practices, and I wasn’t properly utilizing the directive’s controller function. One piece of information that really helped me start understanding these concepts better was an article Todd Motto had written which you can find here:
In it, he discusses his style for creating directives (which I have adopted), as well as how to properly utilize a directive’s link and controller functions.
What I’ve learned is that a directive’s controller should handle any logic that is not manipulating the DOM or waiting for the $scope to change. The link function should handle all the functionality that the controller is not responsible for.
So keeping this in mind, I began refactoring my artist search box on my home page to become its own directive, and move the functionality I once had in my home controller to the directive’s controller, and link functions.
The actual click event, originally found in the home page’s controller will now get moved into the artistSearchBox directive’s controller:
And the typeahead logic, that is hitting the Spotify API, and returning a list of artists to the page will belong in the link function, since a $scope.watch() is being used.
The beauty of this, is that now, I no longer need the home controller at all. All of the logic previously found in this controller has been decoupled and moved to the directive, artistSearchBox ,it belongs in. The home controller is no longer being bogging down with unnecessary variables and functions.