Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
332 views
in Technique[技术] by (71.8m points)

jquery - Trigger validation on form with multiple sections and unknown input fields

I'm trying to validate a complex form and by complex I mean that form is just one but it has been split in four sections and I made a simple wizard to show them. I'm using jQuery Validation but it's not working as I want and also have some doubts about it. Based on this example (second form) I made my code as follow:

$("#product_create").validate({
    rules: {
        product_name: {
            required: true,
            minlength: 10,
            maxlength: 50
        },
        product_price: {
            required: true,
            number: true,
            minlength: 2
        },
        product_quantity: {
            required: true,
            digits: true,
            minlength: 1
        }
    },
    messages: {
        product_name: {
            required: "El nombre del producto no se puede dejar vacío",
            minlength: "El nombre del producto no puede tener menos de 10 carácteres",
            maxlength: "El nombre del producto no puede tener más de 50 carácteres"
        },
        product_price: {
            required: "Debes introducir un precio",
            number: "El precio debe ser un número decimal o no"
        },
        product_quantity: {
            required: "Debes introducir una cantidad",
            number: "La cantidad debe ser un número"
        }
    }
});

If I understand good then on keyup event fields should validate and they are not since errors doesn't come up. So first problem regarding this is: why it doesn't validate? What's wrong in my solution? Second one is how I validate product_price and product_quantity only if they are visible?

Now regarding this same topic I have another doubt, I create several fields on the fly and yes I know theirs ID each time, in this case how I apply rules to those fields?

UPDATE

I figure out where the problem with keyup was, validation is made by input name and not input id's as I tough, so this part is done.

The second problem still pending. For example I can generate three fields with name variation[pprice][] and the fly but can be five or more or whatever, how I add those fields to rules and validation part? Can I just add the rule for variation[pprice][] and it will validates no matter how many elements with the same name are in the form?

Also is pending the part of validate fields just if they are visible

UPDATE 2

Since variation[pprice][] is a array of items, can I use $.each to move for them and assign rules?

UPDATE 3

Following recommendations by @Sparky I change my code to this:

$('#variations_holder input.pprice').each(function() {
    $(this).rules('add', {
        required: true,
        number: true,
        messages: {
            required: "Debes introducir un precio de la variación",
            number: "El precio de la variación debe ser un valor numérico o decimal"
        }
    });
});

But in Firebug I get this error:

TypeError: e.validator.methods[o] is undefined

Which prevent code execution for the script, what I miss in this case?

UPDATE 4

Supposing that I can't use several forms so I only have one form with many sections (using section tag) and I handle to move between each. I'm trying to call validate() in same form but two times and validation at step5 didn't work since fields pass. This is the code I'm using for that:

