Is it possible to have embedded angular-js directives in translation values? I've been easily able to get embedded HTML to be show correctly by using the translate directive or service instead of the filter, and also getting dynamic values using the translate-directive with translate-value attributes.
I just ran into a problem where a translation item contained an embedded element marked with attributes for an angular popover library directive (such that the you can mouse over the word in the span and have a little tooltip pop-up) - while using the translate-filter properly applied the translated value to the page, when mousing over the span element nothing pops up; sure seems like the embedded popover directive is not active.
Example plunker - https://embed.plnkr.co/YJh8W9TgHknnqvXmBAym/
Is this not possible with angular-translate, or a shortcoming of the popover library we're currently using?
Thanks!
UPDATE 2016-08-09
Here is an update version that 1) allows the use of translate-value-* attributes, and 2) removes scope isolation so that translated values can reference scope items. An example use case of (2) is something like the following translation:
{ "KEY": "A sentence <a ng-click='doPopUp()'>that uses the controller scope.</a>" }
The updated directive is:
.directive("translateCompile", ['$compile', '$rootScope', '$translate', function($compile, $rootScope, $translate){
return{
restrict: 'A',
scope: false,
link: function(scope, element, attributes) {
function doCompile() {
var props = {}, key = '';
// Loop through the attributes of the element, looking for the key to use in translation as
// well as any translate-values to be passed along
angular.forEach(attributes, function(a,b) {
if (b.startsWith('translateValue')) {
// This normalize the translation property name to lowercase; if you expect
// to be able to use {{camelCase}} in translation replacements, you'll want to
// make this smarter about just lowercasing the first character.
props[b.replace('translateValue', '').toLowerCase()] = a;
}
else if (b == 'translateCompile') {
key = a;
}
});
// Wrap the contents in a span to make sure $compile will successfully operate
var txt = '<span>' + $translate.instant(key, props) + '</span>';
// Compile the translated content and set it as the element's HTML
$compile(txt)(scope, function(cloned, scope) {
element.empty();
element.append(cloned);
});
}
// Watch for translation changes, to regenerate
$rootScope.$on('$translateChangeSuccess', doCompile);
// Do initial compilation
doCompile();
}
}
}]);
ORIGINAL
So, after playing around for a few days, I've eventually settled on a modified version of implementing a "compile" directive that pops up around the web:
.directive("translateCompile", ['$compile', '$rootScope', '$translate', function($compile, $rootScope, $translate){
return{
restrict: 'A',
scope:{
translateCompile:'@'
},
link: function(scope, element, attributes) {
function doCompile() {
// Wrap the contents in a span to make sure $compile will successfully operate
var txt = "<span>" + $translate.instant(scope.translateCompile) + "</span>";
// Compile the translated content and set it at the element's HTML
$compile(txt)(scope, function(cloned, scope) {
element.html(cloned);
});
}
// Watch for translation changes, to regenerate
$rootScope.$on('$translateChangeSuccess', doCompile);
// Do initial compilation
doCompile();
}
}
}]);
... which allows it to be used such <h3 translate-compile="SOME_KEY"></h3>
. Not sure if it's possible to simplify this at all (or if I did a no-no somewhere), but so far seems to do the trick.