我很难理解指令中传递的指令属性 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.type
或attributes.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.type
为undefined
的原因。想知道为什么..
答案 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。