1

angularjs アプリケーションがあり、カスタム ビジネス ルールでフォームの検証を行う必要があります。問題は、特定の入力フィールドの検証ルールが他のフィールドに依存しており、実際のモデル値が変更されたとき以外に検証をトリガーする方法がわからないことです。

ケースは、従業員の動的リストであり、それぞれに入力する時間の動的リストがあります。ルールの 1 つは、これらの時間が重複してはならないということです。つまり、ある値が変更されたために別の値が無効になる可能性があり、その逆も同様です。また、フィールドごとにエラー メッセージを表示する必要があります。

フォームのコンテンツは、ネストされたリピーターのいくつかのレイヤーを持つデータモデルから生成されます。さまざまな検証ルールを含むカスタム ディレクティブを作成しました。そのフィールドが変更されたときに適切にトリガーされます。私は ngMessages を使用して、違反しているビジネス ルールに基づいて適切なエラー メッセージを表示しています。

問題は、特定の 1 つのフィールドが変更されたときに、他のすべてのフィールドで検証をトリガーするにはどうすればよいかということです。ある従業員の値は他の従業員の検証に影響を与えないため、値が変更されている従業員のすべてのフィールドの検証をトリガーすることをお勧めします。

ここのフィドルには、私の場合の単純化されたバージョンがあり、「重複」ルールは 2 つの数値が同じかどうかをチェックするだけです。

html:

<form name="demoForm">
    <div ng-repeat="employee in list">
    <div ng-bind="employee.name"></div>
    <div ng-repeat="day in employee.days" ng-form="employeeForm">

      <input ng-model="day.hours" name="hours" custom-validate="{day: day, days: employee.days}" ng-model-options="{allowInvalid:true}" />
      <span ng-messages="employeeForm.hours.$error">
        <span ng-message="number">Should be a number.</span>
      <span ng-message="businessHours">The number is outside business hours.</span>
      <span ng-message="max">The number is too large.</span>
      <span ng-message="overlap">The number must be unique for each employee.</span>
      </span>
    </div>
    <br/>
  </div>
</form>

検証ディレクティブ:

angular.module('app').directive('customValidate', [validator]);

function validator() {
  return {
    restrict: 'A',
    require: 'ngModel',
    scope: {
      data: '=customValidate'
    },
    link: linkFunc,
  };

  function linkFunc(scope, element, attrs, ctrl) {
    ctrl.$validators.number = function(value) {
      return value === "" || Number.isInteger(+value);
    }

    ctrl.$validators.businessHours = function(value) {
      // imagine other validation data here
      return value === "" || (value >= 1 && value <= 10);
    }

    ctrl.$validators.overlap = function(value) {
      if (value === "") {
        return true;
      }

      // find all other entries with identical value excluding self
      var identical = scope.data.days.filter(function(x) {
        return x !== scope.data.day && +x.hours === +value;
      });

      return identical.length === 0;
    };
  }
}

ここでフィドル: http://jsfiddle.net/maxrawhawk/dvpjdjbv/

4

1 に答える 1

1

答え: ディレクティブ リンク関数の最後にあるこの小さなコード:

scope.$watch('data', function(){
        ctrl.$validate();
    }, true);

3 番目のパラメーターとして最も重要な詳細 'true' を使用して、マークアップから提供される検証に関連するデータを監視し、$watch でオブジェクトの等価性をチェックします。更新されたフィドル: http://jsfiddle.net/maxrawhawk/dvpjdjbv/12/

于 2016-02-17T09:26:23.670 に答える