【问题标题】:AngularJS: conditional ng-class with a function triggering ridiculous amountsAngularJS:具有触发荒谬数量的函数的条件 ng-class
【发布时间】:2015-12-03 01:06:12
【问题描述】:

我检查了类似的问答,但没有解决我的问题。

我想动态设置一个输入的类,考虑下面Plunkr

如你所见,我有一个字段,定义如下:

<input type="text" ng-model="Person.Name" ng-class="{'mandatory': IsFieldMandatory('Name')}" />

该函数的代码如下:

self.IsFieldMandatory = function(field){
  var isMandatory = true;

  var value = $scope.Person.Name;

  $scope.Cnt = $scope.Cnt + 1;

  return value.length == 0;
}

如您所见,它会在页面加载时触发 11(!) 次(或任何进一步的操作,如模糊)。

PS:该功能不起作用,因为我收到此错误:

Error: $rootScope:infdig Infinite $digest Loop

由于 $scope.Cnt 增量而发生。如果发表评论,它会起作用(但我不知道触发器的数量)。

PPS:

我该如何使用它?:

var value = $parse('Person.' + field);

这样会更好,因为这样该函数将适用于任何领域。它需要,在现实世界的场景中。 (这返回一个函数,而不是一个实际值

谢谢!

更新

Plunkr 的例子似乎没有什么价值,所以取而代之的是原始函数:

self.IsMandatory = function (field) {

    console.log('test');

    if (self.IsMandatoryFieldsLoaded == true) {
        var idxAsync = self.MandatoryFields.indexOf(field);
        return idxAsync > -1;
    }

    return false;
}

如您所见,我没有做任何修改,只是读取。我有 11 个字段,但这个函数的“测试”记录却写了 198 次!

【问题讨论】:

  • var value = $scope.Person[field] 就足够了。是的,你不应该在 watch 函数中更新你的模型($scope 对象),因为每个这样的更改基本上都会触发另一个 watchers 调用。
  • 错误是由$scope.Cnt = $scope.Cnt + 1;引起的,如果你删除该行它只会执行2次
  • 看起来该值有效。你是什​​么意思'在手表功能中更新模型'?我只是在读取值,而不是设置任何值(忘记了示例中的 cnt)。
  • 当然,如果您不使用$scope.cnt,您只会读取值,并且没有“荒谬数量”的摘要调用。
  • @Spikee - 我检查了 plunker 代码,您似乎想根据某些条件验证字段。可能你应该试试 ng-required

标签: javascript .net angularjs asp.net-mvc


【解决方案1】:

您可以简单地检查输入中是否输入了任何内容,如下所示:

<input type="text" ng-model="Person.Name" ng-class="{'mandatory': !Person.Name.length}" />

这样你就可以摆脱你的错误。因为您正在更新函数中的Cnt $scope 变量,所以会一遍又一遍地触发摘要循环。这导致了无限循环(您看到的错误)。

通过简单地检查Person.Name 是否有长度,您可以避免声明新函数和其他不必要的逻辑。它简单而干净。

希望这会有所帮助。

使用 ngForms 更新:

您可以声明一个指令来验证您的输入,如下所示:

app.directive('validate', function() {
  return {
    restrict: 'A',
    require: 'ngModel',
    link: function(scope, elem, attr, ngModelCtrl) {
      scope.$watch('Person.Name', function(newValue) {
        ngModelCtrl.$setValidity('notEmpty', isEmpty(newValue))
      });
    }
  }
});

function isEmpty(string) {
  return !!string.length;
}

并在您的输入中使用它

<input type="text" validate ng-model="Person.Name"/>

在你的 CSS 中你将拥有

input.ng-invalid {
  border: 2px solid red;
}

现在您可以忽略有多少复杂的验证函数,只需使用 $setValiditity() 函数来告诉 Angular 该输入是否有效。如果您的某个验证变为 false,那么 Angular 会通过添加 ng-invalid 类自动将您的输入变为红色。

【讨论】:

  • 它会/确实在是/否条件下工作,但我需要进行非常复杂的检查,这意味着我将有许多可能的类。这不会涵盖这一点。
  • 那么ngForm就可以派上用场了。您可以在 ngModel 上添加 $watch 并删除自定义验证功能。这是一篇关于如何在 angularjs 中进行输入/表单验证的非常详细的文章:ng-newsletter.com/posts/validations.html
  • 基于该验证功能,Angular 会自动在您的输入中添加一个“ng-invalid”类。如果您愿意,您可以使用红色边框为该类设置样式