Arkadiusz Kałkus
Arkadiusz Kałkus

Reputation: 18423

How to make a validation attribute with parameter in Angular.js?

I want to implement a validation attribute with parameter. In particular attribute for validating maximum date in a custom format.

<input type="datetime" ng-model="someForm.someField" name="SomeField" max-date="2016.09.11" />

There are many examples of validating directives without parameters, so I've tried to base my code on them. I've added scope and restriction to attribute only usage of the directive.

fooApp.directive('maxDate', function () {
    return {
        restrict: 'A',
        scope: {
            max: '='
        },
        require: 'ngModel',
        link: function ($scope, element, attrs, ngModel) {
            ngModel.$validators.maxDate = function (value, max) {
                //Here will be validator logic
            };
        }
    }
});

The problem is - max is always the same as value. It's not value of max-date attribute, but the value of input field. What am I doing wrong?

Upvotes: 0

Views: 142

Answers (4)

Vigneshwarr
Vigneshwarr

Reputation: 125

link: function ($scope, element, attrs, ngModel) {
            ngModel.$validators.maxDate = function (value, max) {                
                if (!!value && (value.length ==10 ) )
                {
                    if ( new Date(max) > new Date(attrs.maxDate))
                    {
                        console.log("Date is Higher");
                     }
                }                  
            };
        }

Can you check this.

Upvotes: 1

Arkadiusz Kałkus
Arkadiusz Kałkus

Reputation: 18423

It's a little bit tricky, but works:

fooApp.directive('maxDate', function () {
    return {
        restrict: 'A',
        require: 'ngModel',
        link: function (scope, elm, attr, ctrl) {
            if (!ctrl) return;
            var maximumDate = 0;
            attr.$observe('maxDate', function (value) {
                maximumDate = value;
                ctrl.$validate();
            });
            ctrl.$validators.maxDate = function (modelValue, viewValue) {
                console.log('viewValue: ' + viewValue);
                console.log('maximumDate: ' + eval(maximumDate));
                return ctrl.$isEmpty(viewValue);// || viewValue.length >= minlength;
            };
        }
    }
});

viewValue is a value from the input, maximumDate is a value from the attribute.

I've based it on ngMinlength directive. Here's the code of original Angular directive:

var minlengthDirective = function() {
  return {
    restrict: 'A',
    require: '?ngModel',
    link: function(scope, elm, attr, ctrl) {
      if (!ctrl) return;

      var minlength = 0;
      attr.$observe('minlength', function(value) {
        minlength = toInt(value) || 0;
        ctrl.$validate();
      });
      ctrl.$validators.minlength = function(modelValue, viewValue) {
        return ctrl.$isEmpty(viewValue) || viewValue.length >= minlength;
      };
    }
  };
};

Of course my directive is only an example of getting directive value in a validating directive, not working max-date attribute, but implementation of the details is simple and inessential.

Upvotes: 0

Naga Sandeep
Naga Sandeep

Reputation: 1431

I tried solving this. Please see below.

Template

<input type="datetime" ng-model="someForm" name="SomeField" max-date=20160911 />

2016.09.11 is NaN and 2016/09/11 is dividing the number. Not sure why they both are not treated as strings. So, I have removed the delimiter and used substrings to create the date. See below.

js

return {
    restrict: 'A',
    scope: {
        maxDate: '='
    },
    require: 'ngModel',
    link: function (scope, element, attrs, ngModelCtrl) {
        ngModelCtrl.$validators.maxDateValidator = function (modelValue, viewValue) {
            var year = scope.maxDate.toString().substring(0,4);
            var month = parseInt(scope.maxDate.toString().substring(4,6))-1;
            var day = scope.maxDate.toString().substring(6);
            var maximumDate = new Date(year, month, day)
            var enteredDate = new Date(viewValue);
            console.log(maximumDate.getTime()>=enteredDate.getTime());
            return maximumDate.getTime()>=enteredDate.getTime();
        };
    }
}

As far as your question goes, the parameters are not actually what you thought. They are the view value and model value of the model. Please see the documentation here.

Upvotes: 1

Harald F.
Harald F.

Reputation: 4793

It looks like you've typed the wrong binding in your scope. It looks for a binding called "max". You could either add your max as an attribute that would be evaluated and use the attrs. to fetch the value, or you can bind to itself using something like:

scope: {
  maxDate : '='
}

As far as I can tell from your example, this should work. You could also bind using an isolated scope; e.g. date: '=maxDate'

Upvotes: 0

Related Questions