function validateWizard(step) { var is_valid = true;

switch (step) {
    case 1:
        if ($("#selected_category").val() === '' || $("#selected_category").val().length === 0) {
            alert("Debes seleccionar una categoría antes de continuar");
            is_valid = false;
        }
        break;
    case 2:
        $("#product_create").validate({
            rules: {
                "product[name]": {
                    required: true,
                    minlength: 10,
                    maxlength: 50
                },
                "product[price]": {
                    required: true,
                    number: true,
                    minlength: 2
                },
                "product[quantity]": {
                    required: true,
                    digits: true,
                    minlength: 1
                },
                "product[description]": {
                    required: true
                }
            },
            messages: {
                "product[name]": {
                    required: "El nombre del producto no se puede dejar vacío",
                    minlength: "El nombre del producto no puede tener menos de 10 carácteres",
                    maxlength: "El nombre del producto no puede tener más de 50 carácteres"
                },
                "product[price]": {
                    required: "Debes introducir un precio",
                    number: "El precio debe ser un valor numérico o decimal"
                },
                "product[quantity]": {
                    required: "Debes introducir una cantidad",
                    number: "La cantidad debe ser un número"
                },
                "product[description]": {
                    required: "Debes introducir una descripción del producto"
                }
            }
        });

        is_valid = $("#product_create").valid();

        if (is_valid) {
            $('#variations_holder input.pprice').each(function() {
                pprice = $.trim(this.value);
                if (!pprice.length) {
                    $(this).focus();
                    $(this).addClass('error');
                    is_valid = false;
                } else if (!/^[1-9]d*(.d+)?$/.test(pprice)) {
                    $(this).addClass('error');
                    is_valid = false;
                }
            });

            // Validate quantity in variation
            $('#variations_holder input.pqty').each(function() {
                pqty = $.trim(this.value);
                if (!pqty.length) {
                    $(this).focus();
                    $(this).addClass('error');
                    is_valid = false;
                } else if (!/^[1-9]d*$/.test(pqty)) {
                    $(this).addClass('error');
                    is_valid = false;
                }
            });
        }
        break;
    case 3:
        break;
    case 5:
        $("#product_create").validate({
            rules: {
                "stock[sku]": {
                    required: true,
                    minlength: 10,
                    maxlength: 20
                },
                "stock[width]": {
                    required: true,
                    number: true,
                    minlength: 1
                },
                "stock[height]": {
                    required: true,
                    number: true,
                    minlength: 1
                },
                "stock[length]": {
                    required: true
                },
                "stock[weight]": {
                    required: true,
                    number: true,
                    minlength: 1
                },
                "stock[description]": {
                    required: true
                },
                "warranty[description]": {
                    required: true
                },
                "warranty[valid_time]": {
                    required: true,
                    digits: true
                }
            },
            messages: {
                "stock[sku]": {
                    required: "El SKU no se puede dejar vacío",
                    minlength: "El SKU no puede tener menos de 10 carácteres",
                    maxlength: "El SKU no puede tener más de 50 carácteres"
                },
                "stock[width]": {
                    required: "Debes introducir un ancho",
                    number: "El ancho debe ser un número"
                },
                "stock[height]": {
                    required: "Debes introducir una altura",
                    number: "La altura debe ser un número"
                },
                "stock[length]": {
                    required: "Debes introducir una longitud",
                    number: "La longitud debe ser un número"
                },
                "stock[weight]": {
                    required: "Debes introducir un peso",
                    number: "El peso debe ser un número"
                },
                "stock[description]": {
                    required: "Debes introducir una descripción del stock del producto"
                },
                "warranty[description]": {
                    required: "Debes introducir una descripción de la garantía para este producto"
                },
                "warranty[valid_time]": {
                    required: "Debes introducir un período de validez",
                    digits: "El período de validez no es válido"
                },
            }
        });

        is_valid = $("#product_create").valid();
        break;
}

return is_valid;

}

my question is why if form is not valid at step5 it pass? Should't fail?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

Quoet OP:

"Since variation[pprice][] is a array of items, can I use $.each to move for them and assign rules?"

You must use .each() when the jQuery selector targets more than one input element. However, this does not get around the fact that the jQuery Validate plugin requires that each input element contain a unique name attribute. This is how the plugin keeps track of elements. (A group of radio or checkbox elements with the same name is not an issue since, when they're grouped, they're supposed to have the same name... the group acts as a single data input.)

This will not work because there are multiple input elements with the same name...

$('input[name="something"]').each(function() {
    $(this).rules('add', function() {
        required: true,
        // another rule, etc,
    });
});

This will work as long as each input element contains a unique name...

$('input.class').each(function() {
    $(this).rules('add', function() {
        required: true,
        // another rule, etc,
    });
});

See this answer for the various ways rules can be defined and applied.


There are various approaches to stepped forms.

When I create multi-step forms, I use a unique set of <form> tags for each section. Then I use the .valid() method to test the section before moving to the next. (Don't forget to first initialize the plugin; call .validate(), on all forms on DOM ready.)

Then on the last section, I use .serialize() on each form and concatenate them into a data query string to be submitted.

Something like this...

$(document).ready(function() {

    $('#form1').validate({ // initialize form 1
        // rules
    });

    $('#gotoStep2').on('click', function() { // go to step 2
        if ($('#form1').valid()) {
            // code to reveal step 2 and hide step 1
        }
    });

    $('#form2').validate({ // initialize form 2
        // rules
    });

    $('#gotoStep3').on('click', function() { // go to step 3
        if ($('#form2').valid()) {
            // code to reveal step 3 and hide step 2
        }
    });

    $('#form3').validate({ initialize form 3
        // rules,
        submitHandler: function (form) {
           // serialize and join data for all forms
           // ajax submit
           return false;
        }
    });

    // there is no third click handler since the plugin takes care of this 
    // with the built-in submitHandler callback function on the last form.

});

Important to remember that my click handlers above are not using type="submit" buttons. These are regular buttons, either outside of the form tags or type="button".

Only the button on the very last form is a regular type="submit" button. That is because I am leveraging the plugin's built-in submitHandler callback function on only the very last form.

"Proof of Concept" DEMO: http://jsfiddle.net/N9UpD/

Also, see for reference:

https://stackoverflow.com/a/17975061/594235


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...