1

2 つの検証ディレクティブを作成しました。それぞれが個別にうまく動作しますが、両方が適用されると、rangeValidator が失敗するたびに numberValidator が失敗します (したがって、"3" は rangeValidator に失敗するため、rangeValidator が画像の外にある場合でも、numberValidator も失敗します)。

ロギングにより、numberValidator が実際に失敗していることを確認します (HTML の一部のエラーに対して)。

ディレクティブが互いに独立して機能することを期待していました。ユーザーが「3」を入力しても、「数値でなければなりません」と表示されることは望ましくありません。

数値入力の使用はオプションではありません。

私のJS:

app.directive('rangeValidator', function () {
    return {
        require: 'ngModel',
        link: function (scope, elm, attrs, ctrl) {
            var min = scope.$eval(attrs.minValue);
            var max = scope.$eval(attrs.maxValue);
            ctrl.$parsers.unshift(function (viewValue) {
                if (parseInt(viewValue) >= min && parseInt(viewValue) <= max) {
                    // it is valid
                    ctrl.$setValidity('rangeValidator', true);
                    return viewValue;
                } else {
                    // it is invalid, return undefined (no model update)
                    ctrl.$setValidity('rangeValidator', false);
                    return undefined;
                }
            });
        }
    };
});


app.directive('numberValidator', function () {
    return {
        require: 'ngModel',
        link: function (scope, elm, attrs, ctrl) {
            ctrl.$parsers.unshift(function (viewValue) {
                if (!isNaN(parseInt(viewValue))) {
                    // it is valid
                    console.log('Number Validator passed!');
                    ctrl.$setValidity('numberValidator', true);
                    return viewValue;
                } else {
                    // it is invalid, return undefined (no model update)
                    ctrl.$setValidity('numberValidator', false);
                    return undefined;
                }
            });
        }
    };
});
4

1 に答える 1

2

Angular のドキュメントのアドバイスに従い、undefinedパーサー関数内で無効な値が返されたようです。それを行う際の問題(あなたの場合)は、パーサーのパイプラインを壊すことです。無効な値を最初に検出したディレクティブは次のディレクティブに渡さundefinedれ、明らかにそれも無効であると見なされます。

私は2つの解決策を考えることができます:

1) 元の値がパーサー パイプラインを通過するようにします。

ctrl.$parsers.unshift(function (viewValue) {
    if (parseInt(viewValue) >= min && parseInt(viewValue) <= max) {
        ctrl.$setValidity('rangeValidator', true);
    } else {
        ctrl.$setValidity('rangeValidator', false);
    }
    return viewValue;
});

...

ctrl.$parsers.unshift(function (viewValue) {
    if (!isNaN(parseInt(viewValue))) {
        ctrl.$setValidity('numberValidator', true);
    } else {    
        ctrl.$setValidity('numberValidator', false);
    }
    return viewValue;
});

作業デモはこちら

これにより、モデルが無効な値で更新されるのを防ぐことはできず、$validまたは$invalidプロパティを使用して、その値を使用する前にフィールドの状態を確認する必要がありますが、互いに独立してエラーを確認することができます。

2) 両方のディレクティブに異なる優先度を設定する

それぞれに異なる優先順位を設定することで、ディレクティブが実行される順序を制御できます。そうすることで、次のように無効な値を段階的にチェックできます。

<span ng-show="form.value.$error.rangeValidator">Invalid range</span>
<span ng-show="!form.value.$error.rangeValidator && form.value.$error.numberValidator">Invalid number</span>

作業デモはこちら

注意点があります。検証が追加されると、非常に面倒になる可能性があります。

モデルが無効な値で更新されるのを防ぐことはできませんが、個人的には最初のアプローチの方が気に入っています。

于 2013-10-19T06:51:54.470 に答える