3

I am trying to create a simple application form with two buttons (save and submit). I am using the jQuery validate plugin. In order to submit the form the applicant must actually fill out the entire form correctly. No empty boxes, and valid data in each box. To save, however, they can leave as many fields blank as they would like, but the fields they fill out must be valid. (ie. no letters in boxes for numbers).

To this end, I have two separate validate functions and depending on which button the user clicks, one of the two is called. This works fine for the submit button, and it works the first time for the save button. However, if a user enters some gibberish into a box meant for numbers and hits save TWICE, the form will submit anyway. The first time they hit save, it behaves correctly.

For the life of me I cannot figure out why. My jquery code is below:

 $(document).ready(function(){

      $("#csa_submit_button").live("click",function(){
            //alert("submit");
            $("#csa_submit_flag").val("true");
            validator = $("#csa_form").validate({
                "rules": {
                    "csa_phone" : {required: true, digits: true, minlength: 10, maxlength: 10},
                    "csa_current_grants" : {number: true, required: true},
                    "csa_current_work_study" : {number: true, required: true},
                    "csa_balance_no_loans" : {number: true, required: true},
                    "csa_current_loans" : {number: true, required: true},
                    "csa_textbooks" : {number: true, required: true},
                    "csa_total_to_date" : {number: true, required: true},
                    "csa_parent_plus" : "required",
                    "csa_student_loans" : "required",
                    "csa_balance" : {number: true, required: true},
                    "csa_employment_contributions" : {number: true, required: true},
                    "csa_current_financial_situation" : "required",
                    "csa_activities" : "required",
                    "csa_request_amount" : {required: true, number: true},
                    "csa_term": {required: true, minlength: 1}
                },  
                "messages": {
                    "csa_term": "You must select at least one term",
                    "csa_phone": "You must enter a phone number in the following format: ##########"
                },
                errorPlacement: function(error, element) {
                   if (element.attr('type') === 'radio') {
                      error.insertAfter(element.parent());
                   }
                   else if (element.attr('name') === 'csa_employment_contributions'){
                       error.insertAfter(element.parent());
                   }
                   else if (element.attr('name') === 'csa_term') {
                       error.insertAfter(element.parent());
                   }
                   else {
                      error.insertAfter(element);
                   }
                }
            }); 
       });
      $("#csa_save_button").live("click",function(){

            $("#csa_submit_flag").val("false");

            validator = $("#csa_form").validate({
                "rules": {
                    "csa_phone" : {number: true},
                    "csa_current_grants" : {number: true},
                    "csa_current_work_study" : {number: true},
                    "csa_balance_no_loans" : {number: true},
                    "csa_current_loans" : {number: true},
                    "csa_textbooks" : {number: true},
                    "csa_total_to_date" : {number: true},
                    "csa_balance" : {number: true},
                    "csa_employment_contributions" : {number: true},
                    "csa_request_amount" : {number: true}
                },
                "messages": {
                    "csa_phone": "You must enter a phone number in the following format: ##########"
                },
                errorPlacement: function(error, element) {
                   if (element.attr('name') === 'csa_employment_contributions'){
                       error.insertAfter(element.parent());
                   } else {
                      error.insertAfter(element);
                   }                
                }
            });


        });

      });
Sparky
  • 98,165
  • 25
  • 199
  • 285
jcanipar
  • 1,442
  • 2
  • 11
  • 8

4 Answers4

3

I would like to complete Sparky answer with a link to another of his own answer: https://stackoverflow.com/a/24456384/923712.

In a nutshell, there is a way to update validation after a .validate() call, using .rules('add', ...) and .rules('remove') methods.

More info here: http://jqueryvalidation.org/rules

Community
  • 1
  • 1
Xavier Portebois
  • 3,354
  • 6
  • 33
  • 53
2

If you want to call validate again with new settings on different button call

e.g $('#formid').removeData('validator');

This will remove validation for the form attached then initialize it again with the new settings

Rakesh Singh
  • 1,250
  • 9
  • 8
1

You have a fundamental misunderstanding about what .validate() is doing. It is not a method to check validity on demand. That is done automatically once the plugin is properly initialized.

.validate() is only initializing the plugin and its options on the form. That's why you see it work once on the first click. By design, calling it again, even with different options, will do nothing... and that's why it appears to be broken on subsequent clicks of the other button.

You cannot have two separate and unique instances of the plugin on the same form at the same time. You have no choice but to redesign your code.

See the docs: http://docs.jquery.com/Plugins/Validation


EDIT:

There is no method available to turn validation on/off on demand. Since the plugin is designed to handle the click and intercept the submit event, you could remove the other button from the form (to avoid a submit) and handle the data separately, using ajax to send the data to the server.

$('#save').click(function() {
    var data = $('#myform').serialize();
    // ajax code to send the serialized data to the server
});

Simple DEMO: http://jsfiddle.net/x4N4U/

Sparky
  • 98,165
  • 25
  • 199
  • 285
  • Is there a way to bypass the validation for one of the buttons then? Or do I really just have to write 2 of my own validation methods by hand? – jcanipar Apr 16 '13 at 06:37
  • @jcanipar, no, there is no way to toggle the validation on/off. There should also be no need to write your own validation. Just remove the one button to prevent another `submit` and manually handle the data without validation. See my edits. – Sparky Apr 16 '13 at 13:55
0

I might be a little late here, but I just have come to that same challenge myself. I managed to solve it using depends and a global variable. Here's a very simple demo.

<form id="myform">
  <input type="text" id="myemail" name="myemail">
  <button type="button" id="save">Save</button>
  <button type="button" id="submit">Submit</button>
</form>
  var action = '';
  $("#myform").validate({
    rules: {
      myemail: {
        email: true,
        required: {
          depends: function(el) {
            return action === 'submit';
          }
        }
      }
    },
    messages: {
      myemail: {
        email: 'Enter a valid email!',
        required: 'Email is required!'
      }
    }
  });

  $("#save").on("click", () => {
    action = 'save';
    if($("#myform").valid()) {
      console.log('Valid! ' + action);
      // Save only
    } else {
      $("#myform").validate().focusInvalid();
    }
  });

  $("#submit").on("click", () => {
    action = 'submit';
    if($("#myform").valid()) {
      console.log('Valid! ' + action);
      // Submit
    } else {
      $("#myform").validate().focusInvalid();
    }
  });