Rabadash8820 Rabadash8820 - 1 year ago 148
Javascript Question

jQuery valid() Gives Wrong Value in Delegated Blur Handler

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?

Answer Source

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!

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download