Skip to content
This repository has been archived by the owner on Apr 12, 2024. It is now read-only.

min/max input validation is against $modelValue, not $viewValue #12761

Closed
edzius opened this issue Sep 4, 2015 · 7 comments · Fixed by #16325
Closed

min/max input validation is against $modelValue, not $viewValue #12761

edzius opened this issue Sep 4, 2015 · 7 comments · Fixed by #16325

Comments

@edzius
Copy link

edzius commented Sep 4, 2015

Hi,

I am using ngModelController.$parsers/$formatters pipeline to do the number conversion and default min/max validators. My problem is that validation is done against $modelValue. So in my case when i enter value that is still valid in view validators reports it is invalid in model.

I want to propose to do default (min/max/etc.) validation on $viewValue. This way input limitations applied by browser would match validators rules.

I've made plunker to ilustrate: http://plnkr.co/edit/1IOnf9HYjgHhvpD0QsI3?p=preview

Cheers,
Edvinas

@frfancha
Copy link

frfancha commented Sep 4, 2015

$viewValue is string, $modelValue is of the model type (number in your case).
This is why min/max/... only make sense on $modelValue

@Narretz Narretz changed the title input validation against $modelValue min/max input validation is against $modelValue, not $viewValue Sep 9, 2015
@Narretz
Copy link
Contributor

Narretz commented Sep 9, 2015

I tend to agree that the HTML5 validators should work against the input values. This might break people's apps however. Might be something for 1.5

@edzius
Copy link
Author

edzius commented Sep 9, 2015

Sorry for the delay.

It definitely make sense to validate against $viewValue. From the ideological side in most of the cases validation messages should notify about errors of value that is currently visible on the screen. Also in some cases user might require validation for $modelValue, so validation target value (either $modelValue or $viewValue or both?) could be configurable in ng-model-options. And this way we could have backwards compatibility with older versions of angular.

By the way i took a peek into existing required/minlength/maxlength/pattern validators -- all of them validates against $viewValue..

@bogomips
Copy link

bogomips commented Apr 15, 2016

Hello,
I have the same opinion. I would set min e max in order to limit the $viewValue range, so errors should be consistent with that.
In my case i have an input that allowes different units of measure (let's say one could enter his body's height in inches and cm) so depending on users choice, I dinamically set a different min and max range. Anyway my $parsers value is always in cm because i choosed to send this unit in my db.
Is there any easy work around you guys would suggest? my only alternative is to write the logic inside a controller or better to build a new directive...

**UPDATE
I share my workaround, it could be useful for someone.
The problem was that the input status was invalid so "ng-change" did not get fire and the value was not saved on db.
I've just add ng-model-options="{allowInvalid:true}"
It works for me becouse i don't submit the form in a classic way but field by field when the user presses enter the field is in a blur status.
now i can finally set dinamically my min and max.

@belfz
Copy link

belfz commented Nov 17, 2016

Any updates to this? I am using angular 1.5.8 and this problem still exists.

@Narretz Narretz self-assigned this Dec 1, 2016
@Narretz Narretz modified the milestones: 1.7.0, Ice Box Apr 17, 2017
@petebacondarwin
Copy link
Contributor

@Narretz can we discuss whether this should be considered "workaround-able"?

@Narretz
Copy link
Contributor

Narretz commented Oct 3, 2017

It's work-aroundable as you can copy the validation code and apply it to the $viewValue instead of the $modelValue. However, I think for the sake of consistency we should change it to validate the $viewValue, and then the same applies for devs that want to validate the $modelValue.

For reference, the validation atm is as follows:

  • required: viewValue
  • pattern: viewValue
  • maxlength / minlength: viewValue
  • min / max for "date": modelValue (which is a Date object)
  • min / max for "number": modelValue (which is a Number Object)
  • step for "number": viewValue
  • min / max / step for "range": viewValue

So it is inconsistent, but there's a tendency to validate the viewValue. While it might look like for date and number, it necessary to validate the modelValue because it has been converted to an Object, in range, we convert the viewValue to a Number for the step validation, so we can definitely transform the viewValue for the other validators as well.

Another idea I had was to make it configurable via ngModelOptions if $modelValue / $viewValue gets validated, but this might become too complex.

Narretz added a commit to Narretz/angular.js that referenced this issue Nov 10, 2017
This brings the validation in line with HTML5 validation and all other
validators.

Fixes angular#12761

BREAKING CHANGE

...
Narretz added a commit to Narretz/angular.js that referenced this issue Nov 14, 2017
This brings the validation in line with HTML5 validation, i.e. what the user has entered
is validated, and not a possibly transformed value.

Fixes angular#12761

BREAKING CHANGE

`input[type=number]` with `ngModel` now validates the input for `max`/`min` against
the `ngModelController.$viewValue` instead of the against the `ngModelController.$modelValue`.

This affects apps that use `$parsers` or `$formatters` to transform the input / model value.

IF you rely on the $modelValue validation, you can overwrite the `min`/`max` validator, as in the
following example directive defintion object:

```
{
  restrict: 'A',
  require: 'ngModel',
  link: function(scope, element, attrs, ctrl) {
    var minValidator = ctrl.$validators.max;

    ctrk.$validators.max = function(modelValue, viewValue) {
      return minValidator(modelValue, modelValue);
    };
  }
}
```
Narretz added a commit that referenced this issue Nov 17, 2017
This brings the validation in line with HTML5 validation, i.e. what the user has entered
is validated, and not a possibly transformed value.

Fixes #12761
Closes #16325

BREAKING CHANGE

`input[type=number]` with `ngModel` now validates the input for the `max`/`min` restriction against
the `ngModelController.$viewValue` instead of against the `ngModelController.$modelValue`.

This affects apps that use `$parsers` or `$formatters` to transform the input / model value.

If you rely on the $modelValue validation, you can overwrite the `min`/`max` validator from a custom directive, as seen in the following example directive definition object:

```
{
  restrict: 'A',
  require: 'ngModel',
  link: function(scope, element, attrs, ctrl) {
    var maxValidator = ctrl.$validators.max;

    ctrk.$validators.max = function(modelValue, viewValue) {
      return maxValidator(modelValue, modelValue);
    };
  }
}
```
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

6 participants