Credit to devdocs.io

angularjs 1.4

angularjs

Improve this Doc View Source $compile

  1. $compileProvider
  2. service in module ng

Compiles an HTML string or DOM into a template and produces a template function, which can then be used to link scope and the template together.

The compilation is a process of walking the DOM tree and matching DOM elements to directives.

Note: This document is an in-depth reference of all directive options. For a gentle introduction to directives with examples of common use cases, see the directive guide.

Comprehensive Directive API

There are many different options for a directive.

The difference resides in the return value of the factory function. You can either return a "Directive Definition Object" (see below) that defines the directive properties, or just the postLink function (all other properties will have the default values).

Best Practice: It's recommended to use the "directive definition object" form.

Here's an example directive declared with a Directive Definition Object:

var myModule = angular.module(...);

myModule.directive('directiveName', function factory(injectables) {
  var directiveDefinitionObject = {
    priority: 0,
    template: '<div></div>', // or // function(tElement, tAttrs) { ... },
    // or
    // templateUrl: 'directive.html', // or // function(tElement, tAttrs) { ... },
    transclude: false,
    restrict: 'A',
    templateNamespace: 'html',
    scope: false,
    controller: function($scope, $element, $attrs, $transclude, otherInjectables) { ... },
    controllerAs: 'stringIdentifier',
    bindToController: false,
    require: 'siblingDirectiveName', // or // ['^parentDirectiveName', '?optionalDirectiveName', '?^optionalParent'],
    compile: function compile(tElement, tAttrs, transclude) {
      return {
        pre: function preLink(scope, iElement, iAttrs, controller) { ... },
        post: function postLink(scope, iElement, iAttrs, controller) { ... }
      }
      // or
      // return function postLink( ... ) { ... }
    },
    // or
    // link: {
    //  pre: function preLink(scope, iElement, iAttrs, controller) { ... },
    //  post: function postLink(scope, iElement, iAttrs, controller) { ... }
    // }
    // or
    // link: function postLink( ... ) { ... }
  };
  return directiveDefinitionObject;
});
Note: Any unspecified options will use the default value. You can see the default values below.

Therefore the above can be simplified as:

var myModule = angular.module(...);

myModule.directive('directiveName', function factory(injectables) {
  var directiveDefinitionObject = {
    link: function postLink(scope, iElement, iAttrs) { ... }
  };
  return directiveDefinitionObject;
  // or
  // return function postLink(scope, iElement, iAttrs) { ... }
});

Directive Definition Object

The directive definition object provides instructions to the compiler. The attributes are:

multiElement

When this property is set to true, the HTML compiler will collect DOM nodes between nodes with the attributes directive-name-start and directive-name-end, and group them together as the directive elements. It is recommended that this feature be used on directives which are not strictly behavioural (such as ngClick), and which do not manipulate or replace child nodes (such as ngInclude).

priority

When there are multiple directives defined on a single DOM element, sometimes it is necessary to specify the order in which the directives are applied. The priority is used to sort the directives before their compile functions get called. Priority is defined as a number. Directives with greater numerical priority are compiled first. Pre-link functions are also run in priority order, but post-link functions are run in reverse order. The order of directives with the same priority is undefined. The default priority is 0.

terminal

If set to true then the current priority will be the last set of directives which will execute (any directives at the current priority will still execute as the order of execution on same priority is undefined). Note that expressions and other directives used in the directive's template will also be excluded from execution.

scope

The scope property can be true, an object or a falsy value:

  • falsy: No scope will be created for the directive. The directive will use its parent's scope.

  • true: A new child scope that prototypically inherits from its parent will be created for the directive's element. If multiple directives on the same element request a new scope, only one new scope is created. The new scope rule does not apply for the root of the template since the root of the template always gets a new scope.

  • {...} (an object hash): A new "isolate" scope is created for the directive's element. The 'isolate' scope differs from normal scope in that it does not prototypically inherit from its parent scope. This is useful when creating reusable components, which should not accidentally read or modify data in the parent scope.

