30

我有一个变量类型的指令 myDirective 。如果我运行,<my-directive type="X">我希望指令使用 templateUrl:x-template.html。如果我这样做,<my-directive type="Y">我希望指令使用 templateUrl:y-template.html。

这是我目前的指令。

app.directive('myDirective', function() {
    var myDirective = {
        templateUrl: 'X-template.html',
        restrict: 'E',
        scope: {
            type: '=' 
        },
    };
    return myDirective;
});

我阅读了 stackoverflow 和 angular 文档,但没有找到我需要的任何东西。

我现在正在尝试按照以下方式做一些事情:

if ($scope.type === 'X') {
    templateUrl: 'X-template.html',
}
else if ($scope.type === 'Y') {
    templateUrl: 'Y-template.html',
}

但不知道在哪里做。

你们知道这是否可能以及如何?

4

6 回答 6

103

Angular 将接受一个函数作为模板选项,因此您可以执行以下操作:

.directive('myDirective', function () {
    return {
        templateUrl: function (tElement, tAttrs) {
            if (tAttrs) {
                if (tAttrs.type === 'X') {
                    return 'X-template.html';
                }
                if (tAttrs.type === 'Y') {
                    return 'Y-template.html';
                }
            }
        }
    }
});

有关详细信息,请参阅$compile服务的文档。

于 2013-12-05T15:21:23.687 回答
25

您可以使用inside解决此问题ng-includecompile

app.directive('myDirective', function() {
    return {
        restrict: 'E',
        compile: function(element, attrs) {
            element.append('<div ng-include="\'' + attrs.type + '-template.html\'"></div>');
        }
    }
});

小提琴

于 2013-05-10T22:22:44.723 回答
7

如果您愿意通过 1.1.x 代码路径上的构建生活在最前沿(请注意每个 1.1.x 构建说明条目附带的警告,因此我不会通过在此处再次重复来稀释此答案),您'很幸运——这个功能刚刚在 4 月 3 日的 1.1.4 版本中添加。您可以在此处找到 1.1.4 的发行说明,该功能的任务日志包含一个演示如何使用新功能的 Jasmine 测试。

如果您比较保守并且使用的是 1.0.x 版本,那么您将无法轻松完成此操作,但可以完成。Mark Rajcok 的解决方案看起来符合您的要求,但我只想添加一些额外的注释:

  • 除了 1.1.4 版本之外,编译时指令不支持在运行时进行修改。
  • 您可能需要考虑replaceWith()不是append()因为<my-directive>不是标准定义的 HTML 元素类型。
  • 如果您的 X 和 Y 模板包含额外的指令,我认为您将无法<my-template>如此轻松地将属性传递给模板的根元素。
    • 带有 replace: true 的指令会将属性从源元素传输到其替换根,但我认为ngInclude从主机到包含模板的根不会这样做。
    • 我似乎还记得ngInclude不需要它的模板只有一个根元素。
    • 您也许可以通过使用replaceWith()而不是将标签append()包装在. 外部可以保存属性,并且在元素用加载的内容替换自身后仍然可以访问。<div ng-include=""><div></div><div><div ngInclude>
  • 请注意,这ngInclude会创建一个新范围。这会使您受到关于原始示波器模型危险的闪烁黄色喇叭的警告。有关更多信息,请参阅Angular 的 GitHub 仓库中的这个精美页面

我可以为 1.0.x 上的用户提出另一种替代方案,但它涉及大量代码。这是一个更重量级的操作,但它的好处是不仅可以在模板之间切换,还可以在完全成熟的指令之间切换。此外,它的行为更容易动态化。

app.directive('myDirective', function() {
    return {
        restrict: 'E',
        replace: true,
        templateUrl: 'partials/directive/my-directive.html',
        link: function(scope, element, attrs, ctrl) {
            // You can do this with isolated scope as well of course.
            scope.type = attrs.type;
        }
    }
);

我的directive.js

<div ng-switch on="{{type}}">
    <div ng-switch-where="X" ng-include="X-template.html"></div>
    <div ng-switch-where="Y" ng-include="Y-template.html"></div>
</div>

我的指令.html

于 2013-05-11T02:32:42.263 回答
5

这是我的版本,用于可选地覆盖默认模板

templateUrl: function (elem, attrs) {
  if (attrs.customTemplate) {
    return '/path/to/components/tmpl/' + attrs.customTemplate + '.html';
  } else {
    return '/path/to/components/tmpl/directive.html';
  }
}

例如在指令上

<div my-directive custom-template="custom"></div>
于 2016-04-14T09:04:18.223 回答
4

我这样解决这个问题:

app.directive("post", function ($templateCache, $compile) {
function getTemplate(mode) {
    switch (mode) {
        case "create":
            return "createPost.html";
        case "view":
            return "viewPost.html";
        case "delete":
            return "deletePost.html";
    }
}

var defaultMode = "view";

return {
    scope: {},
    restrict: "AE",
    compile: function (elem, attrs, transclude) {
        return function ($scope, $element, $attr) {
            function updateTemplate() {
                $element.html("");
                $compile($templateCache.get(getTemplate($scope.mode)).trim())($scope, function (clonedElement, scope) {
                    clonedElement.appendTo($element);

                });
            }

            $scope.mode = $attr.mode || defaultMode;

            $scope.$watch("mode", updateTemplate);
        }
    }
}
});

这可能不是最好的方法,但我没有额外的范围。

于 2013-10-23T12:17:47.597 回答
-1

好的,这可能会帮助这里的人:-)

要将您的自定义属性注入您的链接或控制器功能,请使用以下内容。

我现在正在工作,但如果有机会我会在稍后发布一个小提琴:-)

.directive('yourDirective', function() {
  return {
    restrict: 'EA',
    template: '<div></div>', // or use templateUrl with/without function
    scope: {
      myAttibute: '@myAttr' // adds myAttribute to the scope
    },
    link: function(scope) {
      console.log(scope.myAttibute);
    }
  }
}

// HTML ""

// 控制台将输出“foo”

于 2015-01-26T12:08:05.817 回答