I'm trying to understand the difference between compile and link function. In the angular documentation for the compiler it says
Some directives such as ng-repeat clone DOM elements once for each item in a collection. Having a compile and link phase improves performance since the cloned template only needs to be compiled once, and then linked once for each clone instance.
I looked at the source code to try and understand how this works and I don't get how it creates a separate linking function for each cloned instance. To me it looks like the compile function returns one linking function for the ng-repeat directive. This linking function does create a new scope for each element in the ng-repeat but doesn't give each cloned instance a separate linking function.
One thing that can be confusing about their description is they're trying to discuss the idea of a directive within an <ng-repeat>
as opposed to discussing <ng-repeat>
itself.
The idea is that even if you have multiple instantiations of a particular directive (for instance because they are within an <ng-repeat>
) the compile function is executed once and only once for the lifetime of your app. Thus, the performance benefit of putting code in here is that it only gets run only once. And that's also the potential problem. The only things that should go in a compile function are things that are common to all the instantiations of that directive.
The link function, on the other hand, is executed once for each instantiation of that directive (again, for example, within an <ng-repeat>
).
So you can think of the compile function as setting up the template of what a directive of this type should be, while the link function sets up an actual instance of that directive. This is why the link function gets a $scope passed in to it and the compile doesn't and why the link function is the much more commonly used one.
For a great discussion of exactly this by one of the authors of Angular, check out: http://www.youtube.com/watch?v=WqmeI5fZcho&list=TLwY_LmqLDXW_3QKhTNm1zKa9j40TvPO2O (13:42 is where Misko address link vs compile functions)
In addtion to KayakDave's answer, here is a simple implementation of ng-repeat that doesn't do any of the collection watching. The plunker has logging that shows the sequence of events and even has some examples that show how priority works.
Plunker
Link to source question
Javascript:
app.directive('fakeRepeat', function() {
return {
priority: 1000,
terminal: true,
transclude: 'element',
compile: function(el, attr, linker) {
return function(scope, $element, $attr) {
angular.forEach(scope.$eval($attr.fakeRepeat).reverse(), function(x) {
var child = scope.$new();
child[attr.binding] = x;
linker(child, function(clone) {
$element.after(clone);
});
});
}
}
}
});
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With