5

通常のテキスト入力を含む単純な html フォームがあります。ng-minlength、angular組み込みフォーム入力ディレクティブng-maxlengthが入力に設定されています。ng-pattern

問題:およびng-patternによる長さチェックの前にチェックが適用されます。ng-minlengthng-maxlength

質問: デフォルトのチェック順序を変更するにはどうすればよいですか? つまり、最初に長さをチェックしてから、パターン チェックを適用しますか?

例:

<body ng-app>

    <div>
        <form name="myForm">
            Name: <input name="name" type="text" ng-model="name" ng-minlength="3" ng-maxlength="16" ng-pattern="/^\w+$/"/>
            <div ng-show="myForm.name.$dirty && myForm.name.$invalid">
                <span ng-show="myForm.name.$error.pattern">Pattern error</span>
                <span ng-show="myForm.name.$error.minlength || myForm.name.$error.maxlength">Length error</span>
            </div>
            <br/>
            <input type="submit" value="Submit">
        </form>
    </div>

</body>

現在の動作:

  • 「#」を入力してください - 「パターンエラー」を参照してください
  • 「###」を入力してください - 「パターンエラー」を参照してください

望ましい動作:

  • 「#」を入力してください - 「長さエラー」を参照してください
  • 「###」を入力してください - 「パターンエラー」を参照してください

参考までに、関連するjsfiddle

前もって感謝します。

4

5 に答える 5

5

独自のディレクティブを作成します。

var mod = angular.module("myApp", []);

mod.directive("nameValidation", function () {
    return {
        restrict: "A",
        require: "ngModel",
        link: function (scope, element, attrs, ngModelCtrl) {
            var validate = function (value) {
                var minLen = parseInt(attrs.myMinlength, 10),
                    maxLen = parseInt(attrs.myMaxlength, 10),
                    pattern = attrs.myPattern,
                    match = pattern.match(/^\/(.*)\/([gim]*)$/),
                    lenErr = false;

                if (match) {
                    pattern = new RegExp(match[1], match[2]);   
                }
                if (!ngModelCtrl.$isEmpty(value)) {
                    ngModelCtrl.$setValidity("pattern", true);
                    if ((minLen && value.length < minLen) || (maxLen && value.length > maxLen)) {
                        ngModelCtrl.$setValidity("length", false);
                        lenErr = true;
                    }
                    else {
                        ngModelCtrl.$setValidity("length", true);
                        lenErr = false;
                    }

                    if (!lenErr) {
                        if (match && !pattern.test(value)) {
                            ngModelCtrl.$setValidity("pattern", false);
                        }
                        else {
                            ngModelCtrl.$setValidity("pattern", true);
                        }
                    }
                }
                else {
                    ngModelCtrl.$setValidity("length", true);
                    ngModelCtrl.$setValidity("pattern", true);
                }
            }

            ngModelCtrl.$parsers.push(validate);
            ngModelCtrl.$formatters.push(validate);
        }
    }
});

次に、HTML にアプリを含め、次のディレクティブを使用します。

<body ng-app="myApp">

<div>
    <form name="myForm">
        Name: <input name="name" type="text" ng-model="name" name-validation="" my-minlength="3" my-maxlength="16" my-pattern="/^\w+$/"/>
        <div ng-show="myForm.name.$dirty && myForm.name.$invalid">
            <span ng-show="myForm.name.$error.pattern">Pattern error</span>
            <span ng-show="myForm.name.$error.length">Length error</span>
        </div>
        <br/>
        <input type="submit" value="Submit">
    </form>
</div>
</body>

このディレクティブは、3 つの値に my-minlength、my-maxlength、および my-pattern を使用します。長さが失敗すると、それが最初にトリップします。そうでない場合、パターンが一致しない場合、パターンはエラーとして表示されます。属性を介して minlength、maxlength、および pattern を渡すことができるため、名前以外の場所で使用する場合は、このディレクティブの名前を変更することを検討してください。省略されている場合、それらは無視されます。

jsfiddle を参照してください: http://jsfiddle.net/4zpxk/6/

于 2014-03-19T18:22:12.390 に答える
2

この動作の理由を角度コードで検索しました。次に、関数「textInputType」で、角度のある「input」ディレクティブのテキスト入力を処理する特定の関数であることがわかりました。この関数の最後に、3 つのコード ブロックが表示されています。

// pattern validator
if (pattern){
 //validator logic
}

// min length validator
if (attr.ngMinlength) {
 //validator logic
}

 // max length validator
if (attr.ngMaxlength) {
 //validator logic
}

したがって、html 入力要素で ng-* 属性の宣言順序を変更しても、常に同じ結果が得られますが、ブロックの順序を変更すると、最小長のバリデータ ブロックをパターン バリデータ ブロックの前に置きます。期待どおりの結果が得られます。

これはあなたの問題の解決策ですが、角度コードに少し変更を加える必要があり、これが本当に好きかどうかわかりません。しかし、検証概念の宣言の順序が重要な非常に一般的な状況が発生したため、これを処理するにはさらに何かを行う必要があります。ありがとう

于 2014-10-08T15:50:12.530 に答える
1

ng-messages を使用する場合、次のように ng-message 要素の順序を介して順序を設定できるはずです。

<div ng-messages="field.$error">
  <ul class="validation-errors">
    <li ng-message="required">This has the highest prio</li>
    <li ng-message="min">Second in command</li>
    <li ng-message="max">I'm last</li>
  </ul>
</div>

これに関するドキュメントも: https://docs.angularjs.org/api/ngMessages/directive/ngMessages

于 2015-11-17T13:16:46.743 に答える
1

残念ながら、デフォルトのチェック順序を変更することはできません。

1 つの解決策は、カスタム バリデータを作成することですが、それほど難しくありません。この回答に基づいて、このコードを思いつきました(フィドル

  1. 使用法: スコープには検証関数の配列があり、次のようにカスタム ディレクティブに渡されます"validators"

    <input name="name" type="text" ng-model="name" validators="nameValidators"/>
    
  2. バリデータ関数は次のようになります (たとえば、minlength制約の場合):

    function minlength(value, ngModel) {
        if( value == null || value == "" || value.length >= 3 ) {
            ngModel.$setValidity('minlength', true);
            return value;
        }
        else {
            ngModel.$setValidity('minlength', false);
            return;
        }
    }
    

    重要な点は次のとおりです。値とngModelを引数として取り、テスト (ここではvalue.length >= 3) を実行し、必要に応じて呼び出しngModel.$setValidity()ます。

  3. ディレクティブは、指定された関数を次のように登録しますngModel.$parsers

    app.directive("validators", function($parse) {
        return {
            restrict: "A",
            require: "ngModel",
            link: function(scope, el, attrs, ngModel) {
                var getter = $parse(attrs.validators),
                    validators = getter(scope),
                    i;
    
                for( i=0; i < validators.length; i++ ) {
                    ngModel.$parsers.push((function(index) {
                        return function(value) {
                            return validators[index](value, ngModel);
                        };
                    })(i));
                }
            }
        };
    });
    

多くの詳細を微調整して改善できますが、アウトラインは機能します (再びfiddleへのリンク)。検証の順序は、nameValidators配列内のバリデータ関数の順序によって明示的に設定されるようになりました。

于 2014-03-19T17:45:15.617 に答える