Wednesday, February 15, 2012

Check all ASP CheckBoxes within an ASP Repeater with JavaScript to avoid PostBack

Problem:





I created my own CheckBoxList with an ASP Repeater that contained several ASP CheckBoxes and some labels. I also wanted to have the function to check and uncheck all the checkboxes within the repeater. This was easy to do with an OnCheckedChanged=”SomeCodeBehind” and AutoPostBack=”true” on the design file. This gave a working result but since it made a post back each time, the control flashed for a quick second every time the checkbox was clicked and sometimes even gave me time enough to click on the checkbox multiple times. In other words, it gave an impression of a slow application.

The next problem appeared when this controlwas inserted in to an AJAX Modal Popup window. Whenever the control made a postback the modal popup was closed. A solution would be to make an EventHandler for each time the checkbox is clicked, in that way the event could be caught within the parent control and trigger a function to reopen the modal popup again. But since this event is not needed in any other situation this solution felt a bit to much.

Solution

Javascript! But the first question that arised was "How to get hold of all the elements within a repeater?" Well it is not that complicated actually. First of let me show the design of my repeater:

HTML:




<div id="Div_CheckBoxList">
<asp:repeater id="Repeater_CheckBoxList" runat="server">
<headertemplate>
<table id="Table_CheckBoxList">
<tr>
<th>
<asp:checkbox id="CheckBox_CheckAll" runat="server"></asp:checkbox>
</th>
<th>
<asp:label id="Label_CheckAllText" runat="server" text="Check/Uncheck all"></asp:label>
</th>
</tr>
</headertemplate>
<itemtemplate>
<tr>
<td>
<asp:checkbox id="CheckBox_RepeaterItem"></asp:checkbox>
</td>
<td>
<asp:label id="Label_CheckBoxText" runat="server"></asp:label>
</td>
</tr>
</itemtemplate>
</asp:repeater>
</div>




And now to the magic! Here is the javascript function checkAll that checks and unchecks all the checkboxes within the repeater. It obtains the client ID (since we are working with ASP controls) of the element that contains all the checkboxes. It could be a panel or a div, but in this case we use the repeaters client ID.

All the elements within this "container" are then extracted and iterated through. What we are looking for is an element with an ID that contains the word "checkbox". And we also know that the first checkbox that we will find (since it is furtherest up in the page) is the "check/uncheck all"-checkbox. The interesting thing about that checkbox is to know if it is checked or unchecked to be able to check the rest equally. And that would be all!

NOTE! You maybe ask yourself why we do not get all the elements from the document, document.getElementsByTagName('*') instead? Well that is because sometimes there might be other checkboxes on the page, or in my case I want to be able to introduce two repeaters on the same page, without clicking the "check/uncheck all"-checkbox on one repeater also affects the other one.

JavaScript



function checkAll(containerClientID) {
var repeater = document.getElementById(containerClientID);
var all = repeater.getElementsByTagName('*');
var found = false;
var isChecked = true;
for (var i = 1; i < all.length; i++) {
var e = all[i];
if (e.id.toUpperCase().indexOf("CHECKBOX") != -1) {
if (found) {
e.checked = isChecked;
}
else {
isChecked = e.checked;
found = true;
}}}}


To be able to use this javascript following change must be done on the HTML code:

HTML



<asp:CheckBox id=&quot;CheckBox_CheckAll&quot; ...
onClick='<%# "javascript:checkAll(\"" + this.Div_AlternatingTable.ClientID + "\");" %>'
... />


The following code is for making only one checkbox in the repeater to be able to be selected simultaniously.

JavaScript



function checkOne(containerClientID, checkboxIndex) {
var repeater = document.getElementById(containerClientID);
var all = repeater.getElementsByTagName('*');
var currentCheckboxIndex = 0;
for (var i = 1; i < all.length; i++) {
var e = all[i];
if (e.id.toUpperCase().indexOf("CHECKBOX") != -1) {
if (currentCheckboxIndex != checkboxIndex) {
e.checked = false;
}
currentCheckboxIndex++;
}}}


And the following changes need to be done on the HTML

HTML



<asp:CheckBox id=&quot;CheckBox_RepeaterItem&quot; ...
onClick='<%# "javascript:checkOne(\"" + this.Div_AlternatingTable.ClientID + "\",\"" + Container.ItemIndex + "\");" %>'
... />

No comments:

Post a Comment