angularjs directive set template url dynamically

26,740

Solution 1

You can pass a function to the templateUrl option and return a string that will be used as a template url at the end.

First of all assign a role onto the element as an attribute (where userRole is bound to scope) as:

<div my-directive user-role="{{userRole}}></div>

Then the directive can read it as:

myApp.directive('myDirective', function() {
  return {
    restrict: 'A',
    templateUrl: function(element, attrs) {
      return "../assets/common/headerMenu" + attrs.userRole + ".html";
    }
  }
});

Update: This used to work before with older version of Angular.

<div ng-if="userRole === 'admin'" my-directive user-role="admin"></div>

Solution 2

you can manipulate ng-include as a template

html:

<headermenu user-role="selectedUserRole"></headermenu>

js:

app.directive('headermenu', function() {
  return {
    restrict: 'E',
    scope: {
      userRole : '='
    },
    link: function($scope)
    {
      $scope.$watch('userRole', function(userRole)
      {
        if (userRole && userRole.length)
        {
            $scope.dynamicTemplateUrl = 'assets/common/headerMenu' + userRole + '.html';
        }
      });
    },

    template: '<ng-include src="dynamicTemplateUrl"></ng-include>'
  };
});

demo: http://plnkr.co/edit/CCElZ317kYeZpa5ofmoo?p=preview


Or if you don't want to set the full path in the controller:

html:

<headermenu path="assets/common/headerMenu{{selectedUserRole}}.html"></headermenu>

js:

app.directive('headermenu', function() {
  return {
    restrict: 'E',
    scope: {
      path : '@'
    },
    template: '<ng-include src="path"></ng-include>'
  };
});

demo: http://plnkr.co/edit/HEyUUzv6jbjZCDDbAzPm?p=preview

Solution 3

Why not do:

template : '<div ng-include="getActualTemplateContent()"></div>'

then:

$scope.getActualTemplateContent= function() {
  return '../assets/common/headerMenu/' + $scope.user_role + '.html';
};

Solution 4

If not put it in the markup.

<div headermenu template="../assets/common/headerMenu{{user_role}}.html" />
<headermenu template="../assets/common/headerMenu{{user_role}}.html" />


angular.module("directives")
.directive("headermenu", function() {
  return {
    restrict: "EA",
    scope: true,
    templateUrl: function (element, attr) {
      return attr.template;
    },
    link: function(scope, iElement, iAttrs, controller) {
      ....
    }
  };
});
Share:
26,740
Sachin Prasad
Author by

Sachin Prasad

Senior ROR Developer

Updated on October 08, 2020

Comments

  • Sachin Prasad
    Sachin Prasad over 3 years

    I'm creating a directive with template URL. I want to set the template URL dynamically based on user_role. Any idea?

    Heres my directive code:

    RatingRX.directive "headermenu", ->
      directive = {}
      directive.restrict = 'E'
      directive.templateUrl = "../assets/common/headerMenu{{user_role}}.html"
      directive  
    

    And I want to set user_role from the controller. Eg:

    $scope.user_role = 1
    
  • Sachin Prasad
    Sachin Prasad over 9 years
    Well if theres no other way I'll have to follow this, but Again I'll have to set the full path in the controller.
  • Ben Heymink
    Ben Heymink over 9 years
    What do you mean you'll 'have to set the full path in the controller'? How else were you expecting to tell Angular which template file to use?
  • Sachin Prasad
    Sachin Prasad over 9 years
    When I use this: directive.templateUrl, I'll have to set the full path of the template only once and in the controller I'll simply pass the user role, and it will pick it dynamically, based on that user role.
  • Ben Heymink
    Ben Heymink over 9 years
    Sorry I must be missing something - the snippet I've given you does exactly what you want I think - it will load a template based on the user role provided to $scope.user_role, dynamically. If there is some other requirement you have, you need to update your question with a bit more explanation?
  • RMD
    RMD about 9 years
    This doesn't actually work; the attrs.userRole is passed in the "{{userRole}}" string directly, and not the actual value.
  • Nitesh Kumar Anand
    Nitesh Kumar Anand over 8 years
    This will not work because scope is not evaluated yet and is not available too.
  • mariomol
    mariomol about 8 years
    the first one is the best answer.. but i used rootscope to watch a variable that refresh the dynamic template url with the object
  • Mad
    Mad over 7 years
    Did u try this before you put it as the answer, I am pretty sure this won't work with binded values.
  • codef0rmer
    codef0rmer over 7 years
    @Mad As I mentioned in the updates, the interpolation will not work in the latest angular but it was working back then (answered Oct 16th 2014).