$ scope。$ watch,但仅适用于ngChange事件?

时间:2013-07-25 01:14:01

标签: angularjs angularjs-scope

我想订阅一个ngChange事件,但是来自代码而不是标记。也就是说,给定$ scope和可通过ngModel绑定的表达式,我想订阅任何绑定到该表达式的ngModel指令对该表达式所做的任何更改。这可能吗?

类似的东西:

$scope.field = "hello";
$scope.onButtonClick = function() {
  $scope.field = "button clicked!";
}

// this callback is only when the user types in an input bound to field
// not when they click the button with ng-click="onButtonClick()"
$scope.$watchNgChange("field", function() { 
  console.log("user caused field to change via a binding");
});

// this callback is called for both ngModel binding changes and onButtonClick.
$scope.$watch("field", function() {
  console.log("field was changed");
});

我不能只使用$ watch,因为这将捕获所有更改,包括从数据库加载数据,ng-click回调以及从$ watch回调为其他表达式启动的更改(在本例中,如果有任何循环引用,那么很容易让$ watch回调进入无限循环并在10个摘要周期后出错),谁知道还有什么。

3 个答案:

答案 0 :(得分:3)

首先,任何时候我试图做这样的事情都是一个坏主意 - 我只是解决我的代码中的设计问题或我的业务逻辑中的逻辑问题。一般来说,代码不应该关心数据是如何更改的,只是它已经改变了。

其次,$ watch可以为您提供新旧价值 - 这对我来说已经足够了。如果旧值不等于新值,我想更新相关的数据模型。如果旧值和新值相等,我想忽略更新。

最后,您可以考虑使用您的路由使用resolve消除“数据库加载”,因为完全定位的数据可以传递到您的控制器(假设您返回一个承诺)。

答案 1 :(得分:1)

不要这样做,听起来你正试图将DOM逻辑(例如,如果用户已与DOM元素交互)引入控制器。

如果您阅读了ngChange指令的源代码,您会发现它需要一个ngModel,它用作视图和控制器之间的桥梁。

我建议您创建模型的副本,并在视图中使用ngModel + ngChange将数据绑定到数据绑定中,然后您可以观看该副本并执行任何操作。

$scope.field = "hello"; //the field you care
$scope.fieldCopy = $scope.field; //use 'fieldCopy' for databinding

在html代码中,您可以通过多种方式更改模型fieldCopy

<input ngModel="fieldCopy" name='foo' />
<input ngModel="fieldCopy" name='foo2' />

然后,您可以观察fieldCopy以了解与用户互动相关的更改,并将更改复制到“字段”:

$scope.$watch("fieldCopy", function() {
  $scope.field = $scope.fieldCopy;
   console.log("user caused field to change via a binding"); 
});

如果您想让fieldCopy与字段保持同步,请添加另一个监视:

$scope.$watch("field", function() {
  $scope.fieldCopy = $scope.field;
});

答案 2 :(得分:1)

杰里米你刚才描述了Angular中被称为指令的内容。最好在每次需要触摸DOM时始终使用指令。这种逻辑永远不应该存在于控制器甚至服务中。

指令是一个很棘手的问题,但它有大量的文档。

访问docs.angularjs.org/directives