The cleanest way would be to use the transclude
parameter in the link
function of the directive, as stated here (Transclusions and Scopes by Jesus Rodriguez.
A snippet taken from the source:
.directive('person', function() {
return {
restrict: 'EA',
scope: {
header: '='
},
transclude:true,
link: function(scope, element, attrs, ctrl, transclude) {
scope.person = {
name: 'Directive Joe',
profession: 'Scope guy'
};
scope.header = 'Directive\'s header';
transclude(scope, function(clone, scope) {
element.append(clone);
});
}
};
});
the transclude function receives a function and an optional first parameter. What this function does is to clone the transcluded html and then you can do with it what you want. If you put a scope as the first parameter, that scope will be the one used on the cloned element. The callback function of transclude will receive the cloned DOM and also the scope attached to it.
In this case, we are using the directive’s parent scope (in this case the controller’s one) as the scope of the transcluded html and then we are receiving it in the callback function. What we do here is just append it on our directive’s DOM element. In the case we had a template on the directive, we could retrieve a DOM element and then use it to append the transcluded html, that is what I call complete control :)
Also, transclude
d elements are appended to the directive, inheriting the parent's $scope
instead of the directive's. More information can be found here