281

required属性などを追加して、入力フィールドと検証を設定したフォームがあります。しかし、一部のフィールドについては、追加の検証を行う必要があります。制御する検証にどのように「タップイン」しFormControllerますか?

カスタム検証は、「これら 3 つのフィールドが入力されている場合、このフィールドは必須であり、特定の方法でフォーマットする必要がある」のようなものです。

にメソッドがありFormController.$setValidityますが、それはパブリック API のようには見えないので、むしろ使用しません。カスタム ディレクティブを作成して使用するNgModelControllerことは別のオプションのように見えますが、基本的にはカスタム検証ルールごとにディレクティブを作成する必要があり、これは望ましくありません。

実際には、コントローラーからのフィールドを無効としてマークすること (FormController同期を維持しながら) は、最も単純なシナリオで仕事を完了するために必要なことかもしれませんが、その方法がわかりません。

4

12 に答える 12

375

編集:以下にngMessages(> = 1.3.X)に関する情報を追加しました。

標準フォーム検証メッセージ(1.0.X以降)

これは、Googleの「AngularForm Validation」の場合の上位の結果の1つであるため、現在、そこから入ってくる人のために、これに別の回答を追加したいと思います。

FormController。$setValidityにメソッドがありますが、これはパブリックAPIのようには見えないため、使用しません。

それは「公開」であり、心配する必要はありません。これを使って。それが目的です。使用することを意図していなかった場合、Angularの開発者はクロージャーでそれを民営化したでしょう。

カスタム検証を行うには、他の回答が提案するようにAngular-UIを使用したくない場合は、独自の検証ディレクティブをロールするだけです。

app.directive('blacklist', function (){ 
   return {
      require: 'ngModel',
      link: function(scope, elem, attr, ngModel) {
          var blacklist = attr.blacklist.split(',');

          //For DOM -> model validation
          ngModel.$parsers.unshift(function(value) {
             var valid = blacklist.indexOf(value) === -1;
             ngModel.$setValidity('blacklist', valid);
             return valid ? value : undefined;
          });

          //For model -> DOM validation
          ngModel.$formatters.unshift(function(value) {
             ngModel.$setValidity('blacklist', blacklist.indexOf(value) === -1);
             return value;
          });
      }
   };
});

そして、ここにいくつかの使用例があります:

<form name="myForm" ng-submit="doSomething()">
   <input type="text" name="fruitName" ng-model="data.fruitName" blacklist="coconuts,bananas,pears" required/>
   <span ng-show="myForm.fruitName.$error.blacklist">
      The phrase "{{data.fruitName}}" is blacklisted</span>
   <span ng-show="myForm.fruitName.$error.required">required</span>
   <button type="submit" ng-disabled="myForm.$invalid">Submit</button>
</form>

注:1.2.Xでは、上記の代わりに使用することをお勧めng-ifng-showます

ここに必須のプランカーリンクがあります

また、私はもう少し詳細に入るこの主題についてのいくつかのブログエントリを書きました:

角度形式の検証

カスタム検証ディレクティブ

編集:1.3.XでngMessagesを使用

ngShowの代わりにngMessagesモジュールを使用して、エラーメッセージを表示できるようになりました。実際には何でも機能します。エラーメッセージである必要はありませんが、基本は次のとおりです。

  1. 含む<script src="angular-messages.js"></script>
  2. ngMessagesモジュール宣言での参照:

    var app = angular.module('myApp', ['ngMessages']);
    
  3. 適切なマークアップを追加します。

    <form name="personForm">
      <input type="email" name="email" ng-model="person.email" required/>
    
      <div ng-messages="personForm.email.$error">
        <div ng-message="required">required</div>
        <div ng-message="email">invalid email</div>
      </div>
    </form>
    

上記のマークアップでは、ng-message="personForm.email.$error"基本的にng-message子ディレクティブのコンテキストを指定します。次に ng-message="required"ng-message="email"監視するそのコンテキストのプロパティを指定します。最も重要なのは、チェックインする順序も指定していることです。リストで最初に見つかった「真実」のメッセージが優先され、そのメッセージが表示され、他のメッセージは表示されません。

そして、ngMessagesの例のプランカー

于 2013-02-26T13:52:57.060 に答える
95

Angular-UI のプロジェクトには、おそらくこれに役立つ ui-validate ディレクティブが含まれています。検証を行うために呼び出す関数を指定できます。

http://angular-ui.github.com/のデモ ページを見て、Validate の見出しまで検索してください。

デモページから:

<input ng-model="email" ui-validate='{blacklist : notBlackListed}'>
<span ng-show='form.email.$error.blacklist'>This e-mail is black-listed!</span>

