Use a directive to augment a DOM node:
- To transform its contents in a regular manner.
- To add a behaviour that is general and reusable.
Do not use a directive:
- To augment or manipulate shared
scope(use acontrollerinstead). - To allow a partial to include another partial specific to your application (this is not composable, use nested states instead).
Directives are invoked using hypenated-lowercase but are mapped as camelCase. Their factory is a method so is also camelCase. Meaning:
angular.module(...).directive('myDirective', myDirective);
And in HTML:
<div my-directive></div>
Injection is available at the top of the directive only in its function definition. This must be annotated with the @ngInject doctag.
There is no dependency injection in link(). Consequently you cannot change the order of parameters in the link() method.
Use any combination of the restrict characters; Attribute name, Element name, CSS Class name.
Use either template or templateUrl but not both. The template must not be specific to your use case.
If you need specific content then use transculusion, meaning:
replace: true,
transclude: true,
template: '<div ng-transclude></div>',
The replace option relates to the HTML node in which you apply your directive. Generally you will want this node to only comprise your template (any any transcluded content). However when using replace: false your template will appear first, before the existing content.
Your directive should have a well defined dependency on your document. Start with scope: { } to isolate your scope.
Do not use a controller() function, use a link() function instead.
Pass parameters explicitly through attributes. Attributes are a parameter of the link() function, or may be coppied to the isolated scope; @ implies string initialisation, = implies 2-way string binding, & implies a function that evaluates the attribute as a statement.
If you need to expose an API, and only in this case, use a Class for the controller property. Meaning controller: MyController (as the definition not as a string). This will be instantiated. Other directives may require your directive and will receive this instance as an additional parameter in its link() method. See the angular docs for full details.
The driver of complexity in the directive is the link() function. Where your link function is simple then write it in-line. However if it is complex then make it an external Class.