Unable to validate jQuery-created select menus

Hi everyone,

I am experiencing some difficulty using the jQuery validation plugin jqueryvalidation.org/ to validate content created via jQuery.

I have a select menu which creates other select menus. These new select menus must have values greater than 0 before the form can be submitted. I can’t use the plugin on these select menus.

Another select menu with the “this works” paragraph above it can be validated. This can be done by changing “somename” to “wine” in the selection.

I am also not sure about the jQuery.validator.addMethod. Is it checking that all of the select menus have values greater than 0?

Thank you very much, I’ve been at this for hours.


```html
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html lang="en">
<head>
<title>Testing</title>

<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
<script src="http://ajax.aspnetcdn.com/ajax/jquery.validate/1.11.1/jquery.validate.min.js"></script>
</head>
<body>

<form id="myform" action="" method="post">
<p>beer</p>
<select class="someclass" id="5" name="booz[beer]">
<option>0</option>
<option>1</option>
<option>2</option>
<option>3</option>
</select>
<div class="content"></div><br /><br /><br />

<p>this works</p>
<select class="otherclass" name="wine[red]">
<option>0</option>
<option>1</option>
<option>2</option>
<option>3</option>
</select>
<input type="submit" name="send" id="submit" value="Send">
</form>




<script>
$(document).ready(function() {
var content = $(".content");
$(".someclass").on('change', function () {
var ad = $(this).attr("id");
var count = $(this).val();

newContent = "",
nameWithBrackets = $(this).attr("name");
name = /\\[(.*)\\]/.exec(nameWithBrackets)[1];
for (var i = 0; i < count; i++)
{

newContent += "<p>" + name +  (i+1) +"</p><p>" + 'bottles' +"</p><select  name=\\"somename[" + name + "][" + i + "]\\" >";
for (var a=0; a <=ad; a++)
{
 newContent +="<option>" + a + "</option>";
}newContent +="</select>";
}
$(this).next().html(newContent);
});
});
</script>




<script>
$(document).ready(function () {

    $('#myform').validate({
    });

    $("[name^=somename]").each(function () {
        $(this).rules("add", {
            required: true,
            selectValue: true
        });
    });


    jQuery.validator.addMethod('selectValue', function (value) {
        return (value != '0');
    }, "Please select a value");

});
</script>

</body>
</html>

We meet again, RedBishop!

I hope your Monday is off to a good start?

I think what you need to do here is add the extra validation rules after you’ve inserted the new form elements:

$(this).next().html(newContent);

$("[name^=somename]").each(function () {
    $(this).rules("add", {
        required: true,
        selectValue: true,
        min: 1 // prevents select validating with value of 0
    });
});

Hey fretburner,

how are you doing?

I hope your Monday is off to a good start?

As good as can be expected on a Monday, but thanks to you the validation is working now! :slight_smile: I was wondering what the problem was…

Do you think it’s possible to customize the error messages? For each of the newly-created select menus I have a paragraph before it - such as beer 1, beer 2 etc…
It would be nice if the error message could read “please select a value for beer 2”, or for whatever the case might be.

Thank you for assisting me with this.

Yeah I’m not bad thanks :slight_smile:

Sure, you can grab the index argument from the .each() function and use it to create a custom message for each select tag:

$("[name^=somename]").each(function (index) {
    $(this).rules("add", {
        required: true,
        min: 1,
        messages: {
            min: "Please select a value for beer " + (index +1)
        }
    });
});

Note: After looking at your code again, I noticed you’re using a custom rule to stop the select validating with a zero value. If you’re still using that, you’ll need to change the message key like this:

selectValue: "Please select a value for beer " + (index +1)

Sorry for not getting back to you sooner, I have been trying to get the names of the select menus for the error messages.

The select menus are dynamically generated so the names will always be different. All of the new select menus have names in this format:
name=“name1[name2][1]”. The error message needs to include whatever name is in the first bracket from the left (the name2 value).

I tried this:

$("[name^=somename]").each(function (index) {
var  getname = $(this).attr("name");
var errorname = /\\[(.*)\\]/.exec(getname)[1];

    $(this).rules("add", {
        required: true,
        min: 1,
        messages: {
            min: "Please select a value for " + errorname + " " + (index +1)
        }
    });
});

Would you mind having a look at this?

Thanks a lot!

I think you just need to change your regex pattern slightly to /\\[(\\w+)\\]/ and it should work.

Thank you, but no luck yet. The error messages now state:

“Please select a value for 0” or “Please select a value for 1” etc.

Could you please tell me what the integer in the bracket does? .exec(getname)[1];

Thanks!

This worked for me on my test page:

$("[name^=somename]").each(function (index) {
    var name = $(this).attr("name").match(/\\[(\\w+)\\]/)[1];
    $(this).rules("add", {
        required: true,
        min: 1,
        messages: {
            min: "Please select a value for " + name + ' ' + (index +1)
        }
    });
});

The [1] is accessing the second element of the array returned by exec().

Thank you for replying!

Still not right.

If I use this:

var name = $(this).attr("name").match(/\\[(.*)\\]/)[1];

It prints these error messages:

Please select a value for Beer][0 1

Please select a value for Beer][1 2

And if I use this:

 var name = $(this).attr("name").match(/\\[(\\w+)\\]/)[1];

it prints:

Please select a value for 0 1

Please select a value for 1 2

Could you re-post the whole section of code please? There must be something amiss, as that code works fine for me.

Hi fretburner,

can I get back to you on this? I’ve tested the code with the HTML I posted in the first post and it does work, as you have confirmed. However in my actual webpage it doesn’t work.

Let me see if I can figure this out.

Thank you for your help!

Hi fretburner,

hope you are having a good morning.

Can I ask you something?

As you know I’m using jQuery to create another select menu based on the value of another select menu. What do you think I should do to ensure the page is still functional with JavaScript turned off? The PHP will always create the first select menu regardless of JavaScript being enabled/disabled. Should I have some form inputs in place of the second select menus which only appear if JavaScript is disabled? Validating the form with PHP might also be an issue. I’d need to have some condition to check if the form has been submitted with or without JavaScript enabled.

I am just thinking what options are at my disposal and would greatly appreciate your advice.

Thank you!

Hi RedBishop,

I’m doing well thanks. Sorry I didn’t get back to you sooner, it’s been a busy couple of days.

In your PHP script, why not check to see if there are values set in $_POST for the dynamic inputs and add them if they’re not present? Something like this:

if ($_POST['booze']['beer'] > 0 && isset($_POST['somename']['beer']) === false) {
    // echo the correct number of select inputs,
    // according to the value of $_POST['booze']['beer']
}

Whether the user has JS enabled or not, once all the correct values are present in the $_POST array then the form has been completed and can be processed.

Hey fretburner!

Sorry I didn’t get back to you sooner, it’s been a busy couple of days.

No worries, :slight_smile: I’ve been working on other areas of my website - always something else to do.

if ($_POST[‘booze’][‘beer’] > 0 && isset($_POST[‘somename’][‘beer’]) === false) {
// echo the correct number of select inputs,
// according to the value of $_POST[‘booze’][‘beer’]
}

Thank you, but are you sure this would work? When the page first loads, $_POST[‘booze’][‘beer’] will always be empty. What I’ve done is add the select inputs between noscript tags and this seems to work. Do you think this OK?

Thanks.

Perhaps I misunderstood you - do you want to show the entire form, with all optional inputs, for users who have JS disabled? If so, then I don’t see any problem with your method.

I was thinking that you wanted to start off with the initial input and then have the user submit, add additional inputs and the user submits again, etc. until the form is complete, at which point you’d process it.

The first method produces a longer form with a lot of potentially redundant inputs, but is probably friendlier than the second method as the user doesn’t have to repeatedly submit the form.

Thanks for getting back to me!

Perhaps I misunderstood you - do you want to show the entire form, with all optional inputs, for users who have JS disabled? If so, then I don’t see any problem with your method.

Sorry, yes I’d like to show all the inputs in case JavaScript is disabled.

The first method produces a longer form with a lot of potentially redundant inputs

You are right about that, but I’ll probably stick with this method. Perhaps add a limit as to how many inputs can be produced.

I’ve been playing around with the validation plugin and have noticed that the error messages really hog the input fields. Can I position the error messages somewhere else? I added a div with a class of “placement” below the select menus and am trying to get the error messages to display there, but so far this hasn’t worked. Could you please help me with this?


    $('#myForm').validate({
        errorPlacement: function(error) {
error.appendTo(".placement"  );
}
    });

Thank you, and I hope your Monday is going well.

Sure. Could you post a section of the markup that you’d like to have, showing an input and the error container?

It’s not going too bad, for a Monday :wink:

It’s not going too bad, for a Monday

Good to hear.

Thank you for helping me. The HTML would look like this: The div with the error message would display below the 2 select menus.

Thanks!

<p>Computers A</p>
<select name="somename">
<option>0</option>
<option>1</option>
<option>2</option>
<option>3</option>
</select>
<br /><br />

<p>Computers B</p>
<select name="somename">
<option>0</option>
<option>1</option>
<option>2</option>
<option>3</option>
</select>
<br /><br />

// Display error message here
<div class="errormessage"></div>
<script>
    $('#myForm').validate({ // initialize the plugin
        // other options
    });


$("[name^=somename]").each(function (index) {
var getname = $(this).attr("name");
var errorname = /\\[(\\w+)\\]/.exec(getname)[1];

    $(this).rules("add", {
        required: true,
        min: 1,
        messages: {
            min: "Please select a value for " + errorname + " "
        }
    });
});
</script>

I’ve adapted the following code from the example here: http://jquery.bassistance.de/validate/demo/errorcontainer-demo.html

What you’d need to do is add error messages to the container for each form input:


<div class="errormessage">
    <h4>There are serious errors in your form submission, please see below for details.</h4>
    <ol>
        <li><label for="somename" class="error">Please make a selection for somename</label></li>
    </ol>
</div>

Note that you should add a CSS style to hide the container DIV by default.

Then you add the error settings to the validation plugin:

var container = $('div.errormessage');

$('#myform').validate({
    debug: true,
    errorContainer: container,
    errorLabelContainer: $("ol", container),
    wrapper: 'li'
});

Hey fretburner,

sorry that I didn’t get back to you on this - I hope you are doing fine!

I managed to get the error messages to display in the specific div. Thanks a lot.

One thing I’ve noticed is that the validation occurs even before the form is submitted. If I select, lets say, option 4 from a select menu and I then select option 0, the error message will then display. It should be possible to select an option and then select 0 without the error message popping up. Perhaps there’s a way to do this.

Anyway, hope you will have a great weekend.