Angular Style Guide for enterprise and large-scale projects
Single Responsibility
- Define 1 component per file.
IIFE
- Wrap Angular components in an Immediately Invoked Function Expression (IIFE).
Definitions (aka Setters)
- Declare modules without a variable using the setter syntax.
- When using a module, avoid using a variable and instead use chaining with the getter syntax.
- Only set once and get for all other instances.
Named vs Anonymous Functions
- Use named functions instead of passing an anonymous function in as a callback.
controllerAs View Syntax
- Use the controllerAs syntax over the classic controller with $scope syntax.
- Use a capture variable for this when using the controllerAs syntax. Choose a consistent variable name such as vm, which stands for ViewModel.
- When a controller must be paired with a view and either component may be re-used by other controllers or views, define controllers along with their routes.
Route Resolve Promises
- When a controller depends on a promise to be resolved before the controller is activated, resolve those dependencies in the $stateProvider before the controller logic is executed. If you need to conditionally cancel a route before the controller is activated, use a route resolver.
Bindable Members Up Top
- Place bindable members at the top of the controller, alphabetized, and not spread through the controller code.
- Resolve start-up logic for a controller in an activate function.
Function Declarations to Hide Implementation Details
-
Use function declarations to hide implementation details. Keep your bindable members up top. When you need to bind a function in a controller, point it to a function declaration that appears later in the file. This is tied directly to the section Bindable Members Up Top
-
Resolve start-up logic for a controller in an activate function.
Separate Data Calls
- Refactor logic for making data operations and interacting with data to a factory. Make data services responsible for XHR calls, local storage, stashing in memory, or any other data operations.
Directives
- Create one directive per file. Name the file for the directive.
- When manipulating the DOM directly, use a directive.
- When creating a directive that makes sense as a stand-alone element, allow restrict E (custom element) and optionally restrict A (custom attribute).
- Use controller as syntax with a directive to be consistent with using controller as with view and controller pairings.
- Use bindToController = true when using controller as syntax with a directive when you want to bind the outer scope to the directive's controller's scope.
Manual Annotating for Dependency Injection
- Avoid using the shortcut syntax of declaring dependencies without using a minification-safe approach. Use $inject to manually identify your dependencies for Angular components.
Startup Logic
- Inject code into module configuration that must be configured before running the angular app. Ideal candidates include providers and constants.
- Any code that needs to run when an application starts should be declared in a factory, exposed via a function, and injected into the run block.
Module Dependencies
- The application root module depends on the app specific feature modules and any shared or reusable modules.
Application Structure LIFT Principle
- LIFT is:
- Locating our code is easy
- Identify code at a glance
- Flat structure as long as we can
- Try to stay DRY (Don’t Repeat Yourself) or T-DRY
Folders-by-Feature Structure:
- Create folders named for the feature they represent. When a folder grows to contain more than 7 files, start to consider creating a folder for them. Your threshold may be different, so adjust as needed.