Custom form validation directive to compare two fields

后端 未结 6 782
借酒劲吻你
借酒劲吻你 2020-11-28 08:54

I\'m an angular newbie, and I\'m stumbling over something in how angular\'s form validation directives work.

I know that I can fairly easily add directives to in

相关标签:
6条回答
  • 2020-11-28 09:38

    Many ways to skin a cat.

    PLUNKER

    app.directive('lowerThan', [
      function() {
    
        var link = function($scope, $element, $attrs, ctrl) {
    
          var validate = function(viewValue) {
            var comparisonModel = $attrs.lowerThan;
    
            if(!viewValue || !comparisonModel){
              // It's valid because we have nothing to compare against
              ctrl.$setValidity('lowerThan', true);
            }
    
            // It's valid if model is lower than the model we're comparing against
            ctrl.$setValidity('lowerThan', parseInt(viewValue, 10) < parseInt(comparisonModel, 10) );
            return viewValue;
          };
    
          ctrl.$parsers.unshift(validate);
          ctrl.$formatters.push(validate);
    
          $attrs.$observe('lowerThan', function(comparisonModel){
            // Whenever the comparison model changes we'll re-validate
            return validate(ctrl.$viewValue);
          });
    
        };
    
        return {
          require: 'ngModel',
          link: link
        };
    
      }
    ]);
    

    Usage:

    <input name="min" type="number" ng-model="field.min" lower-than="{{field.max}}" />
    <span class="error" ng-show="form.min.$error.lowerThan">
      Min cannot exceed max.
    </span>
    
    0 讨论(0)
  • 2020-11-28 09:38

    Would a simple comparison suit you?

    <small class="error" ng-show="field.min > field.max">
    

    I think a directive would be an overkill if your case is just this. If you do not feel comfortable with the view containing application logic, you can export it in a function of the controller:

    $scope.isMinMaxInalid = function() {
        return $scope.field.min > $scope.field.max;
    };
    

    And the template:

    <small class="error" ng-show="isMinMaxInalid()">
    
    0 讨论(0)
  • 2020-11-28 09:49

    You may take a look at https://github.com/nelsonomuto/angular-ui-form-validation

    This provides a directive that is preconfigured with an api that exposes the scope and its models to your validator function.

    Here is a plunker with the your specific use case: http://plnkr.co/edit/S0rBlS?p=preview

    The syntax for the directives validators is as shown in the below example : { errorMessage: 'Cannot contain the number one', validator: function (errorMessageElement, val, attr, element, model, modelCtrl){ /** * The model and modelCtrl(scope) are exposed in the validator function * */ return /1/.test(val) !== true;
    } }

    0 讨论(0)
  • 2020-11-28 09:50

    You do not need any directive. Just assign the "min" value of max to min-value. Like:

    <input name="min" type="number" ng-model="field.min"/>
    <input name="max" type="number" ng-model="field.max" min=" {{ field.min }}"/>
    

    And you do not need any customization.
    More: you can do min=" {{ field.min + 1}}"

    0 讨论(0)
  • 2020-11-28 09:55

    For me, beyond a feedback message, I needed define the field as invalid, preventing submit. So I gathered some approaches, like @thestewie approach, with a view configuration to gather a solution for dates comparison. I hope can aggregate the solutions that were presented.

    The code is in PLUNKER

    angular.module('MyApp')
        .directive('thisEarlierThan', function () {
            return {
                require: 'ngModel',
                restrict: 'A',
                link: function (scope, elem, attrs, ctrl) {
                    var startDate,
                        endDate;
    
                    scope.$watch(attrs.ngModel, function (newVal, oldVal, scope) {
                        startDate = newVal;
                        check();
                    });
    
                    scope.$watch(attrs.thisEarlierThan, function (newVal, oldVal, scope) {
                        endDate = newVal;
                        check();
                    });
    
                    var check = function () {
                        if (typeof startDate === 'undefined' || typeof endDate === 'undefined') {
                            return;
                        }
    
                        if (!validate(startDate)) {
                            startDate = new Date(startDate);
                            if (!validate(startDate)) {
                                return;
                            }
                        }
    
                        if (!validate(endDate)) {
                            endDate = new Date(endDate);
                            if (!validate(endDate)) {
                                return;
                            }
                        }
    
                        if (startDate < endDate) {
                            ctrl.$setValidity('thisEarlierThan', true);
                        }
                        else {
                            ctrl.$setValidity('thisEarlierThan', false);
                        }
    
                        return;
                    };
    
                    var validate = function (date) {
                        if (Object.prototype.toString.call(date) === '[object Date]') {
                            if (isNaN(date.getTime())) {
                                return false;
                            }
                            else {
                                return true;
                            }
                        }
                        else {
                          return false;
                        }
                    };
                }
            };
        })
    ;
    
    0 讨论(0)
  • 2020-11-28 09:58

    My version of the directive:

    module.directive('greaterThan', function () {
        return {
            restrict: 'A',
            require: 'ngModel',
            link: function (scope, element, attributes, ngModelController) {
                var otherValue;
    
                scope.$watch(attributes.greaterThan, function (value) {
                    otherValue = value;
    
                    ngModelController.$validate();
                });
    
                ngModelController.$parsers.unshift(function (viewValue) {
                    ngModelController.$setValidity('greaterThan', !viewValue || !otherValue || viewValue > otherValue);
    
                    return viewValue;
                });
            }
        };
    });
    
    0 讨论(0)
提交回复
热议问题