04 February, 2008

Working Client-Side with CheckBoxLists

One of the new things I have been playing with are CheckBoxLists. This is a server control which is DataBindable. It creates a list of CheckBox controls. You can define if the list is displayed horizontally, or vertically. I am using a couple of these in a new application and ran into some problems accessing them with JavaScript. This application doesn't ever do a real-honest-to-goodness postback. Instead, all calls to the server are handled through Callbacks. Callbacks aren't really what I'm here to talk about, so if you need to learn more about them, I would recommend popping on over to ASP.NET and checking out their forums and other areas of that site. It is chock full of excellent information.

Ok, back to where I was. Getting to the CheckBoxList stuff. The CheckBoxList renders its ID on the HTML side slightly different from a normal control. Since the control generates multiple sub-controls. For instance, normally, if you had a CheckBox and gave it the ID of "myCheckBox" then to access it in JavaScript you'd simply do something like var chkbx = document.getElementById('<%=myCheckBox.ClientID %>'); and voila! you have access to your CheckBox control. But as stated, the CheckBoxList generates multiple CheckBoxes. The problem was how in the world do I access these? How do I do capture a client side event with a databound list like this? I mean, the list could change daily right? What I came up with (and it probably isn't the _best_ way to go about it, but it certainly works) is to add an attribute to the generated CheckBox in the DataBound EventHandler for the CheckBoxList control. Using DataBound of course because that means the list has been completed.

The CheckBoxList, like the DropDownList (and several other controls) contains the .Items parameter which is the ListItemCollection object. What I ended up doing is adding an "onclick" attribute to each item, passing to the JavaScript the client id of the actual CheckBox control, the text and the value (really, I only needed the control client id and the text, but I figured I'd go ahead and throw in the value for good measure. I separated the ClientID, Text and Value data with a colon (:) so I could easily split it back on the client side.

protected void checkBoxList_DataBound(object sender, EventArgs e)
{
CheckBoxList cbl = (CheckBoxList)sender;
for (int i = 0; i < style="color: rgb(51, 51, 255);">string controlName = cbl.ClientID + "_" + i;
cbl.Items[i].Attributes.Add("onclick", "javascript:checkBoxChanged('" + controlName + ":" + cbl.Items[i].Text + ":" + cbl.Items[i].Value + "')");
cbl.Items[i].Selected = true;
}
}


I use the same DataBound Event Handler for all of the CheckBoxList controls since there is nothing happening that is actually specific to any one CheckBoxList, they all call the same JavaScript. However, getting the control information, and whether or not it is checked, back to the client side is only half the battle. The check boxes are part of a data filter which will display data in a GridView. The user can click on or off all or part of the list items to decrease or expand the scope of the data displayed. So I need to put these checked boxes into some kind of JavaScript array so that when the time comes to do the Callback to populate the GridView, I have all the required data to build the filter server-side.

var checkedBoxesArray = new Array();
function checkBoxChanged(controlInfo) {
var ary = controlInfo.split(":");
var chkBx = document.getElementById(ary[0]);
if(chkBx.checked) {
// check to see if the check box already exists (it shouldn't)
for(x in checkedBoxesArray) {
if(controlInfo == checkedBoxesArray[x]) return; // <-- get out of here, it's already there, and there is nothing else to do
}
checkedBoxesArray[checkedBoxesArray.length+1] = controlInfo;
}else {
for(x in checkedBoxesArray) {
// find the checkbox information in the array and remove it (it should be there)
if (controlInfo == checkedBoxesArray[x]) {
checkedBoxesArray.splice(x,1);
break; // <-- No use going through all of them if we don't have to , right?
}
}
}
}


Then I could access the checkedBoxesArray in the JavaScript function which actually creates the querystring style callback event arguments which are used on the server-side to create the data filter.

No comments: