13

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
4
  • Where does user_role come from? Commented Oct 16, 2014 at 6:15
  • Its from controller scope. I'll set in controller: $scope.user_role=1; Commented Oct 16, 2014 at 6:16
  • Do you expect template to change dynamically if user_role changes? Or you want to load proper template just once at the beginning Commented Oct 16, 2014 at 6:18
  • Exactly I want the template to change dynamically if user_role changes. Commented Oct 16, 2014 at 6:19

4 Answers 4

15

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>

Sign up to request clarification or add additional context in comments.

4 Comments

This doesn't actually work; the attrs.userRole is passed in the "{{userRole}}" string directly, and not the actual value.
This will not work because scope is not evaluated yet and is not available too.
Did u try this before you put it as the answer, I am pretty sure this won't work with binded values.
@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).
8

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

1 Comment

the first one is the best answer.. but i used rootscope to watch a variable that refresh the dynamic template url with the object
3

Why not do:

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

then:

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

4 Comments

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.
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?
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.
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?
1

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) {
      ....
    }
  };
});

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.