I am writing a lot of javascript lately, and I ran into a quirk in the ASP.Net framework that caused a bit of frustration.
Let’s say we have a user interface requirement that calls for a checkbox to indicate using a default value. If the checkbox is not selected, then additional controls must be displayed to capture the non-default value. This is quite straight-forward with jQuery’s hide/show functions. This paradigm is repeated for numerous items on the page.
Since I don’t want to copy/paste javascript all over the place, I re-factored the script to have an onclick function for every checkbox:
DefaultSelector = {
containerId: null,
useDefaultClick: function (e) {
if (e.checked) {
$(e.id + "[related_control_id]").hide();
} else {
$(e.id + "[related_control_id]").show();
}
},
initialize: function (containerId) {
this.containerId = containerId;
// attach an on-click event to the "use default" checkboxes
$("#" + containerId + " input:checkbox").click(function () {
DefaultSelector.useDefaultClick(this);
});
}
};
As you can see in the snippet, I need the id of the control to hide/show. In the server control code, I can use the ClientId property to get that value, but how do I get that value into the useDefaultClick function?
The easiest approach is to put the id into the html as a property. (This is called expando properties.) So, I used the Attributes property of the CheckBox class to add the related control id:
private CheckBox CreateUseDefaultControl(string id, string relatedControlId)
{
CheckBox result = new CheckBox { ID = id };
result.Text = "Use Default";
result.TextAlign = TextAlign.Right;
result.InputAttributes.Add("relatedcontrol", relatedControlId);
return result;
}
Now, I just need to grab that property from the element that is clicked:
useDefaultClick: function (e) {
if (e.checked) {
$(e.relatedControl).hide();
} else {
$(e.relatedControl).show();
}
},
However, it does not work! Digging into the html, I found this nice bit of malformed XHTML:
<SPAN relatedControl="ctl00_TextBox1">
<INPUT id=ctl00_useDefault name=ctl00$useDefault value="" type=checkbox>
<LABEL for=ctl00_useDefault>Use Default</LABEL>
</SPAN>
How nice of the CheckBox class to put the attribute in a containing element. Grrrrr!! The solution: the CheckBox class has to additional attribute collections – InputAttributes and LabelAttributes.