隔离范围未更新

时间:2014-12-01 21:36:18

标签: javascript angularjs scope directive

我有以下代码:



var testApp = angular.module('testApp', []);

testApp.directive('myDirective', function () {
    return {
        scope: {
            child: '=child'
        },
        
        controller: function ($scope, $element, $attrs) {
            $scope.$on('childChanged', function (event, newChild) {
                if ($scope.child.id != newChild.id) {
                    alert("The child in the isolated scope is not updated!");
                }
                else {
                    alert("success");                    
                }
            });
        }
    };
});

testApp.controller('myController', function ($scope) {
    $scope.parentObject = {childObject: {id:1}};
    $scope.changeChild = function changeChild()
    {
        var newChild = { id: $scope.parentObject.childObject.id + 1};
        $scope.parentObject.childObject = newChild;
        //$scope.$apply(); //This solves the problem
        $scope.$broadcast('childChanged', newChild);
    }
});

<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div data-ng-app="testApp">
    <div data-ng-controller="myController">        
        <div my-directive child="parentObject.childObject"></div>
        <button data-ng-click="changeChild()">Change Child</button>
    </div>
</div>
&#13;
&#13;
&#13;

说明:

  • 我正在为指令创建一个孤立的范围,具有双向 绑定到父作用域的对象(parentObject.childObject)。
  • 单击按钮时,将调用函数changeChild myController的。此功能将取代 $ scope.parentObject.childObject与另一个孩子,并将 广播活动。
  • 此事件的监听者位于指令的控制器中。在里面 监听器,我们检查孤立范围($ scope.child)中的子是否是 与事件中发送的一个相同(即父的scope.parentObject.childObject)。 我们看到他们不一样,这意味着我们收到的孩子 孤立的范围尚未更新。

请注意,如果我在广播之前使用$ scope。$ apply(),那么指令控制器中的$ scope.child将会更新,但是,它会抛出以下异常:&#34; $申请已在进行中&#34;。

有人可以帮我理解这里发生的事情吗?为什么$ scope。$应用帮助,即使它只是引发了一次重复?如何在不调用$ scope的情况下解决这个问题。$ apply? 我想知道是否有办法确保隔离范围中的绑定属性在父范围内更改后得到更新,而无需在事件中传递它。

谢谢

1 个答案:

答案 0 :(得分:0)

更新child.id后,您可以使用$ timeout来调用下一个摘要周期

请参阅下面的演示

var testApp = angular.module('testApp', []);

testApp.directive('myDirective', function() {
  return {
    scope: {
      child: '=child'
    },

    controller: function($scope, $element, $attrs) {
      $scope.$on('childChanged', function(event, newChild) {

        if ($scope.child.id != newChild.id) {
          alert("The child in the isolated scope is not updated?");
        } else {
          alert("success");
        }
      });

    }
  };
});

testApp.controller('myController', function($scope, $timeout) {
  $scope.parentObject = {
    childObject: {
      id: 1
    }
  };
  $scope.changeChild = function changeChild() {
    var newChild = {
      id: $scope.parentObject.childObject.id + 1
    };
    $scope.parentObject.childObject = newChild;

    $timeout(function() {
      $scope.$broadcast('childChanged', newChild);
    }, 0);
  }
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div data-ng-app="testApp">
  <div data-ng-controller="myController">
    <div my-directive child="parentObject.childObject"></div>
    <button data-ng-click="changeChild()">Change Child {{parentObject.childObject}}</button>
  </div>
</div>