AngularJS中指令之间的通信指令

3

我有这样一个过滤器指令:

app.directive('filter', function(){
  return {
    restrict: 'E',
    transclude: true,
    scope: {
        callFunc: '&'
    },
    template:
            '   <div>' +
            '       <div ng-transclude></div>' +
            '   </div>',
    controller: function($scope, $element, $attrs){
        this.getData = function() {
            $scope.callFunc()
        }
    }
  }   
});

app.directive('positions', function(){
  return {
    require: '^filter', 
    scope: {
        selectedPos: '='
    },
    template:
            '  Positions: {{selectedPos}}' +
            '  <ul>' +
            '   <li ng-repeat="pos in positions">' +
            '           <a href="#" ng-click="setPosition(pos); posRegData()">{{pos.name}}</a></a>' +
            '       </li>' +
            '  </ul>',
    controller: function($scope, $element, $attrs){
          $scope.positions = [
            {name: '1'},
            {name: '2'},
            {name: '3'},
            {name: '4'},
            {name: '5'}
          ];
          $scope.selectedPos = $scope.positions[0].name;
          $scope.setPosition = function(pos){
            $scope.selectedPos = pos.name;
          };

    },
    link: function(scope, element, attrs, filterCtrl) {
        scope.posRegData = function() {
            filterCtrl.getData();
        }
    }
  }   
})

还有控制器:

app.controller('keyCtrl', ['$scope', function($scope) {
  var key = this;
  key.callFunc = function() {
    key.value = key.selectedPos;
    console.log(key.selectedPos)
  }
}]);

主要问题是为什么控制器中的key.selectedPos只有在第二次点击时才获取正确的值?
这里有一个Plunker示例复制我的问题。
一种解决方法是在调用callFunc()时发送一个参数。然后,我在控制器中更新函数:key.callFunc = function(filterParams),同时,我也更新了传递的方法call-func="key.callFunc(filterParams)
然后,在filter指令中,我将getData方法更改为:
this.getData = function(val) {
  $scope.callFunc({filterParams: val})
}

positions directive 中,我传递需要的值:
scope.posRegData = function() {
  filterCtrl.getData({position: scope.selectedPos});
}

最后,在keyCtrl中,我是这样获取值的:
key.callFunc = function(filterParams) {
  key.value = filterParams.position;
  console.log(filterPrams.position)
}

这是一个展示这种尝试的plunker
在这种情况下,问题是这是否是一种好的做法,要记住它是在一个非常大的应用程序中。

1
如果你想在控制器或指令之间共享数据,使用服务几乎总是最佳选择。 - Bob Thomas
1个回答

3
这是因为隔离作用域的工作原理。父级作用域(在您的情况下是控制器)将在 digest cycle 运行时进行更新,这是在您的 ng-click 函数调用 callFunc 之后。所以,您可以将 callFunc 代码放在 $timeout 中,它会起作用(但会导致另一个 digest cycle)。
另一个解决方案是将值放入对象中,这样当您更改对象时,具有引用的控制器将立即看到更新:
在控制器中:
key.selectedPos = { value: {}};

key.callFunc = function() {
    key.value = key.selectedPos.value;  
    console.log(key.selectedPos.value)
} 

在这个指令中:
$scope.selectedPos.value = $scope.positions[0].name;
$scope.setPosition = function(pos){
    $scope.selectedPos.value = pos.name;
};

See this plunker.


我本来想谈论$scope.$apply(),但我知道这不是一个好的做法。感谢你提供的对象技巧,我会记住的。 - Okazari

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接