21
votes

Guys from http://jqueryvalidation.org/ just released version 1.13.1. Checking on their website i see this on the changelog:

CORE: * Ignore readonly as well as disabled fields. (9f4ba10)

This is the link: https://github.com/jzaefferer/jquery-validation/commit/9f4ba10ea79b4cf59225468d6ec29911f0e53a0a

I use some bootstrap templates and one of them now uses that version. That brings me a problem, i use readonly attribute to prevent users typing dates manually, so their only option is to choose a date from the datepicker.

With this change, the validation plugin ignores the readonly inputs marked as required, can anyone help me out suggesting some fix for 1.13.1, or future versions? i´ve found a question to do the opposite: How can I disable jquery validation on readonly fields?

4
What do you need to validate? Wrong date selected?Panoptik
I need it to be required, so it gets red and all the validation makeup. It was working fine until this version.Daniel Avellaneda
Maybe it will be better to set default value for this field?Panoptik
It´s not a option for me to let user type anything on the input field.Daniel Avellaneda
To change plugin is too complex solution. I can suggest you to remove readonly attribute and append custom event handler to input field for event "focus" and call blur(). So you prevent user to change date manualy. Another way is to enable readonly on focus (or on datepicker show) and disable on blur (datepicker hide/close). And your validation plugin must work fine.Panoptik

4 Answers

41
votes

Thank you for you suggestion Panoptik, adding readonly on focusin, and then removing it on focusout was the cleanest way, million thanks! I answer myself in case anyone has the same problem. Hope it helps.

$(document).on("focusin", "#someid", function() {
   $(this).prop('readonly', true);  
});

$(document).on("focusout", "#someid", function() {
   $(this).prop('readonly', false); 
});
10
votes

You can override the original "elements" function with an implementation which quite similar to the original implementation except for the readonly field handling. This is not an elegant solution, but it does work. If you update your jquery validate library, you also need to recheck your overridden method.
* UpToDate * See jquery-validate-1.14 changeLog: Revert "Ignore readonly as well as disabled fields." :):)

$.validator.prototype.elements = function() {
    var validator = this,
    rulesCache = {};

    return $( this.currentForm )
    .find( "input, select, textarea" )
    .not( ":submit, :reset, :image, [disabled]") // changed from: .not( ":submit, :reset, :image, [disabled], [readonly]" )
    .not( this.settings.ignore )
    .filter( function() {
        if ( !this.name && validator.settings.debug && window.console ) {
            console.error( "%o has no name assigned", this );
        }

        if ( this.name in rulesCache || !validator.objectLength( $( this ).rules() ) ) {
            return false;
        }

        rulesCache[ this.name ] = true;
        return true;
    });         
};
3
votes

Solution with setting readonly attribute on fired focusin event is good, but requires us write handlers in <script> block (Why? For example, Firefox doesn't support onfocusin attr for input elements).

So, simple and cross-platform solution in my opinion is set onkeydown="return false;" attribute like:

<input type="text" name="myBean.date" onkeydown="return false;">

This leaves element eligible for validation and doesn't allow to enter anything into it.

2
votes

I didn't like binding to the focusin/out events. It also requires you to add CSS styling. The below code removes the readonly attribute and re-applies it when the form is not valid.

$('#form').submit(function () {
    var children = $(this).find('input[readonly]');
    children.prop('readonly', false);

    var validform = $(this).valid();
    if (validform) {
        $(this).unbind('submit').submit();
    } else {
        children.prop('readonly', true);
    }

    e.preventDefault();
    e.stopPropagation();
})