I've put together a plunker that best illustrates my issue.
I'm attempting to write a simple directive that will update the transcluded html from a directive.
For example I would like to have:
<make-bold>Foo *bar* {{something}}</make-bold>
Generate into
<span>Foo <b>bar</b> somevalue<span>
The example on plunker works fine, but I can't figure out how to get notifications (watch) of the transcluded content changing. In the example, try selecting different items (by clicking on them), and you'll notice "Processed" does not update.
I'm pretty sure the issue is that the element passed to the link function does not update, but it's content updates, thus it can't be watched.
Directive
app.directive('makeBold', function($interpolate, $timeout, $compile)
{
var regex = new RegExp("\\*(.+?)\\*", 'g');
var replace = "<b>$1</b>";
return {
restrict: 'E',
transclude: true,
replace: true,
template: '<span ng-transclude></span>',
link: function (scope, element, attrs)
{
scope.$watch(
function() {
// *** What do I need to watch here? ***
return element;
},
function(n, o) {
var text = $interpolate(element.text())(scope);
var newContent = text.replace(regex, replace);
$timeout(function() { element.html(newContent); });
});
}
};
});
Template
<div ng-show="selected">
<h1>{{selected.name}}</h1>
<p><i>Original:</i> {{selected.detail}}</p>
<p><i>Processed:</i> <make-bold>{{selected.detail}}</make-bold></p>
</div>
(Note: I don't actually want to make a 'make-bold' directive, but this illustrates the issues I am having.)
here is a working plunker
This one was not obvious and very challenging. I had to look inside angular.js source code to fully understand where transcluded contents live and what angular doing with interpolated text.
The trick here is to disable angular interpolation and use $interpolate manually.
addTextInterpolateDirective function inside compile.js is responsible for the magic binding of interpolation ( {{ }} ).
Later, I will update this answer with detailed explanation.
app.directive('makeBold', function( $interpolate ) {
var regex = new RegExp("\\*(.+?)\\*", 'g');
var replace = "<b>$1</b>";
return {
restrict: 'E',
scope: true,
compile: function (tElem, tAttrs) {
var interpolateFn = $interpolate(tElem.html(), true);
tElem.empty(); // disable automatic intepolation bindings
return function(scope, elem, attrs){
scope.$watch(interpolateFn, function (value) {
var newContent = value.replace(regex, replace);
elem.html(newContent);
});
}
}
};
});
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