It's important to note that Angular operates on DOM nodes rather than strings. Usually, you don't notice this restriction because when a page loads, the web browser parses HTML into the DOM automatically.
HTML compilation happens in three phases:
$compile
traverses the DOM and matches directives.If the compiler finds that an element matches a directive, then the directive is added to the list of directives that match the DOM element. A single element may match multiple directives.- Once all directives matching a DOM element have been identified, the compiler sorts the directives by their
priority
.Each directive'scompile
functions are executed. Eachcompile
function has a chance to modify the DOM. Eachcompile
function returns alink
function. These functions are composed into a "combined" link function, which invokes each directive's returnedlink
function.
The result of this is a live binding between the scope and the DOM. So at this point, a change in a model on the compiled scope will be reflected in the DOM.
Below is the corresponding code using the
$compile
service. This should help give you an idea of what Angular does internally.var $compile = ...; // injected into your code
var scope = ...;
var parent = ...; // DOM element where the compiled template can be appended
var html = '<div ng-bind="exp"></div>';
// 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.
var element = linkFn(scope);
// Step 4: Append to DOM (optional)
parent.appendChild(element);
How it is rendered? First compile template, calls controller and link function Eg. below
<!doctype html>
<html ng-app="compilation">
<head>
<meta charset="utf-8">
<title>Compilation Demo</title>
<link rel="stylesheet" href="style.css">
<script src="http://code.angularjs.org/1.1.1/angular.js"></script>
<script src="app.js"></script>
</head>
<body>
<div log-compile="parent">
<div log-compile="..child 1">
<div log-compile="....child 1 a"></div>
<div log-compile="....child 1 b"></div>
</div>
<div log-compile="..child 2">
<div log-compile="....child 2 a"></div>
<div log-compile="....child 2 b"></div>
</div>
</div>
<!-- LOG -->
<pre>{{log}}</pre>
</body>
</html>
Inside app.js file
angular.module('compilation', [])
.directive('logCompile', function($rootScope) {
$rootScope.log = "";
return {
controller: function($scope, $attrs) {
$rootScope.log = $rootScope.log + ($attrs.logCompile + ' (controller)\n');
},
compile: function compile(element, attributes) {
$rootScope.log = $rootScope.log + (attributes.logCompile + ' (compile)\n');
return {
pre: function preLink(scope, element, attributes) {
$rootScope.log = $rootScope.log + (attributes.logCompile + ' (pre-link)\n');
},
post: function postLink(scope, element, attributes) {
element.prepend(attributes.logCompile);
$rootScope.log = $rootScope.log + (attributes.logCompile + ' (post-link)\n');
}
};
}
};
})
.directive('terminate', function() {
return {
terminal: true
};
});
Output:
parent (compile)
..child 1 (compile)
....child 1 a (compile)
....child 1 b (compile)
..child 2 (compile)
....child 2 a (compile)
....child 2 b (compile)
parent (controller)
parent (pre-link)
..child 1 (controller)
..child 1 (pre-link)
....child 1 a (controller)
....child 1 a (pre-link)
....child 1 a (post-link)
....child 1 b (controller)
....child 1 b (pre-link)
....child 1 b (post-link)
..child 1 (post-link)
..child 2 (controller)
..child 2 (pre-link)
....child 2 a (controller)
....child 2 a (pre-link)
....child 2 a (post-link)
....child 2 b (controller)
....child 2 b (pre-link)
....child 2 b (post-link)
..child 2 (post-link)
parent (post-link)
No comments:
Post a Comment