Skip to content

Different kinds of angularjs directives

Angularjs directives are a powerful tool. Like many powerful tools, it can take some time to figure out how to use it, and it’s easy to create a working solution that you’ll regret later. I’ve been using angular in small projects for a few years now, and have come up with a few different ways to think about and classify simple directives.

Component Directive

A logical user-inteface element. Is the trio of directive / template / controller. Usually has an isolated scope, and is self-contained. These are like .NET user or server controls. Much of john papa’s style guide advice applies to the controller and views used in component directive.

Use attributes to pass data in, and data gets out via double-data binding, events, or calling services.

Component directives are not composable.

Usage looks like <my-component ng-model="vm.thing"/> (or <div my-component> depending on IE support).

Example

Mixin Directive

Add behavior to an existing element. Doesn’t isolate scope, but may read attributes directly. Rarely has a controller, mostly is just a link function.

Similar to bootstrap data- annotations or the approach of “unobtrusive” jquery plugins that function based on custom attributes.

Mixin directives are meant to be composable.

Usage looks like <input ng-model="vm.thing" my-mixin/>.

I haven’t found a many cases to write these, but many of the built-in directives fall into this category: ngDisabled, ngClass, etc.

DOM Macro Directive

Adds DOM to or around and existing element. Uses transclusion when possible, direct angular.element manipulation if not. Doesn’t have a scope, but may read attributes directly in the link function. Rarely has a controller, mostly is just a link function.

Many of the angular bootstrap directives fall into this category; they add a bunch of HTML so you don’t have to type it again.

DOM macro directives are composable, but you’ll likely need to mess with priority to get the results you want.

Example

Meta Directive

Directive that adds other directives. Doesn’t isolate scope, rarely has a controller, reads configuration from attributes or services. Has some complicated boilerplate. The meta directive is similar to a DOM macro directive, and helps reduce repetitive angular directives.

Meant to be composable, which is the primary reason to use these.

Usage looks like <button ng-click="vm.remove()" my-remove-button/>.

Most macro directives could be implemented as component directives or DOM macro directives, but will less flexibility. For example, we could implement a remove button as a component, and use it like <my-remove-button ng-click="vm.remove()"/>.

But then we want to disable the button sometimes. In the macro directive, we can just add ngDisabled:

<button ng-click="vm.remove()" my-remove-button ng-disabled="vm.canRemove"/>

For the component directive, we can do the same thing, but we need to teach the component about ng-disabled, and it’s template needs to render as <button ng-disabled />. This is straightforward work, but still work.

The remove button isn’t a great example since it’s so simple, but is shows the weird boilerplate needed. Consider wanting common settings throughout your application for a more complicated directive like a datepicker

Example

Other references