Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Open accordion panel on validation error

I am using jQuery accordion to split my forms into several panels and jQquery validation to check the required fields. It works great to show errors in validated fields as long as they are in the open panel.

An example. Let's say I have tree accordion panels and on the first I have two form fields that needs to be validated. Now, if the visitor switch to panel two or three and submiting the form without without filling in the required fields on panel one I want the first accordion panel to open up and show the errors.

Does anybody know a way to make this work?

This is the code I'm using today:

$(document).ready(function() {
$("#accordion").accordion({
    autoHeight: false,
    navigation: true,
});

$("#validate_form").validate({
    rules: {
        page_title: "required",
        seo_url: "required",
        AccordionField: {
            required: true
        }
    },
    ignore: [],
    messages: {
        page_title: "Please enter a page title",
        seo_url: "Please enter a valid name"
    }
 }); 
});
like image 471
perqedelius Avatar asked Jul 14 '12 00:07

perqedelius


1 Answers

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.)

like image 90
Frédéric Hamidi Avatar answered Oct 18 '22 14:10

Frédéric Hamidi