AngularJS指令动态设置模板URL

13

我正在创建一个具有模板URL的指令。我希望根据用户角色动态设置模板URL。有任何想法吗?

这是我的指令代码:

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

我希望您能够从控制器中设置用户角色。例如:

$scope.user_role = 1

user_role 来自哪里? - dfsq
这是控制器作用域的内容。我会在控制器中设置:$scope.user_role=1; - Sachin Prasad
你希望模板在用户角色更改时动态更改吗?还是你只想在开始时加载正确的模板? - dfsq
我希望模板能够在用户角色更改时动态更改。 - Sachin Prasad
4个回答

15

您可以将一个函数传递给templateUrl选项,并返回一个字符串,该字符串将被用作模板URL。

首先,将角色分配给元素作为属性(其中userRole绑定到作用域),如下所示:

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

然后指令可以将其解读为:

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

更新: 这在旧版Angular中曾经起作用。

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


16
这实际上是无效的,attrs.userRole直接传递到"{{userRole}}"字符串中,而不是实际值。 - RMD
1
这不会起作用,因为作用域尚未评估并且也不可用。 - Nitesh Kumar Anand
你在将其作为答案之前尝试过这个吗?我很确定这不适用于绑定的值。 - Mad
1
@Mad 正如我在更新中提到的,插值在最新版本的Angular中不起作用,但在2014年10月16日之前是有效的。 - codef0rmer

8
您可以将 ng-include 用作模板。 HTML:
<headermenu user-role="selectedUserRole"></headermenu>

JavaScript:
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>'
  };
});

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


或者如果您不想在控制器中设置完整路径:

html:

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

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

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

第一个是最佳答案。但我使用rootscope来监视一个变量,该变量使用对象刷新动态模板URL。 - mariomol

3

为什么不这样做:

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

然后:

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

好吧,如果没有其他办法,我就必须遵循这个方式,但是我还是得在控制器中设置完整路径。 - Sachin Prasad
你说的“必须在控制器中设置完整路径”是什么意思?你还有其他方法可以告诉Angular要使用哪个模板文件吗? - Ben Heymink
当我使用这个指令.directive.templateUrl时,我只需要设置模板的完整路径一次,在控制器中简单地传递用户角色,它将根据该用户角色动态选择。 - Sachin Prasad
抱歉,我可能漏掉了什么 - 我给你的片段恰好可以满足你的需求 - 它将根据提供给 $scope.user_role 的用户角色动态加载模板。如果您有其他要求,请在问题中提供更多解释。 - Ben Heymink

1
如果没有放入标记中,则不要放置它。
<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) {
      ....
    }
  };
});

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接