Ivanka Todorova
Ivanka Todorova

Reputation: 10219

Validating Bootstrap radio buttons on mouseup/keyup

I have a bit complex form (includes inputs, textareas, custom selects, etc). I want to perform validation (just to check whether all fields are empty or not). Nothing more.

But I find it difficult to validate whether a radio button was selected or not. I'm using Twitter Bootstrap and I have styled the radio buttons through their javascript and css (btn-group).

I want whenever a user types or clicks something to run the script which checks whether the field is empty or not.

I will post a jsFiddle link below which reproduces my problem. The javascript I use is a bit different, because I want to perform the check only to inputs in the current tab.

$('body').on('keyup mouseup ', 'li, label, input, textarea, select', function (e) {
    var tabId = $(this).closest('.tab-pane').attr('id');
    var inputs = $('#' + tabId + ' :input');
    var errors = {};
    inputs.each(function (i, element) {
        if ($(element).attr('name') !== undefined) {
            if ($(element).attr('type') !== 'radio') {
                if ($.trim($(element).val()) === '') {
                    errors[i] = $(element).attr('name');
                }
            } else {
                if ($('.active', $("input[name='" + $(element).attr('name') + "']").closest('.btn-group')).length <= 0) {
                    errors[i] = $(element).attr('name');
                }
            }
        }
    });
    console.log(errors);
    if (!$.isEmptyObject(errors)) {
        $('a[href="#' + tabId + '"]')
            .html("<i class='red ace-icon fa fa-times bigger-120'></i> " + $('a[href="#' + tabId + '"]').text());
    } else {
        $('a[href="#' + tabId + '"]')
            .html("<i class='green ace-icon fa fa-check bigger-120'></i> " + $('a[href="#' + tabId + '"]').text());
    }
});

http://jsfiddle.net/gzwyddrc/ To reproduce the problem:

  1. Click on the text field (An alert will tell you that the form is not valid) - OK

  2. Close the alert and type one letter (otherwise you will be annoyed by the alert). The alert will pop out again telling you that the form is still invalid. - OK

  3. Now click on one of the radio buttons. The alert will still tell you that the form is invalid. - NOT OK

  4. If you click on either the text field or one of the radio buttons the alert has something else to say: THE FORM IS VALID! - NOT OK

I believe I've misused the events that I binded to the elements I want to fire that validation.

Upvotes: 1

Views: 778

Answers (1)

pid
pid

Reputation: 11607

Ok, I've looked into this, but there were quite a lot of changes I had to make.

This is the code:

$("form").on("keyup mouseup", function (ev) {
    var selected, errors = [];

    setTimeout(function () {
        $("input,select").each(function (i, v) {
            var e;

            e = $(v);
            if (e.attr("name") === undefined) return;

            switch (e.attr("type"))
            {
                case "radio":
                    selected = false;
                    e.closest(".btn-group").find("input[type=radio]").each(function (i, v) {
                        if ($(v).closest("label").hasClass("active"))
                        {
                            selected = true;
                        }
                    });

                    if (!selected) {
                        errors.push(e.attr("id"));
                    }
                    break;
                default:
                    if ($.trim(e.val()) === "")
                    {
                        errors.push(e.attr("name")); // should be id?
                    }
                    break;
            }
        });

        if (errors.length > 0) {
            alert("ERRORS: " + errors);
        }
    }, 10);
});

The changes I made are:

  • event handlers are attached to the form, this is more convenient especially for multi-form pages (imagine a separate form on the top for login);
  • the selector also considers select (dropdowns) a possible input field;
  • minor name/order changes to make it more readable;
  • the switch replaces the if, because you will encounter more input types further along (switch scales better than if..else);
  • replaced the error object with an error array on which to push() errors;
  • when a radio group is unselected, the whole group is invalid, not any single one of the radio buttons nested, so the check should be based on the group as a whole (see use of selected flag);
  • for radio buttons the active class is toggled on the label not on the input;
  • finally, the most important feature you'll already have noticed:

Bootstrap itself uses events and JS to toggle the active class, so if you check it right away the label will never have the active class -- to counter this, I inserted a setTimeout() that will fire validation 10 ms later (which still is instantly for humans) so that Bootstrap has all the time to make an update pass over the form before we go in and validate.

I checked it thoroughly in a fiddle, so I'm quite confident it works well and opens up many possibilities you've probably envisioned.

Upvotes: 1

Related Questions