11

I need to add an handle to any circumstance where a form validation fails.

I've read this, that explains that I have to add a handler as follows:

$('form').bind('invalid-form.validate', function () {
  console.log('form is invalid!');
});

But this event only fires when I try to submit the form.

I need to handle an event that's fired ANY time the form is post-validated (i.e. element loses focus etc.).

What I'm trying to achieve is, I have a large form (~50 fields), and it's splitted in Bootstrap tabs.
I want, that when there is any new validation failure or success, set or clear an error class in the tab title of the tab that contains the invalid/valid elements. P.S. my question is not on how to set those classes in the tabs. I only want to know what event(s) to handle in order to be notified upon each validation state change in the entire form.

Community
  • 1
  • 1
Shimmy Weitzhandler
  • 101,809
  • 122
  • 424
  • 632
  • There is no such event provided by jQuery or the Validate plugin. You'll have to attach a `focusout`, `blur`, `keyup`, etc to every input element and use the `.valid()` method to test the form. – Sparky Apr 25 '15 at 23:59
  • @Sparky is there an event such as `onvalidated` provided by the unobtrusive validation plugin? – Shimmy Weitzhandler Apr 26 '15 at 00:00
  • I am not very familiar with the `unobtrusive` plugin at all. However within all the thousands of jQuery Validate questions I've seen, I've never seen any custom events described. – Sparky Apr 26 '15 at 00:01
  • 1
    What exactly are you trying to do? Why can't you just use [one of the built-in options](http://jqueryvalidation.org/validate)? – Sparky Apr 26 '15 at 00:03
  • @Sparky with unobtrusive validation you don't call `validate` at all. It sets it all up for you. Anyway I've updated my question with the purpose of my requirement. – Shimmy Weitzhandler Apr 26 '15 at 00:18
  • Yes, I understand that. However, you can use `setDefaults()` to get around the inability to call `.validate()`. – Sparky Apr 26 '15 at 00:20

1 Answers1

8

I need to add a handler to any circumstance where form validation fails.

$('input, textarea, select').on('focusout keyup', function() {
   if ($('form').valid()) {
       // do something
   }
});

I want, that when there is any validation error, set an error class in the tab title that contains the invalid elements.

Well, that's a bit different than what you originally asked about. (Ignore the first half of my answer.)

Use the highlight and unhighlight options along with jQuery DOM traversal to set and unset any class in the DOM you wish. highlight fires when something is invalid and unhighlight fires when it becomes valid. See this answer as an example.

Use the .setDefaults() method to set these options since you're using the unobtrusive-validation plugin and have no direct access to the .validate() method.

Community
  • 1
  • 1
Sparky
  • 98,165
  • 25
  • 199
  • 285
  • I think the `highlight` and `unhighlight` is indeed what I'm looking for. Anyway, Can I call the original `highlight` function from the highlight function I'm setting up? [Here](http://pastebin.com/x5aBLz1s)'re the original function, do I have to copy and paste it in my override script or it exists anywhere? – Shimmy Weitzhandler Apr 26 '15 at 00:50
  • 1
    @Shimmy, whatever you put in there will over-ride the default. – Sparky Apr 26 '15 at 01:03
  • 1
    In other words, you'll need to copy the default function into yours if you want to keep the default behavior. Then built upon it to get your new behavior. – Sparky Apr 26 '15 at 01:11
  • The problem is that I need to set the tabs' titles only after validation has finished for all elements. Otherwise it gets the valid state of its last element validation state. So again, I find myself back with the original question. I believe I'll have to know how and when the unobtrusive validation is triggered. – Shimmy Weitzhandler Apr 26 '15 at 01:48
  • @Shimmy, again, review the options. The `invalidHandler` fires on an invalid form. – Sparky Apr 26 '15 at 01:59
  • 1
    I ended up using the `invalid-form.validate` event, which is the unobtrusive validation event that is fired out from the under the hood jquery `invalidHandler`. Unfortunately I missed something in the function that made it not to work. I should haven't asked this question and wasted your time at all. Anyway your answer taught me a lot on how jquery validation works. – Shimmy Weitzhandler Apr 26 '15 at 02:02
  • anyway my question is still not answered. That event only stops when submitting form, and doesn't work at all for client validation. Using the proposals in your answer will again trigger an event for each field - I have to get a summary of all invalid fields, and all fields that just became valid (to clear their error state). – Shimmy Weitzhandler Apr 26 '15 at 21:32
  • BTW, [here](http://pastebin.com/raw.php?i=USxLJXdg)'s the source code of unobtrusive validation used in ASP.NET MVC. – Shimmy Weitzhandler Apr 26 '15 at 21:40
  • @Shimmy, `invalidHandler` only fires on the `submit` if any part of the form is invalid. `submitHandler` only fires on the `submit` if the entire form is valid. `highlight/unhighlight` fire on a field-by-field basis as each becomes invalid/valid. The `.valid()` method can be called programmatically to test a single field or the entire form. That's it. I really don't know what else to tell you. – Sparky Apr 27 '15 at 00:29
  • there is something else I realize now. The global event only fires for visible elements! Meaning that all the fields in other tabs are not validated, and the real issue is that I have some areas that I hide intentionally and those don't have to be validated... I'm thinking how can I: 1) disable validation skipping for invisible fields 2) unless they `disabled`. – Shimmy Weitzhandler Apr 27 '15 at 01:30
  • `ignore: []` will enable validation on hidden fields. – Sparky Apr 27 '15 at 01:49
  • Please include in your answer for further reference. I'm gonna use `ignore: ':disabled'`. I hope it's gonna work. – Shimmy Weitzhandler Apr 27 '15 at 01:58
  • @Shimmy, I thought you did **not** want to ignore hidden fields? If you tell it to ignore `:disabled`, then it's going to ignore the disabled fields. If you tell it to ignore nothing, `[]`, then it will ignore nothing and validate everything. – Sparky Apr 27 '15 at 02:10
  • I want it to validate `:hidden` fields, but not `:disabled` ones. – Shimmy Weitzhandler Apr 27 '15 at 02:12
  • 1
    @Shimmy, [looking at the source code](https://github.com/jzaefferer/jquery-validation/blob/master/src/core.js#L553), `disabled` fields are always going to be ignored no matter what... it's hard coded to bypass the `ignore` option entirely. So `ignore: ':disabled'` is effectively the same as `ignore: []`. See: http://jsfiddle.net/amy4sven/ – Sparky Apr 29 '15 at 14:36
  • I actually changed to `ignore: ':disabled'` and the event didn't fire at all. I'm gonna try replacing with empty array. – Shimmy Weitzhandler Apr 30 '15 at 00:06
  • @Shimmy, I don't think `:disabled` is a valid selector. Since skipping disabled fields is already built into the plugin, `ignore: []` is the best way to go. – Sparky Apr 30 '15 at 00:50
  • I've found a weird issue in the validator, see this [pull request](https://github.com/jzaefferer/jquery-validation/pull/1474). As a workaround I've used `ignore: "input[type='hidden'],fieldset[disabled] *"`. – Shimmy Weitzhandler Apr 30 '15 at 23:03
  • I've found the issue in jQ validation and added a [pull request](https://github.com/jzaefferer/jquery-validation/commit/f37c2d8131ca0e3c2af0093f6fd9d2c40c282663) which was committed and will up on next version. – Shimmy Weitzhandler May 12 '15 at 12:32