AngularJS 1.x WGW (What Goes Where) guide

September 14, 2014

A few months ago, I finally had a chance to get my hands on the so-much-talked-about AngularJS framework and I really digged it. In fact, I like it so much that I am 100% sure this framework will stay ahead of others for a long time. Well, in our world this means for at least another year or two.

Though, I’ve got the basics down fairly fast, I had hard time around understanding the proper code organization. Being a perfectionist didn’t help either. Coming from a very opiniated Rails framework it didn’t feel comfortable at first that AngularJS gave significantly more freedom to do things. But thank God the “Rails magic” is gone!

The type of questions that kept poping up in my head were:

  • “OK, I want to code this functionality, but where shoud I really put it”?
  • Should I stick this code into a View controller, or should I put it into a Service?
  • Perhaps, a directive could be a good place for it, but then where exactly in a directive?

Doing my googling I’ve realized there were plenty of other pilligrims like me trying to find their way in this new and exciting AngularJS world.

So, I am putting together this cheatsheet hoping it will guide us on where the stuff should really go. It’s not meant to be detail, but it should give you the right starting point depending on what you are trying to achieve.

*Please note, that I've intentionally omitted the `Service` component from this list. I find that using factories lets me accomplish everything I could do with `Service`, therefore I really had no real need to engage the latter. `Service` component does have some limited benefits if you are using CoffeeScript classes, but this would out of the scope of this post. Let's KISS (Keep It Simple Stupid).*
Use Case App Component Angular Component Examples Notes
  1. Reusable application-wide business logic that does not need to be further configured in `module.config` phase
  2. Application-wide shareable data
Non-configurable Application Service Factory md5Service
These are generally referred to as `application services` or simply `services`. Do not confuse it with the name of AngularJS `Service` component that we've excluded from this post for simplicity.
  1. Reusable application-wide business logic that does need to be configured in `module.config` phase before it can be used
Configurable Application Service Provider facebookLoginProvider
Examples of such configurations may include setting Facebook application id or an API key for accessing geo-location service.
  1. View specific business logic
View Service Factory dashboardViewService
Keeping view logic in application controllers makes them eventually fat. Recommend placing it in the view service instead and have controllers simply call these view service methods and process their responses.
  1. Display model data in UI differently from the actual source data
  2. Filter out ng-repeats based on a certain criteria
View Filter Filter currencyFilter
  1. Models that map to database tables
  2. CRUD interaction with `REST-ful` server-side data sources
  3. Business logic specific to the model
Model Factory ($resource) User
For anything more than a trivial implementation, I recommend using
js-data-angular instead of the built-in `$resource`.
  1. Wire up (e.g. initialize) scope with data and methods for views to use
Application Controller Controller DashboardController
Keep controllers thin. Should mostly contain calls to methods in an application service or in a view service.
  1. Manipulations of DOM template that you want all directive instances to inherit
DOM Template Manipulator Directive
(compile function)
Rarely used1. Does not have access to scope.
  1. Manipulations of DOM instances in linked HTML
  2. Addition of DOM event listeners
  3. Directive specific scope watchers and/or attribute observers
DOM Instance Manipulator Directive (link function) By link function I mean the `post-link` function
  1. Business logic specific to the directive
  2. API methods for communicating between directives
DOM Service/API Directive (controller) A directive controller can be written inline as part of DDO or injected via DI. Another directive wishing to access controller methods of a given directive needs to explicitly require it.
  1. Editable application-wide settings
  2. Editable application-wide value objects or primitives that controller or service components need access to.
Value Value uiConfig
Cannot be injected into the `module.config` phase, but can be altered by a `Decorator`. Examples could include an object that tracks currently logged in user properties or any other object, properties of which you want to access in various parts of your application
  1. Constant application-wide settings
Constant Constant FACEBOOK_ACCOUNT
Besides controller and a service, Constant can also be injected into the `module.config` phase. Constants cannot be altered by a `Decorator`. Avoid modifying the Constant. If you need an editable object or value, use `Value` component/provider instead.
  1. Augment/tweak some-third party service, while leaving the service mostly intact
  2. Initialize a value in a `Value` component where such initialization requires access to a factory service
Decorator Decorator myLog If you simply want to replace an instance, then using `Factory` or `Value` component is musch simpler

1 See example of how a compile function can be used.

for more tips and best practices.