-
Notifications
You must be signed in to change notification settings - Fork 27.5k
Promise-based validations & Multi-stage validation API for ngModel #8267
Conversation
Baaaam! |
Hey @matsko I will check this out tomorrow, but it would be nice if you could explain the PR a little more, what it does and how it integrates with current validation etc. |
@matsko I believe this will not work properly in case an async validator is run twice due to input change and gets resolved out of order (old value validation is resolved after new value validation is resolved). I'll try to send a test that fails later on today. |
In general, I think we should think about reseting the |
The failing test... iit('should ignore old async validator promises that get resolved', inject(function($q) {
var defer, oldDefer, newDefer;
ctrl.$addAsyncValidator('async', function(value) {
defer = $q.defer();
return defer.promise;
});
scope.$apply('value = ""');
oldDefer = defer;
scope.$apply('value = "123"');
newDefer = defer;
newDefer.reject();
scope.$digest();
oldDefer.resolve();
scope.$digest();
expect(ctrl.$valid).toBe(false);
expect(ctrl.$invalid).toBe(true);
expect(ctrl.$pending).toBeUndefined();
})); |
I like the PR a lot, but I think we should first solve the open issues with the current validation before we add another feature, especially first convert all the validations in $parsers to $validators to see if the new architecture is sufficient. |
Can you explain what the difference between native and sync is? The validators in this PR are now changed to native, but when I hear native, I think of the Constaint Validation API, not our own validators (which mimic the CV, but use own regex etc.) |
@shahata I think the failing test is correct (the failure is expected), because it should always ignore the previous async' response and only consider the latest one. This wouldn't be an issue normally if we could cancel promises. |
@Narretz this solution is actually to provide a better foundation to fix some of the native-based validators. Native validators are stuff like required, maxlength, minlength and so on. Async are validators that return promises. The number validator will be changed in a later commit once I can ensure it doesn't break anything. The date stuff still needs to be converted over in a smart way. |
@Narretz do you still need a more detailed explanation of it? |
@matsko I think you misunderstood my comment. The problem is that with the test I sent you, the controller remains in pending validation state even after both promises are resolved. The root cause of this is that you consider the pending validation complete only if I proposed solving this by resetting I adjusted the unit test above to the latest semantics in this PR so you can reproduce easily. |
@shahata I see. The code is now up to date and your spec has been put in. |
@matsko - Has there been a design discussion about this with the core team? How does this deal with the numerous issues that have been discussed recently around things like |
we had a meeting specifically about the features implemented by this PR, I haven't reviewed this one yet though. I think we're all on the same page about what is needed though, I hope |
* method for resolve and a status level of `400` in order to reject the validation. | ||
* | ||
* ```js | ||
* ngModel.$asyncVaidators.usernameTaken = function(modelValue, viewValue) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
typo in "asyncVaidators"
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the name of the validator should likely be something like "uniqueUsername"- you don't validate the the username is taken :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed
var value = ctrl.$viewValue || ''; | ||
if (ctrl.$pending && ctrl.$pending[validationErrorKey] && currentValue === value) { | ||
delete ctrl.$pending[validationErrorKey]; | ||
pendingCount = Object.keys(ctrl.$pending).length; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If all you actually care about is if ctrl.$pending
is empty or not, it seems redundant to have a pendingCount
Hi @matsko,
@matsko @caitp Why do we need to extra phase for native validators again? The case that we have an |
@tbosch because when we have a native ValidityState, we need to check those flags in a specific order (and abort checking them in the case of certain failures) --- in order to avoid over-reporting errors --- and we really need to always run those first, because the 'badInput' error is going to cause user validators to behave unexpectedly. |
Yes, we should check But why should we run |
@matsko I went though all of the open issues that were tagged with To validate your design (e.g. how native validation is handled), it would probably be best to solve them in this PR as well, as each one of those seems really simple. Otherwise we would land an abstract API and would detect later on that we need more changes to it... |
@tbosch thank you for going through all the code. Yes I agree that this PR should contain the additional commits that fix the existing list of validation bugs. Regarding the "native" validators. The point is to detect the errors early on in the Regarding the date validators. Yes I will try and get them into the $validators pipeline today, but the issue is that the validators are run after the parsers/formatters. This means that there still needs to be some level of value checking within the date parser and, if the value is set to null within it, then that null value will be processed as invalid within any existing native validators before the date validator is executed. |
Re date validators: Re native validators: For the other native validators like required, pattern, ...: I still don't Sent from my iPhone On Aug 4, 2014, at 6:30 PM, "Matias Niemelä" [email protected] @tbosch https://github.com/tbosch thank you for going through all the Regarding the "native" validators. The point is to detect the errors early Regarding the date validators. Yes I will try and get them into the — |
1bdab6b
to
5f731a5
Compare
With this commit, ngModel will now handle parsing first and then validation afterwards once the parsing is successful. If any parser along the way returns `undefined` then ngModel will break the chain of parsing and register a a parser error represented by the type of input that is being collected (e.g. number, date, datetime, url, etc...). If a parser fails for a standard text input field then an error of `parse` will be placed on `model.$error`. BREAKING CHANGE Any parser code from before that returned an `undefined` value (or nothing at all) will now cause a parser failure. When this occurs none of the validators present in `$validators` will run until the parser error is gone.
…lidations This commit introduces a 2nd validation queue called `$asyncValidators`. Each time a value is processed by the validation pipeline, if all synchronous `$validators` succeed, the value is then passed through the `$asyncValidators` validation queue. These validators should return a promise. Rejection of a validation promise indicates a failed validation.
5f731a5
to
04ab51c
Compare
No description provided.