我在angularjs指令中创建了一个jQueryui对话框。
该指令的模板非常简单:
<div class="myPopup">
<div>{{msg}}</div>
</div>
在指令的link方法中,我创建了对话框并在openPopup事件上注册:
link: function (scope, element) {
var popupEl = $(element).find('.myPopup');
popupEl.dialog({ ... });
scope.$on('openPopup', function (event, args) {
scope.msg = "MY_MSG";
popupEl.dialog( "open" );
});
}
请注意我填充 scope.msg 变量。
当弹出窗口打开时,我看不到我的消息。
我查看了DOM并发现当弹出窗口打开时,{{msg}}为空:
<div class="myPopup">
<div></div>
</div>
但是当我关闭弹出窗口时,DOM发生了变化,msg变为scope.msg:
<div class="myPopup">
<div>MY_MSG</div>
</div>
有人可以告诉我这里有什么问题以及为什么会这样做?
谢谢!
答案 0 :(得分:0)
正如您所注意到,在更改scope.$apply()
后添加scope.msg
时,值已正确更新,但您获得了$apply already in progress
的例外情况。
If you read this article它解释了为什么需要使用$scope.$apply()
方法。基本上AngularJS会监视范围内数据的更改,然后它会通过一个过程来通知代码中关心这些更改的部分。但是,有时您的代码的一部分会在此过程正在通知的过程中运行,如果发生这种情况并且您的代码对范围进行了更改,那么直到稍后才能看到它 - 这就是为什么您只看到消息更新的原因当对话框关闭时。
因此您需要手动触发$scope.$apply
。有时这可能只是在您进行更改后调用该命令,但有时它会发生冲突并抛出“进行中”异常。
解决方案是使用applyAsync
method,它会将您的代码排入队列以在下一个摘要周期中运行;这通常是在大约10毫秒的延迟之后。
link: function (scope, element) {
var popupEl = $(element).find('.myPopup');
popupEl.dialog({ ... });
scope.$on('openPopup', function (event, args) {
// Trigger the change in the next digest cycle
scope.$applyAsync(function() {
scope.msg = "MY_MSG";
popupEl.dialog( "open" );
});
});
}