The 'isolate' scope object hash defines a set of local scope properties derived from attributes on the directive's element. These local properties are useful for aliasing values for templates. The keys in the object hash map to the name of the property on the isolate scope; the values define how the property is bound to the parent scope, via matching attributes on the directive's element:

  • @ or @attr - bind a local scope property to the value of DOM attribute. The result is always a string since DOM attributes are strings. If no attr name is specified then the attribute name is assumed to be the same as the local name. Given <my-component my-attr="hello {{name}}"> and the isolate scope definition scope: { localName:'@myAttr' }, the directive's scope property localName will reflect the interpolated value of hello {{name}}. As the name attribute changes so will the localName property on the directive's scope. The name is read from the parent scope (not the directive's scope).

  • = or =attr - set up a bidirectional binding between a local scope property and an expression passed via the attribute attr. The expression is evaluated in the context of the parent scope. If no attr name is specified then the attribute name is assumed to be the same as the local name. Given <my-component my-attr="parentModel"> and the isolate scope definition scope: { localModel: '=myAttr' }, the property localModel on the directive's scope will reflect the value of parentModel on the parent scope. Changes to parentModel will be reflected in localModel and vice versa. Optional attributes should be marked as such with a question mark: =? or =?attr. If the binding expression is non-assignable, or if the attribute isn't optional and doesn't exist, an exception ($compile:nonassign) will be thrown upon discovering changes to the local value, since it will be impossible to sync them back to the parent scope. By default, the $watch method is used for tracking changes, and the equality check is based on object identity. However, if an object literal or an array literal is passed as the binding expression, the equality check is done by value (using the angular.equals function). It's also possible to watch the evaluated value shallowly with $watchCollection: use =* or =*attr (=*? or =*?attr if the attribute is optional).

  • & or &attr - provides a way to execute an expression in the context of the parent scope. If no attr name is specified then the attribute name is assumed to be the same as the local name. Given <my-component my-attr="count = count + value"> and the isolate scope definition scope: { localFn:'&myAttr' }, the isolate scope property localFn will point to a function wrapper for the count = count + value expression. Often it's desirable to pass data from the isolated scope via an expression to the parent scope. This can be done by passing a map of local variable names and values into the expression wrapper fn. For example, if the expression is increment(amount) then we can specify the amount value by calling the localFn as localFn({amount: 22}).

In general it's possible to apply more than one directive to one element, but there might be limitations depending on the type of scope required by the directives. The following points will help explain these limitations. For simplicity only two directives are taken into account, but it is also applicable for several directives:

  • no scope + no scope => Two directives which don't require their own scope will use their parent's scope
  • child scope + no scope => Both directives will share one single child scope
  • child scope + child scope => Both directives will share one single child scope
  • isolated scope + no scope => The isolated directive will use it's own created isolated scope. The other directive will use its parent's scope
  • isolated scope + child scope => Won't work! Only one scope can be related to one element. Therefore these directives cannot be applied to the same element.
  • isolated scope + isolated scope => Won't work! Only one scope can be related to one element. Therefore these directives cannot be applied to the same element.

bindToController

This property is used to bind scope properties directly to the controller. It can be either true or an object hash with the same format as the scope property. Additionally, a controller alias must be set, either by using controllerAs: 'myAlias' or by specifying the alias in the controller definition: controller: 'myCtrl as myAlias'.

When an isolate scope is used for a directive (see above), bindToController: true will allow a component to have its properties bound to the controller, rather than to scope. When the controller is instantiated, the initial values of the isolate scope bindings are already available.

It is also possible to set bindToController to an object hash with the same format as the scope property. This will set up the scope bindings to the controller directly. Note that scope can still be used to define which kind of scope is created. By default, no scope is created. Use scope: {} to create an isolate scope (useful for component directives).

If both bindToController and scope are defined and have object hashes, bindToController overrides scope.

controller

Controller constructor function. The controller is instantiated before the pre-linking phase and can be accessed by other directives (see require attribute). This allows the directives to communicate with each other and augment each other's behavior. The controller is injectable (and supports bracket notation) with the following locals:

  • $scope - Current scope associated with the element
  • $element - Current element
  • $attrs - Current attributes object for the element
  • $transclude - A transclude linking function pre-bound to the correct transclusion scope: function([scope], cloneLinkingFn, futureParentElement).
    • scope: optional argument to override the scope.
    • cloneLinkingFn: optional argument to create clones of the original transcluded content.
    • futureParentElement:
      • defines the parent to which the cloneLinkingFn will add the cloned elements.
      • default: $element.parent() resp. $element for transclude:'element' resp. transclude:true.
      • only needed for transcludes that are allowed to contain non html elements (e.g. SVG elements) and when the cloneLinkinFn is passed, as those elements need to created and cloned in a special way when they are defined outside their usual containers (e.g. like <svg>).
      • See also the directive.templateNamespace property.

require

Require another directive and inject its controller as the fourth argument to the linking function. The require takes a string name (or array of strings) of the directive(s) to pass in. If an array is used, the injected argument will be an array in corresponding order. If no such directive can be found, or if the directive does not have a controller, then an error is raised (unless no link function is specified, in which case error checking is skipped). The name can be prefixed with:

  • (no prefix) - Locate the required controller on the current element. Throw an error if not found.
  • ? - Attempt to locate the required controller or pass null to the link fn if not found.
  • ^ - Locate the required controller by searching the element and its parents. Throw an error if not found.
  • ^^ - Locate the required controller by searching the element's parents. Throw an error if not found.
  • ?^ - Attempt to locate the required controller by searching the element and its parents or pass null to the link fn if not found.
  • ?^^ - Attempt to locate the required con