Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to conditionally apply a template via custom Angular directives?

DEMO

Consider the following directive:

angular.module('MyApp').directive('maybeLink', function() {   return {     replace: true,     scope: {       maybeLink: '=',       maybeLinkText: '='     },     template: '<span>' +                '  <span ng-hide="maybeLink" ng-bind-html="text"></span>' +               '  <a ng-show="maybeLink" href="#" ng-bind-html="text"></a>' +               '</span>',     controller: function($scope) {       $scope.text = $scope.maybeLinkText.replace(/\n/g, '<br>');     }   };  }); 

The directive adds both the <span> and the <a> to the DOM (only one is visible at a time).

How could I rewrite the directive such that it will add either <span> or <a> to the DOM, but not both?


UPDATE

OK, I guess I could use ng-if like that:

template: '<span>' +            '  <span ng-if="!maybeLink" ng-bind-html="text"></span>' +           '  <a ng-if="maybeLink" href="#" ng-bind-html="text"></a>' +           '</span>' 

But, how could one get rid of the surrounding <span> in this case?


UPDATE 2

Here is a version of the directive that uses $compile. It doesn't have the surrounding <span>, but the two way data binding doesn't work either. I'm really interested to know how to fix the two way data binding issue. Any ideas?

DEMO

angular.module('MyApp').directive('maybeLink', function($compile) {   return {     scope: {       maybeLink: '=',       maybeLinkText: '='     },     link: function(scope, element, attrs) {       scope.text = scope.maybeLinkText.replace(/\n/g, '<br>');        if (scope.maybeLink) {         element.replaceWith($compile('<a href="#" ng-bind-html="text"></a>')(scope));       } else {         element.replaceWith($compile('<span ng-bind-html="text"></span>')(scope));         }      }    };  }); 
like image 631
Misha Moroshko Avatar asked Sep 19 '13 10:09

Misha Moroshko


People also ask

How do you do a conditional directive?

Currently, there is NO way to conditionally apply a directive to a component. This is not supported. The components which you have created can be added or removed conditionally. There is already an issue created for the same with angular2 , so it should be the case with angular4 aswell.

Can a directive have a template in Angular?

Components are directives with templates. The only difference between Components and the other two types of directives is the Template. Attribute and Structural Directives don't have Templates. So, we can say that the Component is a cleaner version of the Directive with a template, which is easier to use.

Which of the following templates can be used to write Angular directives?

Answer: C is the correct option. The ng-app directive is used to initialize the AngularJS application. The ng-init directive is used to initialize the application data.


2 Answers

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,     //...   };  }); 
like image 69
Behrang Avatar answered Nov 09 '22 20:11

Behrang


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';     }   }; }) 
like image 34
yohairosen Avatar answered Nov 09 '22 20:11

yohairosen