动态模板和范围变量

时间:2014-10-03 10:07:45

标签: javascript angularjs angularjs-directive angularjs-scope

我很难理解指令中传递的指令属性 vs 范围变量
我正在制定一个指令,根据内容类型动态加载正确的模板。 当我使用linker函数使用范围变量来执行切换时,工作正常。

如果我使用:

<mydirective ng-repeat="item in items" content="item" type="item.type"></mydirective>

我传递了一个content对象,其中包含用于填充模板的数据,在此对象中,我有一个type属性,用于选择模板。
这是我的指令定义(省略了一些代码):

//[...]
linker = function(scope, element, attrs){
    //templates is a service I use to retrieve the templates
    loaderPromise = templates.getTemplate(scope.content.type)
    promise = loaderPromise.success(function(html){
        element.html(html)
    }).then(function(response){
        element.replaceWith($compile(element.html())(scope))
    })
}

return {
    restrict : "E",
    replace: true,
    scope: {
        'content': "="
    },
    link : function(scope, element, attributes){
        linker(scope, element, attributes)
    }
    //[...]
}

现在,我想把一个函数传递给'templateUrl',而不是这样:

return {
    restrict : "E",
    replace: true,
    scope: {
        'content': "="
    },
    templateUrl : function(element, attributes) {
      // I don't access to the scope but only to the attributes
      attributes.$observe(attributes.content.type, function(value){
        if(value) {
          // templates is a service 
          return templates.getTemplateUrl(value.type)
        }
      })
    }
    //[...]
}

现在,这无效,我发现attributes.content.typeattributes.type。这些属性始终为undefined

我还尝试将type添加为传递给指令的范围变量:

scope: {
         'content': "="
         'type': '='
        }

但它仍然是undefined

所以基本上我对使用attributes vs使用variable scopes

感到困惑

修改

我想这与ng-repeat有关。如果我在行上设置断点

attributes.$observe(attributes.content.type, function(value){

我检查了attributes我得到的值

$$element: jQuery.fn.init[1]
$attr: Object
content: "item"
ngRepeat: ""item in items"

所以我猜content尚未评估,这就是attributes.content.typeundefined的原因。想知道为什么..

1 个答案:

答案 0 :(得分:2)

您的templates服务是同步还是异步? templateUrl函数必须返回一个代表Url的字符串,并且不支持返回一个promise(我必须在Plunker中测试它才能确定)。

如果它确实同步返回一个字符串,那么我不确定为什么attributes.type === undefined

以下作品:

templateUrl : function(element, attributes) {
   return attributes.type;
}

我尝试使用(稍微修改过一段版本)你的代码,它运行正常 - 这里是plunker

关于你的问题,当你实现单向时使用scope(即指令对值的变化作出反应)或双向绑定(即指令作出反应并且可以更改父级中的值)范围)。使用属性作为初始化值。

修改 我现在更好地理解这个问题。这里有一些事情:

1 应该插入分配给type属性的值(即在花括号内):

<mydirective ng-repeat="item in items" content="item.content" type="{{item.type}}"></mydirective>

因为您需要插值字符串值,而不是对象(除非在范围定义中将其定义为"=type",否则您也不会获得该对象。)

2 遗憾的是,templateUrl函数中仍会出现问题,这与ng-repeat无关。这是因为这些值尚未在templateUrl函数或compile函数中进行插值,因此您将获得&#34; {{item.type}}&#34;作为字符串。使用$interpolate服务也没有帮助,因为您还没有适当的范围。

解决此问题的一种方法是在指向您请求的模板的链接功能中附加$compile <div ng-include>

link: function(scope, elem, attr){
    var template = attr.type || "template1";
    var templateUrl = template + ".html";
    elem.append("<div ng-include='\"" + templateUrl + "\"'></ng-include>");

    $compile(elem.contents())(scope);
},

这里是完整的plunker