3

I have a form that has sections split into tabs. The entire form should be validated when the user submits the form (i.e. an input has focus and they press enter or the save button is pressed) and I'd like to validate the elements on the first tab on the click event of a tab (other than the first one obviously) to disallow moving to another tab before the first tab's elements are validated. The problem I seem to continue running into is that after the first attempt at validating anything the rules and elements to be validated are set and don't get updated based on the passing of a different set of rules.

EDIT: Just to clarify, you can more clearly see the issue if you click Tab 2 then fill out Text 1 and Text 2 and hit Save, then do the exact opposite.

Any thoughts on the matter are greatly appreciated. Thanks in advance!

This is all based on the jquery validate plugin here: http://jqueryvalidation.org/

Here's a link to a fiddle: http://jsfiddle.net/Fsb69/

<html>
<head>
    <script type="text/javascript" src="jquery-1.7.2.js"></script>
    <script type="text/javascript" src="jquery.validate.js"></script>
    <script type="text/javascript">
        var log = function(msg) {
            $('ul#log').append('<li>'+msg+'</li>');
        },
        validate_form = function(elements) {
            var params = {
                errorLabelContainer: '#message-error',
                ignore: [],
                wrapper: 'li',
                onfocusout: false,
                onkeyup: false,
                rules: {
                    text_1: 'required',
                    text_2: 'required',
                    text_3: 'required',
                    text_4: 'required',
                },
                debug:true
            };
            if(elements) {
                $.each(params.rules, function(k, v) {
                    if($.inArray(k, elements) < 0) {
                        delete params.rules[k];
                    }
                });
            }
            log('params: '+JSON.stringify(params));
            return $('form[name=test-form]').validate(params).form();
        };
        $(function() {
            $('span.tab-click').click(function() {
                var self = $(this),
                selected = self.prop('id').replace('-click', ''),
                selected_index = selected.replace('tab-', ''),
                elements = ['text_1', 'text_2'];
                valid = true;
                if(selected_index > 1) {
                    var valid = validate_form(elements);
                    log('is valid? '+valid);
                }
                if(!valid) {
                    return false;
                }
                $('div.tab').hide();
                $('div#'+selected).show();
            });
            $('form[name=test-form]').submit(function(e) {
                var form = $(this);
                e.preventDefault();
                var is_valid = validate_form(false);
                log('is valid? '+is_valid);
                if(is_valid) {
                    log('success');
                    $('#message-error').empty().append('<li>Form is validated.</li>');
                }
            });
        });
    </script>
    <style>
        form span {
            text-decoration: underline;
            color: blue;
            cursor: pointer;
        }
    </style>
</head>
<body>
    <form name="test-form">
        <span id="tab-click-1" class="tab-click">Tab 1</span> | <span id="tab-click-2" class="tab-click">Tab 2</span><br /><br />
        <div class="tab" id="tab-1">
            <label for="text_1">Text 1</label><input name="text_1" value="" /><br />
            <label for="text_2">Text 2</label><input name="text_2" value="" /><br />
        </div>
        <div class="tab" id="tab-2" style="display:none;">
            <label for="text_3">Text 3</label><input name="text_3" value="" /><br />
            <label for="text_4">Text 4</label><input name="text_4" value="" /><br />
        </div>
        <ul style="display:none; list-style-type: none;" id="message-error"></ul>
        <button type="submit">Save</button>
    </form>
    <h4>Log</h4>
    <ul id="log"></ul>
</body>
</html>
Sparky
  • 98,165
  • 25
  • 199
  • 285
edward.louis
  • 357
  • 2
  • 5
  • 14

1 Answers1

5

Title: "jQuery Validator Plugin won't update rules"

Your root problem is the improper way you're handling the .validate() call.

.validate() is only the plugin's initialization method. You cannot call it repeatedly to update rules, as only the first call is used, and all subsequent calls are ignored. The expected usage is that .validate() will be called once on DOM ready for any one particular form.

Then later if you need to dynamically change your rules, you would use the .rules('add') method. It may seem counter-intuitive since you may not be "adding", but this is the only available method. Simply over-writing the rule(s) with the new parameters and/or messages is the typical usage. To remove a rule entirely, use the .rules('remove') method. When applying this method to multiple elements at once, you must wrap it inside of a jQuery .each().

$('input[name^="field_"]').each(function() {
    $(this).rules('remove');
});

Simple demo of the rules() methods: http://jsfiddle.net/7EE5K/


Also, refer to this answer for a simple example about how to validate a form when it's split into steps or sections: https://stackoverflow.com/a/18407211/594235

Simple demo of a multi-step form: http://jsfiddle.net/N9UpD/

Community
  • 1
  • 1
Sparky
  • 98,165
  • 25
  • 199
  • 285
  • Thanks for the thoughts @Sparky. I've tried doing what you're referring to, and I follow you about the initialization aspect, but I haven't been able to get it to work any other way than this. Could you provide a clear example of how you would dynamically update the rules etc? You could even use the fiddle and save a new version. – edward.louis Aug 23 '13 at 20:59
  • @edward.louis, there is no part of your code that I would keep so anything I do would be from scratch. Instead, I provided a link to an answer that includes full code to something similar. Your best bet would be to start over following the typical usage of this plugin. There are also some working examples posted in [the documentation](http://jqueryvalidation.org). – Sparky Aug 23 '13 at 21:05
  • @edward.louis, see this demo: http://jsfiddle.net/7EE5K/ ~ the page loads with a working form complete with validation. One button removes the rules and another button adds the rules back. – Sparky Aug 23 '13 at 21:12
  • brilliant. thanks for clearing up the proper use of this plugin. – edward.louis Aug 26 '13 at 13:44