Conflict between jQuery Validate and Masked Input

后端 未结 7 641
梦谈多话
梦谈多话 2020-12-08 10:40

I\'ve got a form that\'s using both jQuery Validate and Masked Input for phone number and US zip code fields.

For example, for a US zip code, Masked Input allows only

相关标签:
7条回答
  • 2020-12-08 11:02

    I tried following solution, and it works like a charm.

    $("[data-input-type=phone]", "body")
      .mask("(999) 999 99 99")
      .bind("blur", function () {
        // force revalidate on blur.
    
        var frm = $(this).parents("form");
        // if form has a validator
        if ($.data( frm[0], 'validator' )) {
          var validator = $(this).parents("form").validate();
          validator.settings.onfocusout.apply(validator, [this]);
        }
      });
    

    What triggers the problem is event ordering. When an element is masked, it is validated by maskedinput plugin on blur, but same element is validated by validator plugin on focusout event (which is a wrapper for blur on non-ie browsers) which is called before maskedinput's blur.

    In this situation input element has the value "(___) ___ __ __" when validator checks for the value. When code reaches maskedinput's blur event, plugin tests and clears the value since it is not a valid input.

    Validation result may be different for each validation case. For instance required rules will pass with success since element has a value. non-required number fields will fail even if we leave the input empty since a mask like "999" may be tested as 12_

    the code above tests if form of masked input has validation attached to it, and recalls focusout event handler. Since our handler is attached as the latest, hopefully it will be called at last.

    A warning, code simply copies behavior of validation plugin. It will probably work for a decade but may fail if validation plugin decides to do things different than now.

    sincerely

    0 讨论(0)
  • 2020-12-08 11:02

    I had faced same issue and I spend two hours to make a proper solution. Finally, I made a proper code. You can use it

    For ZIP code.

    $.validator.addMethod("zipcode", function(postalcode, element) {
                //removes placeholder from string
                postalcode = postalcode.replace(/[^0-9]/g, "");
                //validates postalcode.
                return this.optional(element) || postalcode.match(/^\d{5}$|^\d{5}\-\d{4}$/);
            }, "Please specify a valid zip code");
    

    If you want to increase or decrease zip length then change postalcode.match(/^\d{5}$|^\d{5}-\d{4}$/); number according to your requirement.

    For phone same code will be used but you need to change only numbers like postalcode.match(/^\d{10}$|^\d{10}-\d{9}$/);

    $.validator.addMethod("phone_length", function(phoneno, element) {
                    //removes all special characters
                    phoneno= phoneno.replace(/[^0-9]/g, "");
                    return this.optional(element) || phoneno.match(/^\d{10}$|^\d{10}\-\d{9}$/);
                }, "Please enter a valid phone");
    

    I hope this code will help you a lot. If you want to know how to call then simply add zipcode:true in your validation field

    0 讨论(0)
  • 2020-12-08 11:03

    Simply hook in to the mask() function and append some additional logic to fire your own blur logic after the default mask's blur logic:

    //Store the original mask function
    var origMaskFn = $.fn.mask;
    
    $.fn.mask = function (mask, settings) {
    
        //Call the original function applying the default settings
        origMaskFn.apply(this, [mask, settings]);
    
        //Manually validate our element on blur to prevent unobtrusive messages
        //from showing before the mask is properly scrubbed
        $(this).bind('blur', function () {
            var $form = $(this).parents('form');
            if (!$form.exists())
                return;
    
            var validator = $form.validate().element($(this));
        });
    }
    

    Also, you may notice the 'exists()' function. This is something I use a lot with my jQuery selectors:

    //Function to detect if a jQuery elements exists.  i.e.:
    //      var $element = $(selector);
    //      if($element.exists()) do something...
    
    $.fn.exists = function () {
        return this.length !== 0;
    }
    
    0 讨论(0)
  • 2020-12-08 11:03

    I tried some of the solutions but none worked for me, i'm using 'bootstrapValidator' (http://bootstrapvalidator.com/) and 'jquery.maskedinput' (http://digitalbush.com/projects/masked-input-plugin/) so if someone still have this problem, my solution was:

    My input was marked like this:

    <input type="text" class="form-control" id="telefone" placeholder="(__) ____-_____" name="telefone" required>
    

    And the full script like this:

    $(document).ready(function() {
       var telefone = $('#telefone'), //THAT'S MY INPUT WITH MASK
           form = telefone.parents("form"), //THAT'S MY FORM WITH THE VALIDATE
           alteredField = false; //THAT'S A FLAG TO SSE IF THE INPUT WAS ALTERED
    
                // APPLY MY MASK
                telefone.mask('(99) 9999-9999?9');
    
                // FOCUS ON ANY INPUT
                form.find('input[type=text]').focus(function(){
                    // REMOVE THE VALIDATION STATUS
                    $(form).data('bootstrapValidator').updateStatus($(this).attr('name'), 'NOT_VALIDATED');
                    // ENABLE THE SUBMIT BUTTON
                    $(form).data('bootstrapValidator').disableSubmitButtons(false);
                });
    
                // FOCUS ON THE MASKED INPUT
                telefone.focus(function(){
                    // DISABLE THE VALIDATE
                    $(form).data('bootstrapValidator').enableFieldValidators('telefone', false);
                    // ENABLE THE SUBMIT BUTTON
                    $(form).data('bootstrapValidator').disableSubmitButtons(false);
                }).blur(function(){ // BLUR ON THE MASKED INPUT
                    // GET THE INPUT VALUE
                    var value = telefone.val();
                    // ENABLE THE VALIDATE 
                    $(form).data('bootstrapValidator').enableFieldValidators('telefone', true);
                    // CHECK IF THE VALUE IS EMPTY
                    if(value != ""){
                        // CHANGE THE STATUS OF THE INPUT TO VALID 
                        $(form).data('bootstrapValidator').updateStatus('telefone', 'VALID')
                        // ACTIVE THE FLAG
                        alteredField = true;
                    }else if (alteredField) { // IF THE INPUT WAS ALTERED BEFORE AND DON'T HAVE VALUE
                        // CHANGE THE STATUS OF THE INPUT TO INVALID
                        $(form).data('bootstrapValidator').updateStatus('telefone', 'INVALID')
                    };
                });
    
            });
    

    This code modifies the standard behavior of the 'bootstrapValidator', but was the only way that I gotta to solve the bug.

    I don't know about performance issues, so please modify and improve the code ^^ Hope that this help ^_^

    0 讨论(0)
  • 2020-12-08 11:07

    I was actually looking for an answer to this exact question. Ended up figuring out a more reliable workaround.

    Since I am defining my own validator method for the zipcode I modified it so that it would remove the hyphen if the length of the zipcode was 6 after I removed the placeholder from the value.

    It looked like this:

    $.validator.addMethod("zipcode", function(postalcode, element) {
                //removes placeholder from string
                postalcode = postalcode.split("_").join("");
    
                //Checks the length of the zipcode now that placeholder characters are removed.
                if (postalcode.length === 6) {
                    //Removes hyphen
                    postalcode = postalcode.replace("-", "");
                }
                //validates postalcode.
                return this.optional(element) || postalcode.match(/^\d{5}$|^\d{5}\-\d{4}$/);
            }, "Please specify a valid zip code");
    

    So the postalcode I am validating will have the placeholders added by the input plugin and the hyphen removed if the zipcode that is entered only has 5 numerical digits (6 including the hyphen). So it will validate it properly.

    0 讨论(0)
  • 2020-12-08 11:07

    Does it matter the order that you do the binding? For example, is there a difference between

    $(function() {
      var $form = $("#myForm"), $zip = $("#zip");
      $zip.mask("99999?-9999");
      $form.validate();
    });
    

    and

    $(function() {
      var $form = $("#myForm"), $zip = $("#zip");
      $form.validate();
      $zip.mask("99999?-9999");
    });
    

    I think that the bindings should fire in order.

    0 讨论(0)
提交回复
热议问题