By Rick Date: April 28, 2016
When you’re learning Angular, there’s a lot of new vocabulary to learn. This is particularly true for Angular providers. Terms like “directive”, “service”, “filter”, “decorator” and “factory” can be overwhelming at first.
Knowing which provider to pick when you’re adding code to a project can be equally daunting. Given the wide array of choices, it is understandable that some developers hit decision paralysis.
Alternatively, when unsure of the best path forward, the all-too-common response is to load everything into a controller. This gets the job done in many situations but can also lead to technical debt if done recklessly.
Let’s take a look at some common situations and choices below.
When dealing with data or business logic inside of an angular app, the most appropriate solution is a
service or a
factory. This is in contrast to UI related concerns (covered later).
factory objects differ in syntax, but provide the same end result. If you’re unsure which one to use specifically, I recommend a
service for reasons I will cover in a future post.
See above. As a general rule of thumb, complicated business logic (the kind that bloats controllers) is best kept in a
If you have code that relates to “shaping” data from one format to another, a
filter might be the best choice.
Filters ingest an input object and output a new object in a specified format. Usually this is done in the view with the pipe (
|) operator. A less common (but useful) strategy is to call a filter inside of a service or controller using the
$filter lookup service.
If you find yourself copying and pasting code from one HTML file to another or copy/pasting code between controllers, it might be time to pull that logic into a
Directives let you re-use view related logic and presentation. Directives make custom HTML tags and attributes possible and they are Angular’s “killer feature”.
Note: Often, UI components require extensive data manipulation internally. For instance, a data grid may need to manipulate data in complex ways. In such cases, isolate complex logic into its own
factory. You can include this logic by injecting it into the
directive directly. This creates a strong separation of UI and data concerns.
Scenario: You’re using a 3rd party library from Github or NPM. It works great, but there’s one small modification you need to make for your use case. You don’t want to change the original source code because it’s only a minute modification to an otherwise useful provider.
This is where decorators shine. They are one of the least used providers, but are very useful for a small subset of use cases.
A decorator allows you to wrap a service and “decorate” it with additional functionality.
You’re building an Angular view or template and need to do some “data massaging” when the page loads.
Although the Angular style guide recommends keeping controllers focused, this is a use case where putting code in a controller is OK.
Since controllers are highly prone to bloating, it is worth considering bad controller use cases:
ng-clickand friends. Better yet, write a directive.
In real world apps,
services are where the majority of code belongs. Following these basics steps can help keep your controllers slim and technical debt to a minimum.
The majority of technical debt in Angular occurs in the controller. It is always worth asking the question “Does this belong here?” when adding new features to an Angular application.
If you’re still unsure of where to put logic in an application, a service is a good place to start. An exception to this rule is code which modifies the DOM, in which case a directive is almost always the correct solution.
Have questions about a use case we didn’t cover? Let us know in the comments.