jpillora / jquery.async.validator

A jQuery plugin for fully customisable asynchronous client-side validations.
http://jpillora.github.com/jquery.async.validator/
1 stars 0 forks source link

Prevalidate still shows initial prompts with multiple failing fields. #5

Open matthewtuck opened 11 years ago

matthewtuck commented 11 years ago

If you have several fields that fail during prevalidation, the subsequent ones will still get a prompt. This is with stock standard required checks without any groups.

Excerpt:

asyncValidator: FormExecution: 76f3: ValidationForm: form: exec fields #2
asyncValidator: RuleExecution: e14e: ValidationField: energy_response[field1]: Failed
asyncValidator: FieldExecution: c005: ValidationField: energy_response[field1]: Failed
asyncValidator: FormExecution: 76f3: ValidationForm: form: Failed
asyncValidator: RuleExecution: ece5: ValidationField: energy_response[field2]: Failed
asyncValidator: FieldExecution: b011: ValidationField: energy_response[field2]: Failed

This is due to parallelize rejecting as soon as one task fails. The other tasks aren't aborted, and so continue after showPrompt has been turned back on.

Note this code:

this.validate(function() {
    opts.showPrompt = true;
});

If you wanted a boolean result derived from AND logic, I'd expect to just abort the other tasks. But for a prevalidate determining the status of all fields it doesn't seem right to do that.

As such I made the fail logic pretty much the same as the success logic and this fixes the problem. Not thoroughly tested but my final code was:

diff --git a/vendor/assets/javascripts/jquery.async.validator.prompt.js b/vendor/assets/javascripts/jquery.async.validator.prompt.js
index f79c14b..7574627 100644
--- a/vendor/assets/javascripts/jquery.async.validator.prompt.js
+++ b/vendor/assets/javascripts/jquery.async.validator.prompt.js
@@ -452,20 +452,26 @@ $.Deferred.parallelize = function(fns) {

   var d = $.Deferred(),
       n = 0, i = 0, l = fns.length,
-      rejected = false;
+      rejection = null;

   if(!$.isArray(fns) || l === 0)
     return d.resolve();

   function pass(result) {
-    n++;
-    if(n === l) d.resolve(result);
+    maybe_resolve();
   }

   function fail(result) {
-    if(rejected) return;
-    rejected = true;
-    d.reject(result);
+    if (rejection == null) rejection = result;
+    maybe_resolve();
+  }
+
+  function maybe_resolve() {
+    n++;
+    if(n === l) {
+      if (rejection == null) d.resolve();
+      else d.reject(rejection);
+    }
   }

   //execute all at once
matthewtuck commented 11 years ago

In other words, it seems you want a parallelisation barrier.