Introduction
In one of my articles, I discussed how to select checkboxes inside the GridView control. You can view the article here. This is an extension to that article in which, I will discuss some additional features. These features include using regular expression to limit the checkbox selection on a particular GridView
and de-selecting the parent checkbox
when all child checkboxes are un-checked.
Creating the GridView Control
The first task is to create a simple GridView
control using template fields. I strongly recommend using template fields instead of bound fields for the following reasons:
- Template fields allow embedding the ASP.NET controls.
- You don’t have to reorganize the appearance of the
GridView
after a new template field is added. This is because template field does not depend on the index number like the bound fields. - Template fields allow access to ASP.NET controls even if the fields are not visible.
Finally, here is the code for the GridView
control.
<asp:GridView ID="GridView1" runat="server"
AutoGenerateColumns="false">
<Columns>
<asp:TemplateField>
<HeaderTemplate>
<input type="checkbox" id="chkAll" name="chkAll"
onclick="Check(this)" />
</HeaderTemplate>
<ItemTemplate>
<asp:CheckBox ID="chkSelect" runat="server" />
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField>
<ItemTemplate>
<asp:Label ID="lblCategoryName" runat="server"
Text = '<%# Eval("CategoryName") %>' />
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
The HeaderTemplate
contains the HTML checkbox and serves as the parent checkbox. The ItemTemplate
contains the ASP.NET checkboxes.
Populating the GridView Control
I have used DataSet
to populate the GridView
control, but you can use any type of container object to complete the task.
private void BindData()
{
string connectionString = "Server=localhost;
Database=Northwind;Trusted_Connection=true";
SqlConnection myConnection = new SqlConnection(
connectionString);
SqlDataAdapter ad = new SqlDataAdapter("SELECT
CategoryID, CategoryName FROM Categories",
myConnection);
DataSet ds = new DataSet();
ad.Fill(ds);
GridView1.DataSource = ds;
GridView1.DataBind();
}
Now, if you run the application, you will see the GridView
displayed on the page.
NOTE: I have added styles to make the GridView
look pretty!
Selecting and Deselecting CheckBoxes
At this point, your GridView
control is displayed on the page and we need to implement the functionality to select and deselect all the child checkboxes when the parent checkbox is checked.
If you take a look at the GridView
HTML code, you will notice that the parent checkbox (chkAll
) fires the Check
function when clicked. Let’s see the Check
function implementation.
function Check(parentChk)
{
var elements = document.getElementsByTagName("INPUT");
for(i=0; i<elements.length;i++)
{
if(parentChk.checked == true)
{
if( IsCheckBox(elements[i]) &&
IsMatch(elements[i].id))
{
elements[i].checked = true;
}
}
else
{
elements[i].checked = false;
}
}
}
The Check
function is responsible for selecting and deselecting all the child checkboxes. First, I retrieve all the objects whose tag name is “INPUT
”. Inside the loop, I check whether the parent checkbox is checked or not. If it is checked, then I find the correct checkbox element and mark it checked. The functions, IsCheckBox
and IsMatch
are responsible for finding the child checkboxes.
Before I explain the working of the two methods, let’s see your little regular expression which separates the GridView
checkboxes from other checkboxes on the page and even from the checkboxes inside other GridView
controls.
Here is our little regular expression:
var pattern = '^GridView1';
The expression says that select every string
whose name starts with “GridView1
”. You might be wondering how this expression can help to find the correct child checkboxes. In order to understand it, let’s take a look at the HTML code that is generated when the GridView
is rendered on the page.
You can see that the checkboxes inside the GridView
control are assigned unique ids. The first part contains the id of the GridView
which, in this case is “GridView1
”. The middle part contains the row number and the final part contains the original id of the checkbox
as set by the developer.
Now, let’s take a look at the IsMatch
function which, takes the id of the control as a parameter and returns true
if matched, else returns false
.
function IsMatch(id)
{
var regularExpresssion = new RegExp(pattern);
if(id.match(regularExpresssion)) return true;
else return false;
}
The IsMatch
function is not enough. Huh! The reason is that we are not checking for the type of the element. The element which has the “INPUT
” tag can be a checkbox, radio, textbox, button, etc. For that reason, there is another small method called IsCheckBox
which simply checks for type of the element.
function IsCheckBox(chk)
{
if(chk.type == 'checkbox') return true;
else return false;
}
All the code that we have discussed will allow you to check and uncheck all the checkboxes based on the parent checkbox. The code also checks for the particular GridView
so, that other checkboxes on the page are not affected.
Attaching Listeners to the Child CheckBoxes
Listeners allow you to catch events generated by the controls and take action on those events by firing a function. Scott Andrew wrote an excellent piece of code that attaches the listeners to the object. The code is browser compatible (I have tested on Mozilla and IE).
function AddEvent(obj, evType, fn)
{
if (obj.addEventListener)
{
obj.addEventListener(evType, fn, true);
return true;
}
else if (obj.attachEvent)
{
var r = obj.attachEvent("on"+evType, fn);
return r;
}
else
{
return false;
}
}
I won’t be explaining the insights of this function but if you are really interested, then you should check out this link. The AddEvent
function is fired from the function AttachListener
.
function AttachListener()
{
var elements = document.getElementsByTagName("INPUT");
for(i=0; i < elements.length; i++)
{
if( IsCheckBox(elements[i]) &&
IsMatch(elements[i].id))
{
AddEvent(elements[i],'click',CheckChild);
}
}
}
In the code above, I am registering the ‘click
’ event of the checkbox
es with a listener. Any time the click event is fired from the child checkboxes, the CheckChild
function is fired. The AttachListener
is fired on the following event:
<body onload="AttachListener()">
The CheckChild Function
The CheckChild
function keeps track of how many child checkboxes are checked. When all the child checkboxes are checked, then the parent checkbox should also be checked.
function CheckChild(e)
{
var evt = e || window.event;
var obj = evt.target || evt.srcElement
if(obj.checked)
{
if(counter < GetChildCheckBoxCount())
{ counter++; }
}
else
{
if(counter > 0) { counter--; }
}
if(counter == GetChildCheckBoxCount())
{ document.getElementById("chkAll").checked = true; }
else if(counter < GetChildCheckBoxCount())
{ document.getElementById("chkAll")
.checked = false;
}
}
The total of checked checkboxes is stored in the global variable called “counter
”. Once, the counter reaches the total child checkboxes, then the parent checkbox is checked. With the global variable counter in-place, there is also a small change in the Check
function. Take a look at the final Check
function.
function Check(parentChk)
{
var elements = document.getElementsByTagName("INPUT");
for(i=0; i<elements.length;i++)
{
if(parentChk.checked == true)
{
if( IsCheckBox(elements[i]) &&
IsMatch(elements[i].id))
{
elements[i].checked = true;
}
}
else
{
elements[i].checked = false;
counter = 0;
}
}
if(parentChk.checked == true)
{
counter = GetChildCheckBoxCount();
}
}
Few, extra lines are added to reset the counter. The method GetChildCheckBoxCount()
is pretty simple and you can view the source in the download.
Conclusion
I hope you liked the article, happy coding!
History
- 27th January, 2007: Initial version