繁体   English   中英

如何在源范围AngularJS的上下文中从指令监视模型

[英]How to watch a model from a directive in the context of its source scope AngularJS

我需要从指令中观察模型。

angular.module('app', [])
.directive('myDirective', [function() {
    return {
       restrict: 'A',
       scope: {
          modelToWatch: '@'
       },
       link: function(scope, element, attrs) {
           scope.$watch(scope.modelToWatch, function(val) {
              // do something...
           });
       }
    };
]})

.controller('MyController', ['$scope', function($scope) {
    $scope.obj = {
       foo: 'val'
    };
}]);

<div ng-controller="MyController">
    <div my-directive model-to-watch="obj.foo"></div>        
</div>

以上工作正常。

但是,当模型的实际所有者与指令之间存在中间作用域时,我会遇到问题。

我使用另一个控制器来演示以下情况:

.controller('AnotherController', ['$scope', function($scope) {}])

<div ng-controller="MyController">
    <div ng-controller="AnotherController">
        <div my-directive model-to-watch="obj.foo"></div>
    </div>
</div>

在上述情况下,我可以使用下面的代码查找$ parent树以找到拥有我要监视的属性的范围:

...

link: function(scope, element, attrs) {
   var contextScope = scope;

   // find for the scope which owns the property that we want to watch
   while (contextScope != null && contextScope.hasOwnProperty(attrs.modelToWatch)) {
       contextScope = contextScope.$parent;
   }

   // use the scope found to watch the model
   if (contextScope != null) {
      contextScope.$watch(scope.modelToWatch, function(val) {
          // do something...
      });
   }
}

但是,另一个问题是,如果modelToWatch是一个复杂的表达式(例如:“ tableParams.filter()。shop_id”),则无法依赖hasOwnProperty。

有没有一种简单的方法可以在其所有者范围内查看模型? 还是有可能甚至从原型孩子那里观看模特儿?

或者我可以将范围作为参数传递,因此至少不必寻找它...

restrict: 'A',
scope: {
    modelToWatch: '@',
    sourceScope: '=', // don't know how to do this..
}

注意:我需要使用隔离范围

正如@pixelbit所建议的那样,我尝试使用$ eval查找正确的范围

link: function(scope, element, attrs) {
   var contextScope = scope;

   // find for the scope which owns the property that we want to watch
   while (contextScope != null && contextScope.$eval(attrs.modelToWatch) != undefined) {
       contextScope = contextScope.$parent;
   }

   ...
}

在大多数情况下都适用,除了modelToWatch表达式实际上计算为undefined时。在当前范围中不存在modelToWatch(意味着它不是所有者)还是modelToWatch表达式恰好计算为undefined时存在歧义。

不需要隔离的作用域-您可以继承作用域。 同样,为了处理复杂的表达式,您可以使用scope。$ eval评估模型并找到适当的范围。 评估模型后,请从受监视的函数返回它:

angular.module('app', [])
.directive('myDirective', [function() {
    return {
       restrict: 'A',
       scope: false,
       link: function(scope, element, attrs) {
           scope.$watch(function() {
               return scope.$eval(attrs.modelToWatch);
           }, function(val) {
              // do something...
           });
       }
    };
]})

如果必须使用隔离范围,请观察一个函数并返回模型:

angular.module('app', [])
.directive('myDirective', [function() {
    return {
       restrict: 'A',
       scope: {
           modelToWatch: '='
       },
       link: function(scope, element, attrs) {
           scope.$watch(function() {
               return scope.modelToWatch;
           }, function(val) {
              // do something...
           });
       }
    };
]})

您可以在指令内部直接声明一个控制器:

angular.module('app', [])
.directive('myDirective', [function() {
  return {
   restrict: 'A',
   scope: {
      modelToWatch: '='
   },
   link: function(scope, element, attrs) {
       scope.$watch(scope.modelToWatch, function(val) {
          // do something...
       });
   },
   controller: 'MyController'
  };
]})

.controller('MyController', ['$scope', function($scope) {
  $scope.obj = {
    foo: 'val'
  };


}]);

<div my-directive model-to-watch="obj.foo"></div>     

这样,当您调用指令时,将首先实例化控制器,然后将执行链接,并共享相同的作用域。

您可以观看一个函数:

scope.$watch(function() { 
        return scope.modelToWatch; 
    }, function(val) {
        // do something
});

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM