AngularJS指令不会更新回调范围

时间:2016-11-04 13:21:37

标签: angularjs angularjs-directive angularjs-scope

我正在使用指令在AngularJS 1.5中创建一个组件库。因此,我的指令需要有隔离范围。

我的一些指令有回调,所以你可以传入一个函数来被指令调用。但是,当指令调用该回调时,似乎对$ scope属性的更改不像我期望的那样完全更新。

这是一个显示此行为的Plunker: http://embed.plnkr.co/Rg15FHtHgCDExxOYNwNa/

代码如下所示:

<script>
    var app = angular.module('myApp', []);
    app.controller('Controller', ['$scope',function($scope) {
        // initialize the value to something obvious
        $scope.clickersValue = "BEFORE";

        // when this call back is called we would expect the value to be updated by updated by the directive
        $scope.clickersCallback = function() {
        //$scope.$apply(); // $apply is not allowed here
        $scope.clickersValueRightAfterCall = $scope.clickersValue;
        console.log("clickersCallback: scope.clickersValue", $scope.clickersValue);
    };
  }
]);

app.directive('clicker', [function() {
  return {
    restrict: 'EA',
    template: '<div ng-click="clicked()">click me!</div>',
    controller: ['$scope', function($scope) {
      $scope.clicked = function() {
        console.log("you clicked me.");
        $scope.newValue = 'VALID';
        $scope.myUpdate();
      }
    }],
    scope: {
      "newValue": "=",
      "myUpdate": "&"
    }
  };
}]);
</script>

因此,当调用clickersCallback时,clickersValue属性仍具有旧值。我已尝试使用$ scope。$ apply但当然发生另一次更新时不允许这样做。我也尝试过使用controller_bind但效果相同。

1 个答案:

答案 0 :(得分:3)

clickersCallback函数中的代码包装在$timeout函数中。

$timeout(function() {
    $scope.clickersValueRightAfterCall = $scope.clickersValue;
    console.log("clickersCallback: scope.clickersValue", $scope.clickersValue); 
});

Updated plunker

  

$ timeout不会产生“$ digest已在进行中”之类的错误,因为$ timeout告诉Angular在当前周期之后有超时等待,这样它确保了摘要周期之间不会发生任何冲突$ timeout的输出将在新的$ digest循环上执行。   source

编辑1:正如OP所说,指令的用户不必写任何&#34;特殊&#34;代码在他的回调函数中。

为了实现这种行为,我将$ timeout从de controller更改为指令。

控制器回调函数(无变更):

$scope.clickersCallback = function() {
    $scope.clickersValueRightAfterCall = $scope.clickersValue;
    console.log("clickersCallback: scope.clickersValue", $scope.clickersValue);
};

指令代码(在指令中注入$ timeout ):

 $scope.clicked = function() {
     console.log("you clicked me.");
     $scope.newValue = 'VALID';
     $timeout(function() {
         $scope.myUpdate();
     });
 }

Updated plunker