ng-repeat 中的自定义指令:为什么 ng-style 不适用?
Custom directive in ng-repeat: Why does ng-style not apply?
我有一个自定义指令 myItems
,它通过 ng-repeat
:
使用另一个指令 myItem
呈现项目列表
app.directive('myItems', function() {
return {
scope:{items:"="},
restrict:"E",
template:"<div my-item ng-repeat='item in items'></div>"
};
});
每个项目都包含用于设置元素样式的信息(例如颜色)。如果我使用模板方法,到目前为止效果很好:
app.directive('myItem', function() {
return {
restrict:"A",
template:"<div ng-style='{color:item.color}'>myItem: {{item.name}}</div>",
replace:true
};
});
为了支持更多涉及的功能,如果 my-item
我现在想通过手动创建所有需要的东西来重建相同的功能,包括 ng-style:
app.directive('myItem', function($compile) {
return {
restrict:"A",
compile: function(element) {
element.removeAttr('my-item');
element.text('myItem: {{item.name}}');
element.attr('ng-style', '{color:item.color}'); // Why does it have no effect?
var compileElement = $compile(element);
return function link(scope, elem, attr) {
compileElement(scope); // Why does binding with {{item.name}} even work without this statement?
};
}
};
});
有趣的是,使用 {{item.name}}
的数据绑定有效,而 ng-style
无效。
这里 fiddle 显示了上述两种方法。
我知道similar question。但我认为它在这里不适用,因为我没有关于 my-item
指令范围的明确声明。
编译函数有一个问题:在 Angular 具有 "parsed" 元素之后,它会针对元素的指令调用。这意味着 从 compile()
函数的代码添加到包含正在编译的指令的元素的任何指令 将不会被 Angular 解析! 这就是 element.attr('ng-style', '{color:item.color}');
被忽略的原因。
另一方面,compileElement(scope);
是多余的; 在包含正在编译的指令的元素内完成的任何DOM操作,将被Angular解析。
你能做什么?你的情况很简单,用手表添加样式是一个微不足道的DOM操作(即使没有手表,如果你不希望颜色发生变化):
return function link(scope, elem, attr) {
scope.$watch('item.color', function(newval) {
elem.css('color', newval);
});
};
调用 compileElement
确实编译了 ng-style 元素,但是因为 $compile
在元素完全构造之前被调用,所以调用 compileElement
对元素的无效版本起作用并且ng-style 没有改变颜色。
因此您可以将 $compile
移动到 link 函数中:
var compileElement = $compile(elem);
compileElement(scope);
但随后它又重新编译了 ng-repeat 指令,这是不好的。因此,您还需要删除该属性:
element.removeAttr('ng-repeat');
检查this plunker。
我有一个自定义指令 myItems
,它通过 ng-repeat
:
myItem
呈现项目列表
app.directive('myItems', function() {
return {
scope:{items:"="},
restrict:"E",
template:"<div my-item ng-repeat='item in items'></div>"
};
});
每个项目都包含用于设置元素样式的信息(例如颜色)。如果我使用模板方法,到目前为止效果很好:
app.directive('myItem', function() {
return {
restrict:"A",
template:"<div ng-style='{color:item.color}'>myItem: {{item.name}}</div>",
replace:true
};
});
为了支持更多涉及的功能,如果 my-item
我现在想通过手动创建所有需要的东西来重建相同的功能,包括 ng-style:
app.directive('myItem', function($compile) {
return {
restrict:"A",
compile: function(element) {
element.removeAttr('my-item');
element.text('myItem: {{item.name}}');
element.attr('ng-style', '{color:item.color}'); // Why does it have no effect?
var compileElement = $compile(element);
return function link(scope, elem, attr) {
compileElement(scope); // Why does binding with {{item.name}} even work without this statement?
};
}
};
});
有趣的是,使用 {{item.name}}
的数据绑定有效,而 ng-style
无效。
这里 fiddle 显示了上述两种方法。
我知道similar question。但我认为它在这里不适用,因为我没有关于 my-item
指令范围的明确声明。
编译函数有一个问题:在 Angular 具有 "parsed" 元素之后,它会针对元素的指令调用。这意味着 从 compile()
函数的代码添加到包含正在编译的指令的元素的任何指令 将不会被 Angular 解析! 这就是 element.attr('ng-style', '{color:item.color}');
被忽略的原因。
另一方面,compileElement(scope);
是多余的; 在包含正在编译的指令的元素内完成的任何DOM操作,将被Angular解析。
你能做什么?你的情况很简单,用手表添加样式是一个微不足道的DOM操作(即使没有手表,如果你不希望颜色发生变化):
return function link(scope, elem, attr) {
scope.$watch('item.color', function(newval) {
elem.css('color', newval);
});
};
调用 compileElement
确实编译了 ng-style 元素,但是因为 $compile
在元素完全构造之前被调用,所以调用 compileElement
对元素的无效版本起作用并且ng-style 没有改变颜色。
因此您可以将 $compile
移动到 link 函数中:
var compileElement = $compile(elem);
compileElement(scope);
但随后它又重新编译了 ng-repeat 指令,这是不好的。因此,您还需要删除该属性:
element.removeAttr('ng-repeat');
检查this plunker。