struts2struts2-jqueryblockuijquery-blockuistruts2-jquery-plugin

BlockUI Not Working Before Form Validation


I have a form that is being submitted using an sj:submit tag from the struts2-jquery plugin. The submit button is setup with a validateFunction and an onAfterValidationTopic. I'm trying to block the form using the jquery BlockUI when a user saves this form via the sj:submit. The problem is that the BlockUI does not turn on until after validation has completed. Since this form is quite extensive and validation takes a second, this gap in time is extremely noticeable to a user.

BlockUI is being invoked via a javascript method added to the button's onClick parameter. I have set the fadeIn to 0 so it should be executing synchronously.

Through breakpointing, I have determined that the BlockUI is called before any of the struts2-jquery validation methods, but the block is still not appearing until after the form is validated and it's either submitted or validation warnings are flagged.

My order of operations should be to block the UI via the onClick parameter, have the struts2-jquery plugin submit the form for validation, then fire my AfterValidationTopic which will unblock the UI if the validation was unsuccessful. All those steps are happening in the correct order, except that I don't see the UI being blocked. I'm at a loss as to why this would be the case. I went so far as to try and add a $.blockUI call in the jquery.struts2.js file into the $.elem.click function with the same results. BlockUI is being invoked, but I'm not seeing it.

Here's my JSP:

<sj:submit 
    button="true"
    type="button"
    id="save_button"
    cssClass="btn bg-cobalt-300"
    buttonIcon="icon-floppy-disk"
    label="Save"
    validate="true"
    formIds="my_form"
    onAfterValidationTopics="postValidation"
    validateFunction="bootstrapValidation"
    value="%{getText('global.save')}"
    onClick="loadingMaskSave();"
    />

and JS code:

function loadingMaskSave() {
    $.blockUI({
        fadeIn: 0
    });
}

$.subscribe('postValidation', function (event,data) {
    if(event.originalEvent.formvalidate == false) {
        $.unblockUI();
    }
});

Solution

  • I managed to figure out what the problem was. In the validateForm method of the jquery.struts2.js file, the form is being submitted for validation via ajax synchronously. The ajaxSubmit's async parameter is set to false. This causes the browser to lock up completely until after validation finishes, which is why the BlockUI overlay was not displaying. To address this, I updated the $elem.click() code in the formsubmit method. AjaxSubmit now fires asynchronously (with async set to true) and the processing of after validation topics and the actual submission of the form are now handled by AjaxSubmit's complete method. This prevents the browser from being locked up and I can now see the BlockUI overlay before validation begins.

    $elem.click( function(e) {
        var form = $(self.escId(o.formids)),
            orginal = {};
        orginal.formvalidate = true; 
        e.preventDefault();
    
        if (o.validate) {
            var submit = true,
                ajaxSubmitParams = {};
    
            if (!self.loadAtOnce) {
                self.require("js/plugins/jquery.form" + self.minSuffix + ".js");
            }
    
            ajaxSubmitParams.type = "POST";
            ajaxSubmitParams.data = {
                    "struts.enableJSONValidation": true,
                    "struts.validateOnly": true
            };
            if (o.href && o.href !== '#') {
                ajaxSubmitParams.url = o.href;
            }
            else {
                ajaxSubmitParams.url = form[0].action;
            }
    
            if (o.hrefparameter) {
                ajaxSubmitParams.url = ajaxSubmitParams.url + '?' + o.hrefparameter;
            }
    
            ajaxSubmitParams.cache = false;
            //ajaxSubmitParams.forceSync = true;
            ajaxSubmitParams.async = true;
    
            ajaxSubmitParams.complete = function(request, status) {
                var f = $(form[0]),
                    et = request.responseText,
                    errors;
                if ($.isFunction(o.validateFunction)) {
                    if (et && et.length > 10) {
                        submit = false;
                        if(et.substring(0,2) === "/*") {
                            // Handle Validation Errors for all Struts2 versions until 2.2.3.1
                            errors = $.parseJSON(et.substring(2, et.length - 2));
                        }
                        else {
                            errors = $.parseJSON(et);
                        }
                        o.validateFunction(f, errors);
                    }
                }
                else if (StrutsUtils !== undefined) {
                    StrutsUtils.clearValidationErrors(form[0]);
    
                    // get errors from response
                    if(et.substring(0,2) === "/*") {
                        errors = StrutsUtils.getValidationErrors(et);
                    }
                    else {
                        errors = StrutsUtils.getValidationErrors($.parseJSON(et));
                    }
    
                    // show errors, if any
                    if (errors.fieldErrors || errors.errors) {
                        StrutsUtils.showValidationErrors(form[0], errors);
                        submit = false;
                    }
                }
                self.log('form validation : ' + submit);
                orginal.formvalidate = submit;
    
                if (o.onaftervalidation) {
                    $.each(o.onaftervalidation.split(','), function(i, topic) { 
                        $elem.publish(topic, $elem, orginal);
                    });
                }  
    
                if(orginal.formvalidate) {
                    if ( o.href && o.href != "#") {
                        form[0].action = o.href;
                    }
                    form.submit();
                }
            };
    
            form.ajaxSubmit(ajaxSubmitParams);
        }
    
        return false;
    });