DEMO
Consider the following directive:
angular.module(\'MyApp\').directive(\'maybeLink\', function() {
return {
replace: true,
s
I think this is the cleanest way to inject a dynamic template based on a scope property
angular.module('app')
.directive('dynamic-template', function () {
return {
template:'<ng-include src="template"/>',
restrict: 'E',
link: function postLink(scope) {
scope.template = 'views/dynamic-'+scope.type+'.html';
}
};
})
You can use ng-if for the same
Below is the working example
Working Demo
Directive Code:
angular.module('MyApp').directive('maybeLink', function() {
return {
replace: true,
scope: {
maybeLink: '=',
maybeLinkText: '='
},
template: '<span>' +
' <span ng-if="!maybeLink.link" ng-bind-html="text"></span>' +
' <a ng-if="maybeLink.link" href="#" ng-bind-html="text"></a>' +
'</span>',
controller: function($scope) {
$scope.text = $scope.maybeLinkText.replace(/\n/g, '<br>');
}
};
});
The following is a solution that provides dynamic updates. Usage:
<a rewrite-as-span="true"></a>
<a rewrite-as-span="false"></a>
<a rewrite-as-span="yourFn()"></a>
etc.
app.directive('rewriteAsSpan', function($compile){
return {
restrict: 'A',
template: '<span />',
replace: true,
// we transclude the element because when it gets replaced with the span
// we want all the properties from the original element
transclude: 'element',
compile: function(tElement, tAttrs){
return {
post: function(scope, element, attrs, controller, transclude){
var rewrittenEl, originalEl;
transclude(scope, function(clone){
originalEl = clone;
});
scope.$watch(attrs.rewriteAsSpan, function(value){
if (value === undefined || value === true){
if (!rewrittenEl){
// lazy compile and cache the rewritten element
transclude(scope, function(clone){
rewrittenEl = tElement;
rewrittenEl.html(clone.html());
// remove this directive because the $compile would get infinite
rewrittenEl.removeAttr('rewrite-as-span');
$compile(rewrittenEl)(scope);
});
}
element.replaceWith(rewrittenEl);
element = rewrittenEl;
} else {
element.replaceWith(originalEl);
element = originalEl;
}
});
}
};
}
};
});
Code and specs as a gist
I came up with the following version at the end:
angular.module('MyApp').directive('maybeLink', function($compile) {
return {
scope: {
maybeLink: '=',
maybeLinkText: '='
},
link: function(scope, element, attrs) {
scope.$watch('maybeLinkText', function(newText) {
scope.text = newText.replace(/\n/g, '<br>');
});
scope.$watch('maybeLink', function() {
var newElement;
if (scope.maybeLink) {
newElement = $compile('<a href="#" ng-bind-html="text"></a>')(scope);
} else {
newElement = $compile('<span ng-bind-html="text"></span>')(scope);
}
element.replaceWith(newElement); // Replace the DOM
element = newElement; // Replace the 'element' reference
});
}
};
});
You might be able to use a template
function. According to the docs:
You can specify template as a string representing the template or as a function which takes two arguments tElement and tAttrs (described in the compile function api below) and returns a string value representing the template.
function resolveTemplate(tElement, tAttrs) {
}
angular.module('MyApp').directive('maybeLink', function() {
return {
//...
template: resolveTemplate,
//...
};
});
I would use ng-switch
.
something like
template: '<span ng-switch on="maybeLink">' +
' <span ng-switch-when="http://www.yahoo.com" ng-bind-html="text"></span>' +
' <a ng-switch-when="http://google.com" href="#" ng-bind-html="text"></a>' +
'</span>',
or
template: '<span ng-switch on="maybeLink">' +
' <span ng-switch-when={{maybeLink.length == 0}} ng-bind-html="text"></span>' +
' <a ng-switch-when={{maybeLink.length > 0}} href="#" ng-bind-html="text"></a>' +
'</span>',
So this is direction
Plunker