4

Before I start I'd just like to state that the code created by ASP.NET for CheckBoxLists is probably the worst thing I've ever seen.

Anyway,

I am using the jQuery validation plugin to validate my ASP.net form. There is a requirement to validate some checkboxes. These are generated by a CheckBoxList control.

<asp:CheckBoxList ID="CBContext" runat="server" RepeatColumns="2" 
              DataSourceID="sqlLibraryEnquiries" DataTextField="value" DataValueField="value" name="topic">
</asp:CheckBoxList>

This control produces the following abomination of xHTML

<table id="MainContent_CBContext" name="topic">
    <tr>
        <td>
          <input id="MainContent_CBContext_0" type="checkbox" name="ctl00$MainContent$CBContext$0" value="Business" /><label for="MainContent_CBContext_0">Business</label>
        </td>
        <td>
          <input id="MainContent_CBContext_2" type="checkbox" name="ctl00$MainContent$CBContext$2" value="Legal" /><label for="MainContent_CBContext_2">Legal</label>
        </td>
    </tr>
    <tr>
        <td>
           <input id="MainContent_CBContext_1" type="checkbox" name="ctl00$MainContent$CBContext$1" value="Business Development" /><label for="MainContent_CBContext_1">Business Development</label>
        </td>
        <td>
           <input id="MainContent_CBContext_3" type="checkbox" name="ctl00$MainContent$CBContext$3" value="Library" /><label for="MainContent_CBContext_3">Library</label>
        </td>
    </tr>
</table>

The issue I am having is actually getting the jQuery Validator plugin to hook into the checkbox list. In my rules section for all the other fields I can get to them with their names for example ctl00$MainContent$tbActions: but the checkboxes all have different names.

The cb_selectone rule isn't firing because the object I am trying to validate is never found. I have tried the following identifiers. CBContext, ctl00$MainContent$CBContext, MainContent_CBContext and checkboxes.

$("#Form1").validate({

     rules: {
     //WHAT GOES HERE???? --------->>    CBContext or ctl00$MainContent$CBContext or MainContent_CBContext or checkboxes all don't work: {
            cb_selectone: true
         }
      }
});

Thanks for your help.

SM

4
  • Why do you think the way asp renders the checkboxes is an abomination? Just curious... Commented Feb 7, 2012 at 13:51
  • 1
    The naming convention sucks, There is no need for eachone to have a different name, when they have ID's. Also why tables and not spans? It's just not easy to work with from a DOM point of view. Commented Feb 7, 2012 at 14:02
  • 1
    The naming convention part is true for all controls implementing INamingContainer interface, and I agree with you with the different name thing. Also, true, why table and not spans? Maybe there is an unknown secret reason behind all this. Commented Feb 7, 2012 at 14:09
  • I just think it's a bit dated now. M$ crowbarred jQuery into VS2010 but some of the old technology just isn't very compatible. :-/ Commented Feb 7, 2012 at 14:13

5 Answers 5

3

I made a small adjustment in the JAVASCRIPT method:

$.validator.addMethod('cb_selectone',
    function (value) {
        if ($('[id$=CBContext] input:checked').length > 0) {
            return true;
        }
        else
        {
            return false;
        }
    }, ""
);
Sign up to request clarification or add additional context in comments.

1 Comment

Why not just use return ($('[id$=CBContext] input:checked').length > 0)
1

Ok I Solved it......

What I did was create a new validator method that gets all the objects of type input that match a regex of MainContent_CBContext. This returns an array of all the checkboxes.

Then loop round the array and check if the attr is checked. If any of them are then set the return as true.

$.validator.addMethod('cb_selectone', function (value, element) {
     if (debug) {
         $.jGrowl("Adding Validation");
     }
     var chkGroup = $("input[id^=MainContent_CBContext]");
     if (chkGroup.length > 0) {
         for (var i = 0; i < chkGroup.length; i++) {
             if ($(chkGroup[i]).attr('checked')) {
                 if (debug) {
                    // alert(i + $(chkGroup[i]).val());
                     $.jGrowl("Running loop " + i + " = " + $(chkGroup[i]).val());
                 }
                 return true;
             }
         }
         return false;
     }
     return false;
 }, 'Please select at least one option');

The part I was stuck on was finding an object to fire off the addMethod code. In the end I just used...

ctl00$MainContent$CBContext$2: {
   cb_selectone: true
}

This meant that the label is placed next to this field, it's purely cosmetic. The important thing is the validator code was finally bound to a real object and fired correctly.

SM

Comments

0

How the list renders makes it complex. I would consider creating your own validation method, and use the root control's ID, and have the validation method parse the inner children:

2 Comments

Thats's what I am trying to do. But it won't fire because it doesn't have an object to attach to.
Ok I solved it. I will post details as soon as stackoverflow let me.
0

Did you try something like this:

$("#Form1").validate({
     rules: {
        <%=CBContext.UniqueID %>: {
            cb_selectone: true
         }
      }
});

6 Comments

The problem with this is the code is in a .js file so the <% tag won't work.
@smitchelluk Then you will need to either pull that statement out of the JS file and put it in the page, or provide a workaround. It could be using a global variable in the page: var comboID = '<%= CBContext.UniqueID %>'; and then in the JS file, refer to comboID. I personally don't like that, but it would work.
Annoyingly, again that won't work because CBContext.UniqueID returns ctl00$MainContent$CBContext jQuery doesn't see an object called that because ASP.Net creates input fields for each item called ctl00$MainContent$CBContext$1,2,3.... etc. Using the UniqueID is how I am validating all my other fields but for this it won't work. :-/
I guess you would have to create your own custom validator for just that asp.net control or use basic html checkboxes and give them the runat="server" attribute and see if you have better luck.
maybe something like this... function validateCB() { var valid = false; var i = 0; $.each($('#ctl00_ContentPlaceHolder1_CBContext :input'), function () { if ($(this).attr('checked') === 'checked') { if (i === 0) { valid = true; } i++; } }); if (i > 1) { valid = false; } return valid; } Or why don't you just use a radio button list since by default is only alows you to select one.
|
0
$("input:checked") 

is the selector that'll grab all checked checkboxes

I've used this for simple validation like:

function testChecks() {
    var n = $("input:checked").length;
    if (n > 6) {
        alert("Please select up to six attributes.");
        return false;
    }
    if (n < 1) {
        alert("You must select at least one attribute.");
        return false;
    }
    return true;
}

I imagine you could just do

$("input:checked").add("input:not(:checked)").Validate({
//....
});

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.