0

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?

4 Answers 4

1

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.

Sign up to request clarification or add additional context in comments.

1 Comment

Great simple solution. Thank you. I'm surprised there's need to call maxDate through scope.MaxDate not maxDate nor $scope.maxDate. It's unusual to me. I've just also posted a solution, based on original angular code. It's more complex, but I've noticed it allows to put for example dots in the attribute value, so in some cases it might be better. Anyway I appreciate your solution. Thank you once again.
1
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.

1 Comment

Conditions inside function doesn't seem to work, but max and attrs.maxDate values are correct. It's the simplest solution so far and works with dots inside attribute value. Great!
0

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'

4 Comments

Unfortunately this causes the exception: Error: [$parse:syntax] Syntax Error: Token 'Date' is an unexpected token at column 5 of the expression [new Date()] starting at [Date()].
What angular version? If you console.log your max what is it's bound value?
Angular version is 1.4.9.
Max is value of input, not value of the attribute.
0

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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.