1

我想订阅一个 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 个摘要循环后出错),谁知道还有什么。

4

3 回答 3

3

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

其次,$watch 可以同时给你新旧价值——这对我来说已经足够了。如果旧值不等于新值,我想更新相关的数据模型。如果旧值和新值相等,我想忽略更新。

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

.

于 2013-07-25T01:36:02.603 回答
1

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

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

我建议创建模型的副本,并在视图中使用 ngModel+ngChange 将副本用于数据绑定,然后您可以 $watch 该副本并做任何您想做的事情。

$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 与 field 保持同步,请添加另一个手表:

$scope.$watch("field", function() {
  $scope.fieldCopy = $scope.field;
});
于 2013-07-25T01:36:30.857 回答
1

Jeremy,您只是描述了 Angular 中所谓的指令。每次需要接触 DOM 时始终使用指令是最佳实践。这个逻辑不应该存在于控制器甚至服务中。

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

访问 docs.angularjs.org/directives

于 2013-07-25T03:02:53.750 回答