Consider a directive called myDirective in an element, and that element is enclosing some other content, let's say:
<div my-directive>
<button>some button</button>
<a href="#">and a link</a>
</div>
If myDirective is using a template, you'll see that the content of <div my-directive>
will be replaced by your directive template. So having:
app.directive('myDirective', function(){
return{
template: '<div class="something"> This is my directive content</div>'
}
});
will result in this render:
<div class="something"> This is my directive content</div>
Notice that the content of your original element <div my-directive>
will be lost (or better said, replaced). So, say good-bye to these buddies:
<button>some button</button>
<a href="#">and a link</a>
So, what if you want to keep your <button>...
and <a href>...
in the DOM? You'll need something called transclusion. The concept is pretty simple: Include the content from one place into another. So now your directive will look something like this:
app.directive('myDirective', function(){
return{
transclude: true,
template: '<div class="something"> This is my directive content</div> <ng-transclude></ng-transclude>'
}
});
This would render:
<div class="something"> This is my directive content
<button>some button</button>
<a href="#">and a link</a>
</div>.
In conclusion, you basically use transclude when you want to preserve the contents of an element when you're using a directive.
My code example is here.
You could also benefit from watching this.
Compile :
This is the phase where Angular actually compiles your directive. This compile function is called just once for each references to the given directive. For example, say you are using the ng-repeat directive. ng-repeat will have to look up the element it is attached to, extract the html fragment that it is attached to and create a template function.
If you have used HandleBars, underscore templates or equivalent, its like compiling their templates to extract out a template function. To this template function you pass data and the return value of that function is the html with the data in the right places.
The compilation phase is that step in Angular which returns the template function. This template function in angular is called the linking function.
Linking phase :
The linking phase is where you attach the data ( $scope ) to the linking function and it should return you the linked html. Since the directive also specifies where this html goes or what it changes, it is already good to go. This is the function where you want to make changes to the linked html, i.e the html that already has the data attached to it. In angular if you write code in the linking function its generally the post-link function (by default). It is kind of a callback that gets called after the linking function has linked the data with the template.
Controller :
The controller is a place where you put in some directive specific logic. This logic can go into the linking function as well, but then you would have to put that logic on the scope to make it "shareable". The problem with that is that you would then be corrupting the scope with your directives stuff which is not really something that is expected.
So what is the alternative if two Directives want to talk to each other / co-operate with each other? Ofcourse you could put all that logic into a service and then make both these directives depend on that service but that just brings in one more dependency. The alternative is to provide a Controller for this scope ( usually isolate scope ? ) and then this controller is injected into another directive when that directive "requires" the other one. See tabs and panes on the first page of angularjs.org for an example.
Best Answer
From AngularJS Documentation on Directives:
transclude: true
So let's say you have a directive called
my-transclude-true
declared withtransclude: true
that looks like this:After compiling and before linking this becomes:
The content (children) of
my-transclude-true
which is<span>{{ something }}</span> {{...
, is transcluded and available to the directive.transclude: 'element'
If you have a directive called
my-transclude-element
declared withtransclude: 'element'
that looks like this:After compiling and before linking this becomes:
Here, the whole element including its children are transcluded and made available to the directive.
What happens after linking?
That's up to your directive to do what it needs to do with the transclude function.
ngRepeat
usestransclude: 'element'
so that it can repeat the whole element and its children when the scope changes. However, if you only need to replace the tag and want to retain it's contents, you can usetransclude: true
with thengTransclude
directive which does this for you.