次に、コントローラーで:

function ValidateCtrl($scope) {
  $scope.blackList = ['bad@domain.com','verybad@domain.com'];
  $scope.notBlackListed = function(value) {
    return $scope.blackList.indexOf(value) === -1;
  };
}
于 2012-10-05T10:08:07.403 に答える
47

検証シナリオにng-requiredを使用できます(「これらの3つのフィールドが入力されている場合、このフィールドは必須です」:

<div ng-app>
    <input type="text" ng-model="field1" placeholder="Field1">
    <input type="text" ng-model="field2" placeholder="Field2">
    <input type="text" ng-model="field3" placeholder="Field3">
    <input type="text" ng-model="dependentField" placeholder="Custom validation"
        ng-required="field1 && field2 && field3">
</div>
于 2013-03-05T11:15:50.853 に答える
14

私は最近、angular フォーム入力の式ベースの無効化を許可するディレクティブを作成しました。任意の有効な角度式を使用でき、オブジェクト表記を使用してカスタム検証キーをサポートします。angular v1.3.8でテスト済み

        .directive('invalidIf', [function () {
        return {
            require: 'ngModel',
            link: function (scope, elm, attrs, ctrl) {

                var argsObject = scope.$eval(attrs.invalidIf);

                if (!angular.isObject(argsObject)) {
                    argsObject = { invalidIf: attrs.invalidIf };
                }

                for (var validationKey in argsObject) {
                    scope.$watch(argsObject[validationKey], function (newVal) {
                        ctrl.$setValidity(validationKey, !newVal);
                    });
                }
            }
        };
    }]);

次のように使用できます。

<input ng-model="foo" invalid-if="{fooIsGreaterThanBar: 'foo > bar',
                                   fooEqualsSomeFuncResult: 'foo == someFuncResult()'}/>

または、単に式を渡すことによって (「invalidIf」のデフォルトの validationKey が与えられます)

<input ng-model="foo" invalid-if="foo > bar"/>
于 2015-06-05T14:36:50.563 に答える
5

@synergetic @bleshは、関数の検証を次のように配置すると思います

function validate(value) {
    var valid = blacklist.indexOf(value) === -1;
    ngModel.$setValidity('blacklist', valid);
    return valid ? value : undefined;
}

ngModel.$formatters.unshift(validate);
ngModel.$parsers.unshift(validate);
于 2013-10-01T05:35:49.423 に答える
1

@Ben Leshの回答を拡張して、検証で大文字と小文字を区別するかどうかを指定できるようにしました(デフォルト)

使用する:

<input type="text" name="fruitName" ng-model="data.fruitName" blacklist="Coconuts,Bananas,Pears" caseSensitive="true" required/>

コード:

angular.module('crm.directives', []).
directive('blacklist', [
    function () {
        return {
            restrict: 'A',
            require: 'ngModel',
            scope: {
                'blacklist': '=',
            },
            link: function ($scope, $elem, $attrs, modelCtrl) {

                var check = function (value) {
                    if (!$attrs.casesensitive) {
                        value = (value && value.toUpperCase) ? value.toUpperCase() : value;

                        $scope.blacklist = _.map($scope.blacklist, function (item) {
                            return (item.toUpperCase) ? item.toUpperCase() : item
                        })
                    }

                    return !_.isArray($scope.blacklist) || $scope.blacklist.indexOf(value) === -1;
                }

                //For DOM -> model validation
                modelCtrl.$parsers.unshift(function (value) {
                    var valid = check(value);
                    modelCtrl.$setValidity('blacklist', valid);

                    return value;
                });
                //For model -> DOM validation
                modelCtrl.$formatters.unshift(function (value) {
                    modelCtrl.$setValidity('blacklist', check(value));
                    return value;
                });
            }
        };
    }
]);
于 2015-11-18T10:36:02.583 に答える
0

このスレッドにはいくつかの優れた例とライブラリが示されていますが、私が探していたものはまったくありませんでした。私のアプローチ: angular-validity -- 非同期検証用の promise ベースの検証ライブラリで、オプションの Bootstrap スタイルが組み込まれています。

OPのユースケースの角度有効性ソリューションは、次のようになります。

<input  type="text" name="field4" ng-model="field4"
        validity="eval"
        validity-eval="!(field1 && field2 && field3 && !field4)"
        validity-message-eval="This field is required">

試してみたい場合は、ここにFiddleがあります。ライブラリはGitHubで入手でき、詳細なドキュメントと多数のライブ デモがあります。

于 2016-11-07T21:01:17.583 に答える