-1

I am creating an ASP.NET Core web app, which uses jQuery Validate for client-side validation, and jQuery Unobtrusive Validation to configure validation using HTML5 data-* attributes. I have a text input, and I am handling its blur event via event delegation. The code looks something like this:

$(document).ready(() => {
    $('#my-container').on('blur', '.my-input-class', (event) => {
        var isValid = $(event.target).valid();
        // Do stuff with isValid's boolean value
    });
});

Unfortunately, if I enter an invalid value in the input then tab out, then isValid is still set to true. But if I click the input and click off again, then this second blur event correctly sets isValid to false.

I think somehow my blur handler is happening before the jQuery Validate blur handler, presumably because I'm using event delegation rather than directly handling input.onblur(). Event delegation is necessary though because the input is generated dynamically, after validate() has already been called. I've seen some posts suggest calling validator.element(), but because ASP.NET Core uses the unobtrusive validation library, I never have access to the validator object returned by validate(). So...

TL;DR

How do I ensure that valid() returns the correct value in a delegated event handler when using the unobtrusive validation library?

EDIT

While trimming up my page's HTML to post, I got an idea for what the issue might be. My input is actually using remote validation with the data-val-remote attribute. Perhaps my blur handler is just being called before the remote validation has sent a response, so the plugin thinks the input is still valid?

Camilo Terevinto
  • 31,141
  • 6
  • 88
  • 120
Rabadash8820
  • 2,328
  • 3
  • 27
  • 49

2 Answers2

0

It looks like the issue was indeed with mixing remote validation with a blur handler. I have since started using a more event-driven approach to validation.

$.validator.setDefaults({
    highlight: (element, errorClass, validClass) =>
        onValidating(element, false, errorClass, validClass),
    unhighlight: (element, errorClass, validClass) =>
        onValidating(element, true, errorClass, validClass)
});

function onValidating(element, valid, errorClass, validClass) {
    var e = new CustomEvent("validating", {
        detail: {
            valid: valid,
            errorClass: errorClass,
            validClass: validClass
        },
        bubbles: true
    });
    element.dispatchEvent(e);
}

The highlight and unhighlight callbacks provided to jQuery Validate's setDefaults() method each raise a synthetic validating event, with the valid property set to false or true, respectively. These events can then be subscribed to anywhere else in the app, allowing one to move onblur actions to those new handlers. In my case:

$('#my-container').on('validating', e => {
    var isValid = e.detail.valid;
    // Do stuff with isValid's boolean value
});

Because this technique uses setDefaults() and not validate(), it can be used with ASP.NET Core's unobtrusive validation plugin!

Rabadash8820
  • 2,328
  • 3
  • 27
  • 49
-1

You are using event.target...

You should console.log it. I'm pretty sure that on a click outside the input, but inside the form, the validation is working.

But on "tab-out", which I guess means TAB keypress... There is no target attribute in the event.

So just change :

$(document).ready(() => {
    $('#my-container').on('blur', '.my-input-class', (event) => {
        var isValid = $(this).closest("form").valid();
        // Do stuff with isValid's boolean value
    });
});
Louys Patrice Bessette
  • 33,375
  • 6
  • 36
  • 64
  • Yes tab referred to TAB (I didn't know you could use keyboard glyphs here!). I just tried hitting TAB, clicking off within the form, and clicking off outside the form, but it looks like `e.target` is always defined. And whether I call `valid()` on the form or the input, I still get `true` for invalid values on the first blur. – Rabadash8820 Sep 08 '17 at 19:32
  • Post your HTML then... **The produced HTML please!** That will make your question ["Minimal, Complete and Verifiable Example"](https://stackoverflow.com/help/mcve) and maybe I will be able to answer differently. **And if** `.valid()` is a custom named function, also post it. – Louys Patrice Bessette Sep 08 '17 at 19:35
  • While trimming up my page's HTML to post, I got an idea for what the issue might be. My input is actually using [remote validation](https://jqueryvalidation.org/remote-method/) with the `data-val-remote` attribute. Is it possible that my blur handler is just being called before the remote validation has sent a response, so the plugin thinks the input is still valid? – Rabadash8820 Sep 08 '17 at 20:01
  • mmm... Sure, the remote validation delay to get the response may be in cause. What is `.valid()` function? Maybe there a `complete` or `success` callback which could be used... – Louys Patrice Bessette Sep 08 '17 at 20:35
  • The valid() function is just a vanilla jQuery Validate method, there is a link to it in my TL;DR above. I've searched for validation events in the plugin before and from what I can tell there are none. The answer to this [previous SO post](https://stackoverflow.com/questions/7247250/jquery-validation-not-waiting-for-remote-validation-to-return-true-considers-fo) describes a way to make remote validation synchronous so that calls to `valid()` work as expected, but getting it to work with ASP.NET Core's unobtrusive library may be difficult – Rabadash8820 Sep 08 '17 at 20:42