JQuery Validation issue: Cannot read property ‘settings’ of undefined

This is basically copy-pasted from an answer I wrote on Stack Overflow. I thought it could be a good post to start off this blog with.The issue at hand is:

Uncaught TypeError: Cannot read property 'settings' of undefined 

which comes from using the rules method in jqueryvalidation  plugin in Google Chrome.

As a disclaimer I used the following code:

http://alittlecode.com/jquery-form-validation-with-styles-from-twitter-bootstrap/

(it’s downloadable from Get The Sample Files link).

So here goes:

REQUIREMENT:

– In my case I wanted an input field of type number to be validated as number however I didn’t want Google Chrome to make it a number field (just try in Chrome to see what I mean)

I have chrome 27.0.1453.116 – I know I should update.

USE CASE:

– So I had a utility JS function which automatically populated the validate rule object by parsing the form input fields after page load. (I might post the code sometime in the future)

– Two fields had to be number to be validated on the client-side but Chrome made them something like a combo-box when the input type=”number”. Moreover, this caused bypassing the native validation by Chrome – or so I think – when the user inputted manually say some characters and it looked ugly so all in all it wasn’t acceptable.

CODE:

– At first I used the rules method to dynamically modify the two fields after page load.

THIS IS WHAT HAPPENED

Uncaught TypeError: Cannot read property 'settings' of undefined 

at line 124 of jquery.validate.js

which shows:

var settings = $.data(element.form, 'validator').settings;

JQuery Documentation for $.data

Description: Returns value at named data store for the element, as set by jQuery.data(element, name, value), or the full data store for the element.

Apparently it was returning undefined because there is no validator instance associated with the form.

Now in validate function you notice that if validator is undefined it will create a new one

var validator = $.data(this[0], 'validator');
        if ( validator ) {
            return validator;
        }

        // Add novalidate tag if HTML5.
        this.attr('novalidate', 'novalidate');

       //HERE it is creating a new one using the constructor   
        validator = new $.validator( options, this[0] );
        $.data(this[0], 'validator', validator);

Apparently the rules method assumes that validator is already there in the form object, so from my understanding, and since validate returns a pre-populated validator instance, you can call validate and then append your extra rules to the returned validator’s settings.rules object and re-run validate again which is not very practical.

The other solution would be to simply append the added rules to the initial rules object before calling validate

code example:

var customRule = {number: true};

//suppose populateValidateRules() fills your initial rules
var validationRules =  populateValidateRules();

validationRules["rules"].field= customRule;
$(formId).validate(validationRules);

Now you will call validate only once after dynamically appending your stuff, of course this could work also on removing some attributes however I have not tested it yet.

Hope this helps,

Feedback appreciated

Advertisements