From 4804c83b7db5770d5d02eea9eea4cc012b4aa524 Mon Sep 17 00:00:00 2001 From: Misko Hevery Date: Wed, 14 Dec 2011 02:55:31 +0100 Subject: docs(compiler): update the compiler docs --- ...ular.module.ng.$compileProvider.directive.ngdoc | 505 +++++++++++++++++++++ 1 file changed, 505 insertions(+) create mode 100644 docs/content/api/angular.module.ng.$compileProvider.directive.ngdoc (limited to 'docs/content/api/angular.module.ng.$compileProvider.directive.ngdoc') diff --git a/docs/content/api/angular.module.ng.$compileProvider.directive.ngdoc b/docs/content/api/angular.module.ng.$compileProvider.directive.ngdoc new file mode 100644 index 00000000..5a258179 --- /dev/null +++ b/docs/content/api/angular.module.ng.$compileProvider.directive.ngdoc @@ -0,0 +1,505 @@ +@ngdoc overview +@name angular.module.ng.$compileProvider.directive +@description + +Directives are a way to teach HTML new tricks. During DOM compilation directives are matched +against the HTML and executed. This allows directives to register behavior, or transform the DOM. + +Angular comes with a built in set of directives which are useful for building web applications but +can be extended such that HTML can be turned into a declarative domain specific language (DSL). + +# Invoking directives from HTML + +Directives have camel cased names such as 'ngBind'. The directive can be invoked by translating +the camel case name into snake case with these special characters `:`, `-`, or `_`. Optionally the +directive can be prefixed with `x-`, or `data-` to make it HTML validator compliant. Here is a +list of some of the possible directive names: `ng:bind`, `ng-bind`, `ng_bind`, `x-ng-bind` and +`data-ng-bind`. + +The directives can be placed in element names, attributes, class names, as well as comments. Here +are some equivalent examples of invoking `ngBind`. + +
+ + ++ +Directives can be invoked in many different ways, but are equivalent in the end result as shown in +the following example. + ++ +
++ +# Compilation process, and directive matching + +Compilation of HTML happens in three phases: + + 1. First the HTML is parsed into DOM using the standard browser API. This is important to + realize because the templates must be parsable HTML. This is in contrast to most templating + systems that operate on strings, rather then on DOM elements. + + 2. The compilation of the DOM is performed by the call to {@link angular.module.ng.$compile + $compile()} method. The method traverses the DOM and matches the directives. If a match is found + it is added to the list of directives associated with the given DOM element. Once all directives + for a given DOM element have been identified they are sorted by priority and their `compile()` + functions are executed. The directive compile function has a chance to modify the DOM structure + and is responsible for producing a `link()` function explained next. The {@link + angular.module.ng.$compile $compile()} method returns a combined linking function, which is a + collection of all of the linking functions returned from the individual directive compile + functions. + + 3. Link the template with scope by calling the liking function returned from the previous step. + This in turn will call the linking function of the individual directives allowing them to + register any listeners on the elements and set up any {@link + angular.module.ng.$rootScope.Scope#.watch watches} with the {@link + angular.module.ng.$rootScope.Scope scope}. The result of this is a live binding between the + scope and the DOM. A change in the scope is reflected in the DOM. + +Hello {{username}}! +
+ var $compile = ...; // injected into your code + var scope = ...; + + var html = ''; + + // Step 1: parse HTML into DOM element + var template = angular.element(html); + + // Step 2: compile the template + var linkFn = $compile(template); + + // Step 3: link the compiled template with the scope. + linkFn(scope); ++ +## Reasons behind the compile/link separation + +At this point you may wonder why is the compile process broken down to a compile and link phase. +To understand this, lets look at a real world example with repeater: + +
+ Hello {{user}}, you have these actions:
+
+ var $compileProvider = ...;
+
+ $compileProvider.directive('directiveName', function factory(injectables) {
+ var directiveDefinitionObject = {
+ priority: 0,
+ template: '',
+ templateUrl: 'directive.html',
+ restrict: 'EACM',
+ scope: false,
+ compile: function compile(tElement, tAttrs) {
+ return {
+ pre: function preLink(scope, iElement, iAttrs) { ... },
+ post: function postLink(scope, iElement, iAttrs) { ... }
+ }
+ },
+ link: function postLink(scope, iElement, iAttrs) { ... }
+ };
+ return directiveDefinitionObject;
+ });
+
+
+In most cases you will not need such fine control and so the above can be simplified. All of the
+different parts of this skeleton are explained in following sections. In this section we are
+interested only isomers of this skeleton.
+
+It is rare that you need `preLink` method since most directives use the `postLink` method.
+Therefore the above can be simplified as:
+
+
+ var $compileProvider = ...;
+
+ $compileProvider.directive('directiveName', function factory(injectables) {
+ var directiveDefinitionObject = {
+ compile: function compile(tElement, tAttrs) {
+ return function postLink(scope, iElement, iAttrs) { ... }
+ }
+ };
+ return directiveDefinitionObject;
+ });
+
+
+Most directives concern themselves only with instances not with template transformations allowing
+further simplification:
+
+
+ var $compileProvider = ...;
+
+ $compileProvider.directive('directiveName', function factory(injectables) {
+ return function postLink(scope, iElement, iAttrs) { ... }
+ });
+
+
+
+## Factory method
+
+The factory method is responsible for creating the directive. It is invoked only once, when the
+{@link angular.module.ng.$compile compiler} matches the directive for the first time. You can
+perform any initialization work here. The method is invoked using the {@link
+http://localhost:8000/build/docs/api/angular.module.AUTO.$injector#invoke $injector.invoke} which
+makes it injectable following all of the rules of injection annotation.
+
+## Directive Definition Object
+
+The directive definition object provides instructions to the {@link angular.module.ng.$compile
+compiler}. The attributes are:
+
+ * `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. Higher `priority` goes
+ first. The order of directives within the same priority is undefined.
+
+ * `terminal` - If set to true then the current `priority` will be the last set of directives
+ which will execute (this means that any directives at the current priority will still execute
+ as the order of execution on same `priority` is undefined).
+
+ * `scope` - If set to true, then a new scope will be created for this directive. It is an error
+ to have two directives on the same element both requesting new scope. The new scope rule does
+ not apply for the root of the template since the root of the template always gets a new scope.
+
+ * `restrict` - String of subset of `EACM` which restricts the directive to a specific directive
+ declaration style.
+
+ * `E` - Element name: `
+ function compile(tElement, tAttrs) { ... }
+
+
+Compile function deals with transforming the template DOM. Since most directives do not do
+template transformation, it is not used often. Examples which require compile functions are
+directives which transform template DOM such as {@link
+angular.module.ng.$compileProvider.directive.ng:repeat ng:repeat} or load the contents
+asynchronously such as {@link angular.module.ng.$compileProvider.directive.ng:view ng:view}. The
+compile functions takes the following arguments.
+
+ * `tElement` - template element - The element where the directive has been declared. It is
+ safe to do template transformation on the element and child elements only.
+
+ * `tAttrs` - template attributes - Normalized list of attributes declared on this element shared
+ between all directive compile functions. See {@link
+ angular.module.ng.$compileProvider.directive.Attributes Attributes}
+
+NOTE: The template instance and the link instance may not be the same objects if the template has
+been cloned. For this reason it is not safe to do anything other the DOM transformation.
+Specifically listener registration as not allowed inside the compile function.
+
+## Link function
+
+
+ function link(scope, iElement, iAttrs) { ... }
+
+
+Compile function is responsible for registering DOM listeners as well as updating the DOM. It is
+executed after the template has been cloned. This is where most of the directive logic will be
+put.
+
+ * `scope` - {@link angular.module.ng.$rootScope.Scope Scope} - The scope to be used be the
+ directive for registering {@link angular.module.ng.$rootScope.Scope#.watch watches}.
+
+ * `iElement` - instance element - The element where the directive is to be used. It is safe to
+ manipulate the children of the element only in `postLink` function since the children have
+ already been linked.
+
+ * `iAttrs` - instance attributes - Normalized list of attributes declared on this element shared
+ between all directive linking functions. See {@link
+ angular.module.ng.$compileProvider.directive.Attributes Attributes}
+
+
+### Pre link function
+
+Executed before the child elements are linked. Not safe to do DOM transformation since the
+compiler linking function will fail to locate the correct elements for linking.
+
+### Post link function
+
+Executed after the child elements are linked. Safe to do DOM transformation in here.
+
+## Attributes
+
+Attributes object is a way of accessing element attributes which:
+
+ * *normalize attribute names:* Since a directive such as 'ngBind' can be expressed in many ways
+ sucha s as 'ng:bind', or 'x-ng-bind', the attributes object allows for a normalize accessed to
+ the attributes.
+
+ * *directive inter-communication:* All directives share the same instance of the attributes
+ object which allows the directives to use the attributes object as inter directive
+ communication.
+
+ * *supports interpolation:* Interpolation attributes are assigned to the attribute object
+ allowing other directives to read the interpolated value.
+
+
+# Creating Widgets
+
+It is often desirable to replace a single directive with a more complex DOM structure. This
+allows the directives to become a short hand for reusable components from which applications
+can be built.
+
+Following is an example of building a reusable widget.
+
+
+