11

AngularJSアプリの他の場所のロジックに依存する最小属性値と最大属性値を持つ多数の入力フィールドがありますが、これらの属性内でデータバインディングを使用すると、Angularによって検証されなくなりますが、HTML5検証ではそれらが選択されているように見えます上。

var myApp = angular.module('myApp', []);
function FirstCtrl($scope) {
    $scope.min = 10;
    $scope.max = 20;
}
<div ng-app="myApp">
    <div ng-controller="FirstCtrl">
        <form name="myForm">
            <input type="number" name="one" required="required"
                   min="10" max="20" ng-model="one" />
            <input type="number" name="two" required="required"
                   min="{{ min }}" max="{{ max }}" ng-model="two" />
            <button ng-disabled="!myForm.$valid">Submit</button>
        </form>
    </div>
</div>

ライブバージョン: http: //jsfiddle.net/kriswillis/bPUVH/2/

ご覧のとおり、HTML / CSS(Bootstrap)では、無効になると両方のフィールドが赤に変わるため、検証は引き続き正常に処理されますが、2番目のフィールドが無効な場合は送信ボタン(Angularで処理)は無効になりません。また、にあるように、には最小プロパティと最大プロパティはありませmyForm.two.$errormyForm.one.$error

誰かが私がどこで間違っているのか見ることができますか?

4

5 に答える 5

22

ギャップを埋めるためのディレクティブ、ng-minとng-maxを作成しました。

http://jsfiddle.net/g/s5gKC/

var app = angular.module('app', []);

function isEmpty(value) {
  return angular.isUndefined(value) || value === '' || value === null || value !== value;
}

app.directive('ngMin', function() {
    return {
        restrict: 'A',
        require: 'ngModel',
        link: function(scope, elem, attr, ctrl) {
            scope.$watch(attr.ngMin, function(){
                ctrl.$setViewValue(ctrl.$viewValue);
            });
            var minValidator = function(value) {
              var min = scope.$eval(attr.ngMin) || 0;
              if (!isEmpty(value) && value < min) {
                ctrl.$setValidity('ngMin', false);
                return undefined;
              } else {
                ctrl.$setValidity('ngMin', true);
                return value;
              }
            };

            ctrl.$parsers.push(minValidator);
            ctrl.$formatters.push(minValidator);
        }
    };
});

app.directive('ngMax', function() {
    return {
        restrict: 'A',
        require: 'ngModel',
        link: function(scope, elem, attr, ctrl) {
            scope.$watch(attr.ngMax, function(){
                ctrl.$setViewValue(ctrl.$viewValue);
            });
            var maxValidator = function(value) {
              var max = scope.$eval(attr.ngMax) || Infinity;
              if (!isEmpty(value) && value > max) {
                ctrl.$setValidity('ngMax', false);
                return undefined;
              } else {
                ctrl.$setValidity('ngMax', true);
                return value;
              }
            };

            ctrl.$parsers.push(maxValidator);
            ctrl.$formatters.push(maxValidator);
        }
    };
});

angular.bootstrap(document.body, ['app']);
于 2013-04-26T17:53:45.330 に答える
9

minどうやら、フィールドとフィールドに{{}}(つまり、補間)を使用することはできませんmaxソースコードを調べたところ、次のことがわかりました。

if (attr.min) {
  var min = parseFloat(attr.min);

$interpolateは呼び出されないだけparseFloatなので、との数字のような文字列を指定する必要がありminますmax

于 2013-03-27T14:51:09.993 に答える
2

Angularは、独自のディレクティブを作成する必要なしに、すぐにサポートできるようにng-minなりました。Angular1.4.2を使用しているこのフィドルng-maxを参照してください。

于 2015-08-03T22:06:13.477 に答える
0

また、カスタムディレクティブを作成しました。

作業デモ: http: //plnkr.co/edit/BJ98ZR?p = Preview

.directive('validateRange', ['$parse', function($parse) {

    function link($scope, $element, $attrs, ngModel) {
        var attrRange, range = [];

        function validate(value) {
            var validMin = true, validMax = true;
            if (typeof range[0] === 'number') {
                ngModel.$setValidity('min', value >= range[0]);
                validMin = value >= range[0];
            }
            if (typeof range[1] === 'number') {
                ngModel.$setValidity('max', value <= range[1]);
                validMax = value <= range[1];
            }
            return validMin && validMax ? value : undefined;
        }

        attrRange = $attrs.validateRange.split(/,/);

        range[0] = $parse(attrRange[0] || '')($scope);
        range[1] = $parse(attrRange[1] || '')($scope);

        $scope.$watchCollection('[' + $attrs.validateRange + ']', function(values) {
            range = values;
            validate(ngModel.$viewValue);
        });

        ngModel.$parsers.unshift(validate);
        ngModel.$formatters.unshift(validate);
    }

    return {
        link: link,
        require: 'ngModel'
    };

}]);

使用例:

<form name="myform" ng-init="minvalue=0;value=1;maxvalue=2">
    Min Value:
    <input type="number" name="minvalue" required
           data-validate-range="0,value"
           ng-model="minvalue">

    Value:
    <input type="number" name="value" required
           data-validate-range="minvalue,maxvalue"
           ng-model="value">

    Max Value:
    <input type="number" name="maxvalue" required
           data-validate-range="value,false"
           ng-model="maxvalue">

    <pre>
        myform.minvalue.$error {{ myform.minvalue.$error }}
        myform.value.$error    {{ myform.value.$error }}
        myform.maxvalue.$error {{ myform.maxvalue.$error }}
    </pre>
</form>
于 2014-05-08T14:14:21.283 に答える
-1

私は同じ問題に直面しています。このディレクティブを使用して成功しました:

angular.module('tech').directive('maximum', ['$parse',
  function($parse) {
    return {
      restrict: 'A',
      require: '?ngModel',

      link: function(scope, element, attrs, ctrl) {

        if (!ctrl) return;
        attrs.maximum = true;


        var checkMax = function(n) {
          if (!n) return;

          var actualValue = ctrl.$viewValue;
          var maxValue = attrs.maximum;
          if (parseInt(actualValue) > parseInt(maxValue)) {
            ctrl.$setValidity('maximum', false);
          } else {
            ctrl.$setValidity('maximum', true);
          }
        };
        scope.$watch(attrs.ngModel, checkMax);
        //attrs.$observe('ngModel', remind);
        attrs.$observe('maximum', checkMax);

      }
    }
  }
]);

私はこのウェブサイトからこの解決策を得まし。コード全体については、このWebサイトにアクセスできます

于 2015-02-01T10:43:10.500 に答える