I'm trying to construct a sentence in an AngularJS view. For example, with variables {overdue: 5, name: "Kasper"}
, I would like to have "{{overdue}} days overdue. Employee: {{name}}"
.
I tried using a function:
function renderLine() {
var results = new Array();
if (overdue) {
result.push("{{overdue}} days overdue");
}
if (overdue) {
result.push("{{points}} points");
}
/* combine into a string */
var result = "";
for (var i = 0; i < results.length; i+=1) {
if (result.length != 0) {
result += ", ";
}
result += results[i];
}
if (result.length > 0) {
result += ". ";
}
/* add name */
result += "Name: {{name}}";
return result,
}
More specifically, my question is: how can I use angular directives like {{variable}} in strings that are constructed programmatically and have angular process the directives? I don't want to construct the strings without using directives because the strings are translated into different languages, where the placing of variables within sentences might change.
I ended up creating an angular directive. The ui-if
and ngRepeat
directives were good starting points for a DOM-manipulating directive. There is the code for the somewhat modified directive:
angular.module("hk").directive("myDirective",
[ "$interpolate", "$log",
function($interpolate, $log) {
return {
transclude: 'element',
replace: false,
restrict: 'A',
terminal: true,
compile: function(tElement, tAttrs, linker) {
return function(scope, elem, attr) {
var lastElement;
var lastScope;
var expression = attr.myDirective;
scope.$watch(expression, function (item) {
if (lastElement) {
lastElement.remove();
lastElement = null;
}
if (lastScope) {
lastScope.$destroy();
lastScope = null;
}
lastScope = scope.$new();
lastScope.item = item;
linker(lastScope, function (clone) {
lastElement = clone;
var results = [];
if (item.isactive) {
results.push("++{{item.createdtime | age}} active");
if (item.status == 'started') {
results.push("++{{item.startedtime | age}} started: {{item.startedby_displayname}}");
}
}
if (item.islate) {
results.push("++{{item.latetime | age}} past due");
}
var result = "";
for (var i = 0; i < results.length; i+=1) {
if (result.length != 0) {
result += ", ";
}
result += results[i];
}
if (result.length > 0) {
result += ". ";
}
if (!item.startedby_displayname) {
if (item.assignedto_displayname) {
result += "++Assigned to {{item.assignedto_displayname}}.";
}
}
var interpolated = $interpolate(result)(lastScope);
elem.after(interpolated);
});
});
};
}
};
}]);
I think you could use $scope.$eval
for your purposes. See this fiddle
In you could create a message like this:
$scope.$eval('"Hello "+name');
And then let the string to be evaluated change per language.
{de: '"Hallo " + name', it: '"Buon giorno "+ name', fr: '"Salut " +name'}
Or something along those lines (of course you'll want to have those translations checked).
You could also create a directive and use $compile to keep the exact strings you have now working.