Oleg Belousov
Oleg Belousov

Reputation: 10111

jQuery validator hides errors on each submit regardless of whether the fields are valid or not

SRS: I need to validate a form which consists of 5 email fields. the rules are as following: At least one of those fields, regardless of the placement and the order should be a valid email.

my code so far:

    $("#frm_referral_email").validate({
    rules: {
        referral_invitation_text: {required: true}
    },
    messages: {
        referral_invitation_text: "Enter your message"
    },
    // the errorPlacement has to take the table layout into account
    errorPlacement: function(error, element) {
            if (error.html() != "")
                error.appendTo( element.parent().next() );
    },
    // specifying a submitHandler prevents the default submit, good for the demo
    submitHandler: function() {
        // if(!("#frm_referral_email").valid())
        //  return false;
        var valid = true;
        $('.referral_email').each(function(){
            if($(this).hasClass('error')){
                valid = false;
                return true;
            }
        });
        if(!valid){
            return false;
        }
        var coworker_invitation_text = $('#frm_referral_email #referral_invitation_text').val();
        var coworker_invitation_text_ext = $('#frm_coworker_email #referral_invitation_text_ext').html();
        var referral_email_coworker_sent = $('#coworker_email_sent').val();
        var referral_email_not_sent = $('#coworker_email_not_sent').val();
        var user_full_name = $('#user_full_name').val();
        var from_email = $('#user_email').val();
        var referral_email_arr = [];
        var i = 0;

        $('.referral_email').each(function()
        {

            var elem = $(this);


            if (elem.val().indexOf("example") < 0 && elem.val() != ""){
                coworker_email_arr.push(elem.val());
                i++;
            }
        });

        if (i ==0 ){
            $("#frm_referral_msg").html(get_phrase("enter_emails"));
            return;
        }



        var email_send = new email_generator(referral_email_arr,from_email, get_phrase("invite_subject") ,coworker_invitation_text, referral_email_invatation_text_ext,referral_email_sent,referral_email_not_sent);
        email_send.send('frm_coworker_msg');
    },
    // set this class to error-labels to indicate valid fields
    success: function(label) {
        // set &nbsp; as text for IE
        //label.html("&nbsp;").addClass("checked");
    }

});
$(".coworker_email, .coworker_email.error").rules("add", { 
                // require_from_group: [1, '.referral_email'],
                email:true,
                required:  {
                        depends: function(element){
                            var sumUp = 0;


$(".coworker_email").each(function(){
                                sumUp += $(this).val().length;
                    });
                    if(sumUp == 0)
                        return true;
                    else
                        return false;
                    }
                },

    messages: "Please enter at least one valid email"
});

HTML:

                            <div>
                        <span style='text-align:left;'><?=get_phrase("EmailAddresses")?>:</span>
                        <br/>
                        <input type='text' class='referral_email' placeholder='example@<?=$company_domain_name?>'/>
                        <br/>
                        <input type='text' class='referral_email' placeholder='example@<?=$company_domain_name?>'/>
                        <br/>
                        <input type='text' class='referral_email' placeholder='example@<?=$company_domain_name?>'/>
                        <br/>
                        <input type='text' class='referral_email' placeholder='example@<?=$company_domain_name?>'/>
                        </div>
                        <div class='error_msg'></div>

in my humble opinion, it is too complicated, since what I am trying to achieve is quite simple. And even though I took a lot of sideways to ensure it's functionality, there are still bugs, for instance if you enter an incorrect input into the last field, and press submit twice, the error message will disappear, and I have no idea which rational explanation can explain this behavior.

Upvotes: 0

Views: 465

Answers (2)

Ejaz
Ejaz

Reputation: 8872

A custom validation method will work in this situation

JS (JavaScript)

//valid email checking function
function validateEmail(email) {
    var re = /^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
    return re.test(email);
}


//custom method for jquery validator
$.validator.addMethod('refEmail', function (value, element, params) {
    var num_valid = 0;
    $(params).each(function () {
        if (validateEmail($(this).val()))
            num_valid++
        });
    return num_valid != 0;
}, 'Please enter at least one valid email address');


//specifying custom validator for your elements after $("#frm_referral_email").validate();
$('.referral_email').rules('add', {
    required: false,
    refEmail: '.referral_email'
})

please note that you must make $('.referral_email') a required field for this to work. The fields will not be required ultimately because we're setting required: false for them in custom method

I KNOW there could be other ways of achieving same thing.

Note: You should remove all other validation methods for .referral_email that aim at facilitating this particular validation requirement.

Upvotes: 1

Sparky
Sparky

Reputation: 98738

"in my humble opinion, it is too complicated, since what I am trying to achieve is quite simple."

You are correct, you were making it way more complicated than it needed to be.

"if you enter an incorrect input into the last field, and press submit twice, the error message will disappear, and I have no idea which rational explanation can explain this behavior."

The jQuery Validate plugin requires that you have a name attribute on all input fields in order to function properly. Without a name attribute, the plugin has no way to keep track of the inputs and behavior is very unpredictable.

Also, within the additional-methods.js file is a rule called require_from_group. It probably didn't work when you first tried it because your input elements were all missing the name attribute.

Working DEMO: http://jsfiddle.net/zny9d/

I also combined it with the groups option to lump all the error messages for this grouping into one.

$(document).ready(function () {

    $('#myform').validate({
        groups: {
            group: "name1 name2 name3 name4 name5"
        },
        rules: {
            name1: {
                require_from_group: [1, '.referral_email'],
                email: true
            },
            name2: {
                require_from_group: [1, '.referral_email'],
                email: true
            },
            name3: {
                require_from_group: [1, '.referral_email'],
                email: true
            },
            name4: {
                require_from_group: [1, '.referral_email'],
                email: true
            },
            name5: {
                require_from_group: [1, '.referral_email'],
                email: true
            }
        }
    });

});

HTML:

<form id="myform">
    <input type='text' name='name1' class='referral_email' />
    <input type='text' name='name2' class='referral_email' />
    <input type='text' name='name3' class='referral_email' />
    <input type='text' name='name4' class='referral_email' />
    <input type='text' name='name5' class='referral_email' />
</form>

On an unrelated note, you do not need a conditional inside here:

errorPlacement: function(error, element) {
    if (error.html() != "")
        error.appendTo( element.parent().next() );
},

Whenever this callback fires, the error.html() is never going to be empty, so first testing to see that it's not empty is pointless.

This will function identically:

errorPlacement: function(error, element) {
    error.appendTo( element.parent().next() );
},

Upvotes: 1

Related Questions