jQuery & JavaScript

Validate an ASP.NET CheckBoxList with JavaScript or jQuery (at least one, at most N)

jQuery & JavaScript · · Published 2026-08-24

A RequiredFieldValidator cannot target a CheckBoxList: the list renders many inputs, not one value. The standard answer is a CustomValidator with a client-side function and the same rule on the server. The client function is a few lines in plain JavaScript or jQuery.

Markup

<asp:CheckBoxList ID="cblTopics" runat="server" RepeatLayout="Flow" CssClass="topics">
    <asp:ListItem Value="web">Web Forms</asp:ListItem>
    <asp:ListItem Value="sql">SQL Server</asp:ListItem>
    <asp:ListItem Value="js">JavaScript</asp:ListItem>
    <asp:ListItem Value="css">CSS</asp:ListItem>
</asp:CheckBoxList>
<asp:CustomValidator ID="cvTopics" runat="server" Display="Dynamic"
    ErrorMessage="Choose between one and three topics."
    ClientValidationFunction="validateTopics"
    OnServerValidate="cvTopics_ServerValidate" />
<asp:Button ID="btnSubscribe" runat="server" Text="Subscribe" OnClick="btnSubscribe_Click" />

Leave ControlToValidate empty: a CustomValidator without it still runs, and it would not accept a CheckBoxList as target anyway. The list renders one <input type="checkbox"> per item, with ids such as cblTopics_0, cblTopics_1, inside a container whose id is the list's ClientID.

Client function: plain JavaScript

<script>
  function validateTopics(source, args) {
    var list = document.getElementById("<%= cblTopics.ClientID %>");
    var checked = list.querySelectorAll("input[type=checkbox]:checked").length;
    args.IsValid = checked >= 1 && checked <= 3;
  }
</script>

ASP.NET calls the function with the validator (source) and an object whose IsValid you set. The check runs when the button is clicked, before the postback.

Client function: jQuery

function validateTopics(source, args) {
  var checked = $("#<%= cblTopics.ClientID %> input:checkbox:checked").length;
  args.IsValid = checked >= 1 && checked <= 3;
}

// Optional: re-validate as soon as a box changes, so the message disappears immediately
$(function () {
  $("#<%= cblTopics.ClientID %>").on("change", "input", function () {
    ValidatorValidate(document.getElementById("<%= cvTopics.ClientID %>"));
  });
});

ValidatorValidate is part of ASP.NET's validation script and re-runs a single validator.

Server-side check (always)

protected void cvTopics_ServerValidate(object source, ServerValidateEventArgs args)
{
    int count = cblTopics.Items.Cast<ListItem>().Count(i => i.Selected);
    args.IsValid = count >= 1 && count <= 3;
}

protected void btnSubscribe_Click(object sender, EventArgs e)
{
    if (!IsValid) return;   // validators have run; never skip this
    var topics = cblTopics.Items.Cast<ListItem>().Where(i => i.Selected).Select(i => i.Value).ToList();
    Subscribe(topics);
}

Client validation is for convenience; a user can disable it or post directly. Page.IsValid covers both the server-side handler and the other validators on the page.

Accessibility

With RepeatLayout="Flow" the items are rendered in spans; the default Table layout uses a table. In both cases, wrap the list in a <fieldset> with a <legend> ("Topics") so screen readers announce the group name with each box.

Same technique for other list controls: RadioButtonList and DropDownList.

Common mistakes

Official documentation