Take the 2-minute tour ×
Stack Overflow is a question and answer site for professional and enthusiast programmers. It's 100% free, no registration required.

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

share|improve this question
    
Why do you think the way asp renders the checkboxes is an abomination? Just curious... –  Hanlet Escaño Feb 7 '12 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. –  smitchelluk Feb 7 '12 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. –  Hanlet Escaño Feb 7 '12 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. :-/ –  smitchelluk Feb 7 '12 at 14:13

5 Answers 5

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;
        }
    }, ""
);
share|improve this answer
1  
Why not just use return ($('[id$=CBContext] input:checked').length > 0) –  Dayan Apr 4 '14 at 15:22
up vote 1 down vote accepted

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

share|improve this answer

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:

share|improve this answer
    
Thats's what I am trying to do. But it won't fire because it doesn't have an object to attach to. –  smitchelluk Feb 7 '12 at 13:46
    
Ok I solved it. I will post details as soon as stackoverflow let me. –  smitchelluk Feb 7 '12 at 15:49

Did you try something like this:

$("#Form1").validate({
     rules: {
        <%=CBContext.UniqueID %>: {
            cb_selectone: true
         }
      }
});
share|improve this answer
    
The problem with this is the code is in a .js file so the <% tag won't work. –  smitchelluk Feb 7 '12 at 14:05
    
@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. –  Brian Mains Feb 7 '12 at 14:31
    
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. :-/ –  smitchelluk Feb 7 '12 at 14:40
    
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. –  zgood Feb 7 '12 at 14:43
    
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. –  zgood Feb 7 '12 at 15:01
$("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({
//....
});
share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.