3

I am trying to retrieve my template for a directive using a repository I have built that returns a promise that resolves to the contents of the template.

What is the difference between using the compile function in a directive and using the $compile service in the link function?

Compile Function

compile: function (element, attrs) {
    templateRepository.get('Shared/Login').then(function (result) {
        element.replaceWith(result);
    });
}

This renders the HTML, but the scope is not bound to the DOM elements.

Using $compile

link: function (scope, elem, attrs) {
    templateRepository.get('Shared/Login').then(function (result) {
        elem.html(result);
        $compile(elem.contents())(scope);
    });
}

This works as expected.

What is the difference here?

2 Answers 2

2

$compile:

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.

So $compile does the Angular processing on whatever DOM elements are handed to it.

During $compile the Compile Function within all found directives is run. Note that each directive's compile function is executed just once, no matter how many instances of that directive there are.

When the template function produced by $compile is executed ("to link scope and the template together") then each directive's link function is executed (with the scope passed in as the first parameter).

So $compile transforms the DOM. While the directive's compile function is what's run, for that directive, during that transformation.

Here's a little fiddle you can experiment with which shows the order of execution.

Sign up to request clarification or add additional context in comments.

7 Comments

So the directives compile function does no linking to scope, only creates a template from the directive and the element it is attached to? If true, then using the $compile service is the correct way to do what I want?
This compiledResult = $compile(elem.contents()) does no linking against scope. This compiledResult(scope) or $compile(elem.contents())(scope) does. So the $compile itself doesn't link, but executing the function it returns (the template function) against a scope does.
But also note, neither $compile not executing the resulting template function adds the element to the dom. You can have a compiled element that is not yet on the DOM, or vice-versa.
Very well explained!! Adding it to the DOM is done in the elem.html(result) correct?
Two issues with doing it in the compile. One, like you mention, there's no scope available in the compile function. And compile is only called once for a directive- no matter how many instances there are of it. So it's like a constructor function for the directive. Thus, using the compile function you couldn't have multiple copies of the directive with different html.
|
1

I think, Compile Function is a bit more agile:

From docs:

A compile function can have a return value which can be either a function or an object.

returning a (post-link) function - is equivalent to registering the linking function via the link property of the config object when the compile function is empty.

returning an object with function(s) registered via pre and post properties - allows you to control when a linking function should be called during the linking phase. See info about pre-linking and post-linking functions below.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.