Open accordion panel on validation error

一曲冷凌霜 提交于 2019-12-03 08:53:48

To solve the specific problem in your question, you only have to provide a an invalidHandler callback function that calls the activate() method of the accordion widget to open the first pane:

$("#validate_form").validate({
    // your options,
    invalidHandler: function(form, validator) {
        if (validator.numberOfInvalids() > 0) {
            $("#accordion").accordion("activate", 0);
        }
    }
});

That said, handling the general case (invalid elements on any pane) and switching to the appropriate pane would arguably be better. To do that, we have to fetch the first invalid element from the invalidHandler callback. We can match the errorClass used by the validation engine (error by default), however we cannot blindly match that because that class is also applied to the error message labels. Restricting the results with a :input selector will help us here.

From there, we can use closest() to match the ancestor accordion pane, and index() to obtain its index relative to the other panes, which leads us to the following code:

$("#validate_form").validate({
    // your options,
    invalidHandler: function(form, validator) {
        if (validator.numberOfInvalids() > 0) {
            validator.showErrors();
            var index = $(":input.error").closest(".ui-accordion-content")
                                         .index(".ui-accordion-content");
            $("#accordion").accordion("activate", index);
        }
    }
});

Update: We also have to call showErrors() explicitly in our invalidHandler, since this function is responsible for decorating the invalid elements with the error class in the first place, but is normally only called afterwards. (Source: http://forum.jquery.com/topic/jquery-validate-invalidhandler-is-called-before-the-errors-are-shown-maybe-better-vice-versa.)

The API has changed slightly, here is a working example based on the selected answer for anyone in the future. Note the ignore which is needed to prevent the hidden fields in an accordion from being overlooked by the validator.

$('form').validate({
    invalidHandler: function(event, validator) {
        if (validator.numberOfInvalids() > 0) {
            validator.showErrors();
            // Open accordion tab with errors
            var index = $(".has-error")
                .closest(".ui-accordion-content")
                .index(".ui-accordion-content");
            $(".accordion").accordion("option", "active", index);
        }
    },
    ignore: [],
});

For those who are using MVC, the invalidHandler is created for you. When I tried overriding it (from https://github.com/jzaefferer/jquery-validation/issues/765)

$form.off('invalid-form.validate')
                .on('invalid-form.validate', newInvalidHandler);

The form would always submit.

My solution is to pull out the function and call it when the submit is clicked. I also had to pull out the ignore=[]

function ShowPanel() {
    var validator = $("form").validate();
    if (validator.numberOfInvalids() > 0) {
        validator.showErrors();
        var index = $(".input-validation-error")
                    .closest(".ui-accordion-content")
                    .index(".ui-accordion-content");
        $("#accordion").accordion("option", "active", index);
    } 
}

$("#Save").click(function () { if (!$("form").valid()) { ShowPanel(); } });

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