0

I'm looking at this in my browser:

<input class="ng-valid-number ng-dirty ng-valid ng-valid-required" type="number" step="0.01" required="" data-ng-model="obfuscated" min="0.1" max="0.5">

That seems strange to me, given the fact that I filled in 42 as a value.

I'd like to use a custom validation function. I don't care for a directive a this point, I just want to do something along the lines of

ng-valid-when="expression"

Does such a thing exist?

(If you're wondering how I got this to fail, the clue is to use an espression to fill max and min max="0.5" works as expected, max="{{my expression}}" doesn't.)

UPDATE: working directive solution

With a directive:

module.directive('withinRange', function () {
return  {
  require: 'ngModel',
  link: function (scope, element, attrs, ngModel) {
    var restrictions = scope.$eval(attrs.withinRange);
    scope.$watch(function(){return ngModel.$modelValue}, function(){
      ngModel.$setValidity('min', ngModel.$modelValue >= restrictions.min());
      ngModel.$setValidity('max', ngModel.$modelValue <= restrictions.max());
    });
  }
}
});

this works:

<input name="input" type="number" step="0.01"
       data-within-range="range" 
       data-ng-model="value"/>

    angular.extend($scope, {value: 0.2,
      range: {
        min: function () {
          return 0.1;
        }, max: function () {
          return 0.9;
        }}});
2
  • What's strange? What failed? Commented Feb 11, 2014 at 21:40
  • Thanks for pointing out the stellar gap in my question, will fix immediately. Commented Feb 11, 2014 at 21:42

3 Answers 3

2

Angular form validation is expecting a form or input error to have a name. This name is specified in the arguments you pass to $setValidity, which you use from the ngModelController instance that you require in a directive definition and use in its link function.

Such a ng-valid-when="expression" attribute would not pass an error name.

So, you have to build a directive for your error type. Angular is designed this way.

However, you may write your own generic ngValidExpression directive which would for example toggle ng-invalid-expression/ng-valid-expression classes the same way it does with the ngPattern attribute.

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

1 Comment

Yep, that's what I ended up doing. Wouldn't it work fine if there was a generic directive with a default name though?
1

This doesn't exist in Angular. The closest you can get is the ng-pattern attribute of the input directive.

See the manual page for forms for more information on form validation with a directive.

2 Comments

I've got a working solution with a directive, but if all you need is validation based on business logic accessible through the controller it seems insane. ng-pattern won't do for number range I think.
Yes, it's annoyingly cumbersome to write custom validation.
1

I make a solution for multiple validations (one per input) without write multiple validators directive, simply put the validators in the scope and the call those validators as an attribute

Controller:

//...
myRangeValidator = (modelValue, viewValue)=>{...}
$scope.actions.validators.range = myRangeValidator;
$scope.data.number = 0;

myUserNameValidator = (modelValue, viewValue)=>{...}
$scope.actions.validators.userName = myUserNameValidator;
$scope.data.userName = "";
//...

View:

<input
  type="number"
  ng-model="data.number"
  dfxpvalidator="actions.validators.range"
>
<input
  type="text"
  ng-model="data.userName"
  dfxpvalidator="actions.validators.userName"
>

Directive:

// This directive add a custom validator independent of the directive
// original writed in CS
app.directive( 'dfxpvalidator', [
  '$rootScope',
  '$timeout',
  function($rs, $to){
    return {
      restrict: 'A',
      require: 'ngModel',
      scope:{dfxpvalidator: '='},
      link: function(scope, elements, attrs, model){
        model.$validators.myValidator = scope.dfxpvalidator
      }
    }
  }
])

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.