How to get unobtrusive jquery remote validator to perform async..?

不羁的心 提交于 2019-12-04 04:32:48

It's kind of hacky, but I would suggest trying the following.

First, hide the submit button with display="none", and show your own "submit" button, which runs your script above.

Second, in your page, add a flag var [var remotePending = false;] and a variable for a setInterval call [var intervalPending;], and in your script, set the flag to true, then call the following function using intervalPending = setInterval('remoteCheck()', 200);

function remoteCheck() {
    if ($.validator.pendingRequest == 0) {
        // requests are done
        // clear interval
        clearInterval(intervalPending);
        // re-enable our "submit" button

        // "click" the hidden button
        $("#hiddenSubmit").click();
    }
    // we will try again after the interval passes
}

This will allow you to wait for the completion of the pending remote validation, then proceed normally. I have not tested, so you may have to play around to get this working as you want.

I'm a bit late to the table with this, but I stumbled across this question while trying to solve a similar problem. I too didn't want to use Interval, so I cooked up a different solution and thought it might be worth detailing here for others.

In the end I decided to override the jQuery validator startRequest and stopRequest methods in order to add my own logic. After executing my own logic I simply call the old validator methods.

// Extend jQuery validator to show loading gif when making remote requests
var oldStartRequest = $.validator.prototype.startRequest;
$.validator.prototype.startRequest = function (element) {
    var container = $('form').find("[data-valmsg-for='" + element.name + "']");
    container.addClass('loading');       

    oldStartRequest.apply(this, arguments);
};

var oldStopRequest = $.validator.prototype.stopRequest;
$.validator.prototype.stopRequest = function (element) {
    var container = $('form').find("[data-valmsg-for='" + element.name + "']");
    container.removeClass('loading');

    oldStopRequest.apply(this, arguments);
};

All I wanted to do for my purposes was simply add a 'loading' css class to an adjacent validation message field in order to show a loading gif, but you could easily extend this to enable/disable a button, etc.

I found myself puzzling over this last night and after trying various approaches I ended up with an evolution of counsellorbens. Since counsellorbens didn't work straight out of the box I thought I'd share it to prevent others having the same headache. It's not as "clean" a solution as I would like (I really hate using intervals). But it seems to suffice.

var iIntervalId = null;

//
// DECLARE FUNCTION EXPRESSIONS
//

//==============================================================================
// function that triggers update when remote validation completes successfully
//==============================================================================
var fnPendingValidationComplete = function () {

  var validator = $("#frmProductType").data("validator");
  if (validator.pendingRequest === 0) {

    clearInterval(iIntervalId);

    //Force validation to present to user (this will not retrigger remote validation)
    if ($("#frmProductType").valid()) {

      alert("valid - you can submit now if you like");

    }
    //else { alert("invalid"); }
  }
  //else { alert("NOT YET"); }
},

//==============================================================================
// Trigger validation
//==============================================================================
fnTriggerValidation = function (evt) {

  //Remove any cached values to ensure that remote validation is retriggered
  $("#txtProductType").removeData("previousValue");

  //Trigger validation
  $("#frmProductType").valid();

  //Setup interval which will evaluate validation (this approach because of remote validation)
  iIntervalId = setInterval(fnPendingValidationComplete, 50);
};

fnTriggerValidation();

I ended up solving this, but the button disable / wait image show only happen when there is a valid submitted form. It's okay though, since multiple invalid form submissions are idempotent, the user can click as much as they want. (Also, the remote validation action method is cached against its parameter values.)

$(function () {
    $('form').bind('invalid-form.validate', function () {
        $('form').each(function () {
            $(this).find(
                '[data-app-form-submitting-icon="true"]').hide();
            var button = $(this).find(
                'input[type="submit"][data-app-form-submit-button="true"]');
            setTimeout(function () {
                button.removeAttr('disabled');
            }, 1);
        });
    });
    $('form').live('submit', function (e) {
        $(this).find('[data-app-form-submitting-icon="true"]').show();
        var button = $(this).find(
            'input[type="submit"][data-app-form-submit-button="true"]');
        setTimeout(function () {
            button.attr('disabled', 'disabled');
        }, 0);
    });
});

This is a little hacky too, but when I didn't use setTimeout, the submit action was never firing the invalid handler.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!