2014-12-01 179 views
1

我有以下代码:隔离范围

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>

说明:

  • 我创造了该指令的隔离范围,具有双向 绑定到父作用域的对象(parentObject.childObject)。
  • 单击该按钮时,将在 myController中调用changeChild函数。该函数将替换 $ scope.parentObject.childObject与另一个孩子,并将 广播一个事件。
  • 此事件的监听者位于指令的控制器中。在 侦听器中,我们检查隔离范围($ scope.child)中的子项是否与在事件中发送的子项(即父项的scope.parentObject.childObject)相同的子项是 。 我们看到他们不一样,这意味着我们在 收到的孩子的隔离范围尚未更新。

请注意,如果我在广播前使用$ scope。$ apply(),那么指令控制器中的$ scope.child将被更新,但是它会抛出以下异常:“$ apply already in进展”。

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

谢谢

回答

0

您可以使用$超时旁边调用更新child.id后消化周期

请参阅下面的演示

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>

+0

谢谢你,这确实解决了这个问题。 我是js和AngularJs的新手,你能解释为什么这个解决方案有效吗? 这是这种情况下的最佳做法吗? (对不起,我不能投票了,我也是一个stackoverflow新手...) – user2051749 2014-12-02 08:18:12

+0

@ user2051749在你播放newChild的例子中,angularjs在摘要循环期间,newChild没有更新bo,你需要调用另一个摘要循环来brodcast新值(http://stackoverflow.com/questions/16066239/defer-angularjs-watch-execution-after-digest-raising-dom-event)。我宁愿使用$ watch指令而不是$ broadcast请参阅http://jsbin.com/nibopa/1/edit – sylwester 2014-12-02 09:30:53

+0

感谢您的解释。在提交问题之前,我尝试使用$ watch,但我在newValue和oldValue中都收到了“undefined”。不知道为什么,因为你的例子(jsbin.com/nibopa/1/edit)完美工作,代码似乎与我的一样... :( )当我看到以下帖子后,我试图使用$广播,而不是: http://www.benlesh.com/2013/10/title.html – user2051749 2014-12-02 09:48:35