Angularjs 您可以动态更改templateUrl吗?

Angularjs 您可以动态更改templateUrl吗?,angularjs,angularjs-directive,Angularjs,Angularjs Directive,是否可以通过在指令的作用域中传递值来动态更改templateUrl? 我想将数据传递给控制器,该控制器将根据从指令传递的数据呈现页面 可能是这样的: <div> <boom data="{{myData}}" /> </div> .directive('boom', function { return { restrict: 'E', transclude: true,

是否可以通过在指令的作用域中传递值来动态更改templateUrl? 我想将数据传递给控制器,该控制器将根据从指令传递的数据呈现页面

可能是这样的:

<div> 
   <boom data="{{myData}}" />
</div> 

.directive('boom', function {
        return {
            restrict: 'E',
            transclude: true,
            scope: 'isolate',
            locals: { data: 'bind' },
            templateUrl: "myTemplate({{boom}}})" // <- that of course won't work.
        }
    });

.指令('boom',功能{
返回{
限制:'E',
是的,
范围:'隔离',
局部变量:{data:'bind'},

templateUrl:“myTemplate({{boom}}})”/这是可能的,但是当要加载的模板依赖于某些范围数据时,您不能再使用指令的
templateUrl
属性,您将不得不使用较低级别的API,即
$http
$compile

大致上,您需要做的(仅在链接功能中可能)是使用
$http
(不要忘记涉及
$templateCache
!)检索模板的内容,然后“手动”编译模板的内容

这听起来可能需要做很多工作,但实际上相当简单。我建议您看看使用此模式的
ngInclude
指令

以下是此类指令的框架:

app.directive('boom', function($http, $templateCache, $compile, $parse) {
        return {
            restrict: 'E',
            link: function(scope , iElement, iAttrs) {                            
              var boom = $parse(iAttrs.data)(scope);
              $http.get('myTemplate'+boom, {cache: $templateCache}).success(function(tplContent){
                iElement.replaceWith($compile(tplContent)(scope));                
              });              
            } 
        }
    });
假设它将用作
。此处的工作按钮:


请注意,我已将属性评估从
{{{name}}
更改为属性解析,因为一个模板在开始时可能只应确定一次。

这是Angular版本1.1.4+中的一个新功能,我刚刚发现是否使用了当前的不稳定(1.1.5)您可以将函数传递到指令的模板url中。函数的第二个参数是attribute指令的值,如下所示

这是一个显示官方变化的链接

使用
partials/template1.html
作为

Html:


我对pkozlowski.opensource的答案做了一点修改

发件人:

致:

这对我很有用,而且可以使用

<boom data="{{myData}}" /> 


在指令中。

这是一个后续答案,解决了以前答案中的一些问题。值得注意的是,它只编译一次模板(如果您的页面上有很多这样的内容,这一点很重要,并且它会在链接模板后监视模板的更改。它还会将类和样式从原始元素复制到模板中(尽管在内部使用“replace:true”时不是非常优雅的方式)。与当前支持的将函数用于模板或templateUrl的方法不同,您可以使用范围信息来确定要加载的模板

.directive('boom', ['$http', '$templateCache', '$compile', function ($http, $templateCache, $compile) {
    //create a cache of compiled templates so we only compile templates a single time.
    var cache= {};
    return {
        restrict: 'E',
        scope: {
            Template: '&template'
        },
        link: function (scope, element, attrs) {
            //since we are replacing the element, and we may need to do it again, we need
            //to keep a reference to the element that is currently in the DOM
            var currentElement = element;
            var attach = function (template) {
                if (cache[template]) {
                    //use a cloneAttachFn so that the link function will clone the compiled elment instead of reusing it
                    cache[template](scope, function (e) {
                        //copy class and style
                        e.attr('class', element.attr('class'));
                        e.attr('style', element.attr('style'));
                        //replace the element currently in the DOM
                        currentElement.replaceWith(e);
                        //set e as the element currently in the dom
                        currentElement = e;
                    });
                }
                else {
                    $http.get('/pathtotemplates/' + template + '.html', {
                        cache: $templateCache
                    }).success(function (content) {
                        cache[template] = $compile(content);
                        attach(template);
                    }).error(function (err) {
                        //this is something specific to my implementation that could be customized
                        if (template != 'default') {
                            attach('default');
                        }
                        //do some generic hard coded template
                    });
                }
            };

            scope.$watch("Template()", function (v, o) {
                if (v != o) {
                    attach(v);
                }
            });
            scope.$on('$destroy', function(){
                currentElement.remove();
            });
        }
    };
} ])

这些答案很好,但不专业。有一种使用
模板url
的语法,我们不经常使用。它可以是一个返回url的函数。该函数有一些参数。如果您想要更多,这里有一篇很酷的文章

我也有类似的问题

返回{
限制:“AE”,
templateUrl:function(elm,attrs){return(attrs.scrolled='scrolled'?'parts/scrolled nav.php':'parts/nav.php'),

替换:正确,
此问题将通过ng解决,包括以下内容:

MyApp.directive('boom', function() {
    return {
      restrict: 'E',
      transclude: true,
      scope: 'isolate',
      locals: { data: 'bind' },
      templateUrl: '<div ng-include="templateUrl"></div>',
      link: function (scope) {
        function switchTemplate(temp) {
          if (temp == 'x')
          { scope.templateUrl = 'XTemplate.html' }
          else if (temp == 'y')
          { scope.templateUrl = 'YTemplate.html' }
        }
      }
    }
});
MyApp.directive('boom',function(){
返回{
限制:'E',
是的,
范围:'隔离',
局部变量:{data:'bind'},
templateUrl:“”,
链接:功能(范围){
功能开关模板(temp){
如果(温度='x')
{scope.templateUrl='XTemplate.html'}
否则,如果(温度='y')
{scope.templateUrl='YTemplate.html'}
}
}
}
});

在指令的link函数中使用任意temp参数调用switchTemplate函数。

是的,我正在尝试使用ngInclude,但找不到如何获取局部变量的值。在我的情况下如何获取
数据?我正在尝试attrs.data,但它返回
未定义的
提供了更多信息。我不确定您是否真的想要t使用属性插值,因为这意味着模板可以作为$digest循环的一部分动态更改。但是如果您真的想这样做,您必须$observe attributes。也解决了我的问题。谢谢!我使用的是angular 1.0.8,值得一提的是,
$compile
在未包含jQ时失败你无法想象我对此有多感激!我自己有一个(类似的)解决方案,但结合我的一个指令,它只编译了两次…太感谢了!参数是
(元素,属性)
感谢您找到上述Plnkr中的示例:。注意,这种方法不适用于Angular 1.0.8(如上所述),因为
iAttrs.data
有一个值(如果您记录
iAttrs
对象,可以看到该值),当你试图访问它时,它是未定义的。这不是核心问题。如果你真的创建了一个类似于OP的演示应用程序,你会发现你不能简单地将插值传递给指令的
templateURL
函数。这有助于ie my属性值在运行时发生变化,并且需要有di吗不同的模板url基于此。
var boom = scope.data.myData
<boom data="{{myData}}" /> 
.directive('boom', ['$http', '$templateCache', '$compile', function ($http, $templateCache, $compile) {
    //create a cache of compiled templates so we only compile templates a single time.
    var cache= {};
    return {
        restrict: 'E',
        scope: {
            Template: '&template'
        },
        link: function (scope, element, attrs) {
            //since we are replacing the element, and we may need to do it again, we need
            //to keep a reference to the element that is currently in the DOM
            var currentElement = element;
            var attach = function (template) {
                if (cache[template]) {
                    //use a cloneAttachFn so that the link function will clone the compiled elment instead of reusing it
                    cache[template](scope, function (e) {
                        //copy class and style
                        e.attr('class', element.attr('class'));
                        e.attr('style', element.attr('style'));
                        //replace the element currently in the DOM
                        currentElement.replaceWith(e);
                        //set e as the element currently in the dom
                        currentElement = e;
                    });
                }
                else {
                    $http.get('/pathtotemplates/' + template + '.html', {
                        cache: $templateCache
                    }).success(function (content) {
                        cache[template] = $compile(content);
                        attach(template);
                    }).error(function (err) {
                        //this is something specific to my implementation that could be customized
                        if (template != 'default') {
                            attach('default');
                        }
                        //do some generic hard coded template
                    });
                }
            };

            scope.$watch("Template()", function (v, o) {
                if (v != o) {
                    attach(v);
                }
            });
            scope.$on('$destroy', function(){
                currentElement.remove();
            });
        }
    };
} ])
MyApp.directive('boom', function() {
    return {
      restrict: 'E',
      transclude: true,
      scope: 'isolate',
      locals: { data: 'bind' },
      templateUrl: '<div ng-include="templateUrl"></div>',
      link: function (scope) {
        function switchTemplate(temp) {
          if (temp == 'x')
          { scope.templateUrl = 'XTemplate.html' }
          else if (temp == 'y')
          { scope.templateUrl = 'YTemplate.html' }
        }
      }
    }
});