AngularJS Whitespace Guide
The purpose of this style guide is to suggest formatting conventions for AngularJS modules that result in readible, maintainable, and lint free code (see the linter configurations for JSHint and gjslint.py.
All-in-one example
Typically, an AngularJS application would be structured with many modules in separate files. The example below shows a monolithic module to illustrate the formatting conventions for various module methods.
angular.module('module.name', [
'dependency.one',
'dependency.two'
])
.animation('.animation-name',
function(injectable1, injectable2) {
// animation factory here
return {};
})
.config(
function(injectable1, injectable2) {
// config function here
injectable1.foo(injectable2);
})
.constant('NamedFunction',
function(value) {
// constant function here
return value * 2;
})
.controller('NamedCtrl',
function(injectable1, injectable2) {
// controller constructor here
this.foo = injectable1() + injectable2();
})
.factory('NamedService1',
function(injectable1, injectable2) {
// service factory here
return {};
})
.service('NamedService2',
function(injectable1, injectable2) {
// service constructor here
this.foo = injectable1() + injectable2();
})
.directive('NamedDirective',
function(injectable1, injectable2) {
// directive factory here
return {};
})
.value('var1', 123);
Details
These formatting guidelines assume that before minifying your code, you process it with ngmin
to generate minifier-safe inline annotations for injectables (ngmin
is available as a Grunt plugin, a Rails gem, and Optimus middleware).
The guidelines assume 2 spaces for tabs and a maximum 80 character line length.
Module registration
angular.module('module.name', [
'dependency.one',
'dependency.two'
])
The module name and opening bracket for the dependency array are on the same line as angular.module
. Module dependencies are listed one per line. Closing bracket and parenthesis are on their own line. The justification for this is that the module name is clearly separated from dependencies, and dependencies are easy to add or remove without extra changes related to line wrapping.
Module configuration
// module registered above
.config(
function(injectable1, injectable2) {
// config function here
});
The .config(
call is on its own line, with the function argument indented 4 spaces on the following line. This follows the pattern for other providers below. A semicolon ends the statement (leave the semicolon off if there are more call expressions in the same file).
The angular.Module
methods that take a name and a factory or constuctor (e.g. controller
, directive
, factory
, etc.) are all written in a similar way.
// module registered above
.controller('NamedCtrl',
function(injectable1, injectable2) {
// controller constructor here
this.foo = injectable1() + injectable2();
});
The first argument (the name of the controller, service, filter, etc.) goes on the same line as the method and opening parenthesis. The factory or constructor function begins on a new line and is indented 4 spaces (function arguments that are on a new line get two tabs). The closing parenthesis immediately follows the closing brace for the function. Omit the semicolon if there are more method calls on the module in the same file.
A value
or constant
call goes on a single line if shorter than 80 characters.
// module registered above
.value('var1', 123);
Edge cases
Functions with a ton of arguments
If a function requires more arguments than fit on a single 80 character line, wrap arguments and indent with two tabs (4 spaces).
// module registered above
.factory('NamedService1',
function(injectable1, injectable2, injectable3, injectable4, injectable5,
injectable6, injectable7, injectable8, injectable9, injectable10) {
// service factory here
return {};
});
(Functions with many arguments would be discouraged as they are harder to reason about, but this is just a whitespace guide.)
Calls to constant
or value
with big object literals
It should be possible to indent big object literals as follows:
// module registered above
.constant('NamedObject', {
property1: 'value1',
property2: 'value2'
})
Unfortunately, gjslint.py
complains about this - expecting 6, 10, or 14 spaces of indentation before property1
instead of 2. When gjslint.py
is satisfied, JSHint
complains that property1
needs 2 spaces indentation and the closing brace needs no indentation. Where possible, the object literal can be written on a single line. Where this is not possible, the following (ugly) format satisfies both linters:
// module registered above
.constant('NamedObject',
{property1: 'value1', property2: 'value2', property3: 'value3',
property4: 'value4'})
@scheffield I typically put one per line as well, in Alpha order ($ declarations in alpha order, then non $ declarations in Alpha order; so like: