-
Notifications
You must be signed in to change notification settings - Fork 27.5k
fix(input): validate minlength/maxlength for non-string values #7968
Conversation
Thanks for the PR! Please check the items below to help us merge this faster. See the contributing docs for more information.
If you need to make changes to your pull request, you can update the commit with Thanks again for your help! |
I'm going to leave them open for now because of the different approach taken (view value vs stringified model value). I'm undecided on which is the better approach |
@caitp The order of processing is $viewValue -> $parsers -> $validators, so validation will possibly be wrong when comparing with viewValue, no? |
Define "wrong"? If your view value is like |
I feel like you'd generally expect the typed value to have to fit into the maxlength, because people aren't thinking about what the data looks like under the hood, so I think comparing the $viewValue for non-string models should be fine |
Maybe we should always be testing the $viewValue rather than model value, in that case |
Hmm, with the $validators, the role of $parsers is kind of undefined, but I tihnk @matsko had his reasons to use the parsed model value for validation. With something like ui-mask, http://angular-ui.github.io/ui-utils/#/mask, it's imperative that the value that is validated is parsed, because the viewValue contains characters that do not end up in the model and will distort the validation result. From a developer's perspective it also doesn't make much sense to validate the model, then parse and commit it, possibly making it in invalid again in the process. The whole thing is veeery complex. I always have the feeling I'm only looking at half the cases that need to be covered. |
maybe people shouldn't use maxlength with ui-utils --- maxlength validation should validate what the user enters, not some transformed value that might look totally different, heh |
That's a good point because the mask will do it's own validation anyway ... it also wouldn't work with objects (say type="date"). Maybe it's okay. |
I think we should merge this (maybe after validation settles), but convert the viewValue to string beforehand. If the model is a |
There is a question about applying this directives. According to MDN documentation:
I think we should apply same rule here. There is not much sense in validating length for a number input, can use the |
@airato Thanks for the input again. While ng-maxlength is not documented for date etc., it's now a standalone directive and can be applied to every input. We should just document that this directive will always validate the input value that's visible to the user ($viewValue), and internally convert the $viewValue to a string before validating it. |
Since this isn't entirely clear from the initial description: |
It's not just for type=number, because the fix is to look at the viewValue rather than modelValue. yes. |
Just change the variable names. Otherwise LGTM. |
Use viewValue for minlength/maxlength validation if model value is not a string. This allows ngMinlength and ngMaxlength to be used for number inputs. Closes angular#7967 Closes angular#8811
I think you got them all @caitp However, I am not entirely sure this is completely correct. Why aren't we simply always checking the $viewValue? If someone parses $viewValue into a different length $modelValue string (for whatever reasons), the result may be unexpected to the user (or developer). |
@Narretz your points are valid but I think that the natural use of the minlength attribute is for comparing user entered data on Thinking about this some more, we should always compare the |
There are at least two cases where the $viewValue in type=text can be a number. First, when the value comes from the scope, and second when it's set programmatically with $setViewValue(). http://plnkr.co/edit/euEvTIbIxr1piZ093SnC?p=preview Maybe $setViewValue should convert everything to string? But that probably wouldn't catch all cases. Or we could simply always do the conversion in the min/maxlength validator. |
@Narretz |
I think that it's safe to say that But for when the model is assigned we should be doing this: function textInputType(scope, element, attr, ctrl, $sniffer, $browser) {
ctrl.$formatters.push(function(value) {
return ctrl.$isEmpty(value) ? value : value.toString();
});
baseInputElement(scope, element, attr, ctrl, $sniffer, $browser);
} |
I just created this fiddle to file this exact issue, guess I should've searched here before because you guys are one step ahead 😄 Hoping to see this merged. Thanks for the good work! |
@matsko Will this formatter be applied to all input types that are text-like, i.e. also url, email etc.? They all have the same requirement I think. |
@Narretz yes. It applies to: blank (when no type is set), text, email and url. |
Use viewValue for minlength/maxlength validation if model value is not a
string. This allows ngMinlength and ngMaxlength to be used for number inputs.
Closes #7967