Angularjs& dialog jQueryui - 仅在对话框关闭后更改{{msg}}

时间:2015-05-25 20:17:41

标签: angularjs jquery-ui

我在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>

有人可以告诉我这里有什么问题以及为什么会这样做?

谢谢!

1 个答案:

答案 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" );
      });
   });
}