0

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();
    }
});
Curtis Snowden
  • 407
  • 1
  • 4
  • 20
  • What happens if just call `blockUI`? E.g. in ready block. – Aleksandr M Apr 17 '17 at 18:53
  • The ready block? – Curtis Snowden Apr 17 '17 at 18:55
  • [**The** ready](https://api.jquery.com/ready/). – Aleksandr M Apr 17 '17 at 18:56
  • Right, sorry. It works perfectly fine. I invoke $.blockUI() without options in the $(window).ready() area, and the overlay displays as expected, with the default message of 'Please wait...'. BlockUI is working in other areas. For example, on the same form, I have BlockUI started the moment the page is loaded to account for sj:select elements being populated from the server. $.unblockUI is called once all of my sj:select elements finish loading, via the onSuccessTopics. That works perfectly fine. – Curtis Snowden Apr 17 '17 at 19:04
  • Try with some before topic instead of `onClick`. – Aleksandr M Apr 17 '17 at 19:10
  • That doesn't work at all, I'm afraid. I add onBeforeTopics="beforeValidation" to the sj:submit element and subscribe that as a function that executes $.blockUI(). The subscribed function beforeValidation is never even executed. – Curtis Snowden Apr 17 '17 at 19:15
  • If the blocking works as expected why are you waiting? – Roman C Apr 17 '17 at 21:30
  • The blocking wasn't working as expected. The overlay could not be seen until after validation had completed. – Curtis Snowden Apr 17 '17 at 23:00

1 Answers1

1

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;
});
Curtis Snowden
  • 407
  • 1
  • 4
  • 20