What Im trying to accomplish: I have jQuery plugin that I want to wrap to be an angular directive. And to do this i need to pass params to it, and the plugin have it own
onchange `即使在我试图更改传递值的情况下,它也会反映在原始范围中。我得到了一些非常出乎意料和奇怪的结果。这是第一小提琴:
http://jsfiddle.net/q1915b38/2/
在这里,我试图模拟我想要完成的事情的最小示例。但正如你所看到的,它根本不起作用。原始控制器作用域中的值不变。但在现实世界中,它的行为有点不同。第二把小提琴来了。
http://jsfiddle.net/ne5hbgxp/
与第一个相比,我唯一改变的是模板与模板:
template: "<input type='text' id='blah' />",
至
template: "<input type='text' id='blah' ng-model='abc' />",
基本上,我在模板中添加了一个ng-model
属性,我在任何地方都不使用它。但它只是从完全不起作用变成了出现故障。现在,当更改第一次触发时,什么也没发生。但当它触发第二次时,先前更改的值被传递到原始范围中。当我更改3个时间值时,第二次的值会进入控制器。等等。所以基本上它有一个延迟,因为我不知道的原因后退了一步。这正是我在现实世界中遇到的行为,尽管根本没有ng-model
,所有内容都是通过jQuery插件生成的。
所以基本上我的问题如下:
1) 为什么它在第一个例子中不起作用
2) 为什么它在第二个例子中用这种一步延迟的奇怪行为工作?这种行为的逻辑是什么?
3) 解决这个问题的正确方法是什么?
由于您使用jQuery来更新指令中的某些内容,因此需要调用$apply()
来触发角度摘要周期
link: function(scope, iElement, iAttrs, controller) {
$('#blah').change(function() {
scope.value = $(this).val();
scope.$apply();
});
}
JSFiddle链接
然而,仔细观察一下,在这个例子中,您喜欢jQuery.change()
是有原因的吗?Angular提供了ngChange,这可能正是您想要的,因为您将从显式调用摘要循环中解脱出来,因为我们在Angular世界中,而不是与jQuery作战。一个例子可能包括。。。
<input type='text' id='blah' ng-model='abc' ng-change='update()'/>
scope.update = function() {
scope.value = scope.abc;
}
带ng-change
的JSFiddle链路
问题很简单。。。在angular的核心指令之外更改范围的事件对angular不可见,因此您需要通知angular执行摘要,以便更新视图。
这是用$apply()
完成的,或者可以使用$timeout()
来防止在另一个摘要循环进行时调用$apply()
link: function (scope, iElement, iAttrs, controller) {
$('#blah').change(function () {
var $el =$(this);
scope.$apply(function () {
scope.value = $el.val();
})
});
}
我建议利用指令中暴露的iElement
。当jQuery包含在角度之前的页面中时,这是一个jQuery对象