I had a very interesting requirement on one of the pages I was working on in my latest project recently. It of course had to render correctly in both the latest version of IE and Firefox. Not too difficult to do. It had to use our existing masterpage. Ok, again, not difficult at all. In this page, I had a radiobuttonlist control that needed to have a text box control conditionally show or hide based on which button in the list was clicked. Ok, a little more difficult. But that text box control also had to be a required field when it did show. Ok that might be tough to do.
Well here's how we accomplished it
On the page we added our controls
<asp:RadioButtonList ID="RadioButtonList1" runat="server">
<asp:ListItem Value="1">1</asp:ListItem>
<asp:ListItem Value="0">0</asp:ListItem>
<asp:ListItem Value="2">2</asp:ListItem>
<asp:ListItem Value="4">4</asp:ListItem>
</asp:RadioButtonList>
<div id="divTB" style="display:none">
<input id="Text1" type="text" onKeyPress="return ValidationError()" />
<span id="lblValidator" style="display:block;"></span>
</div>
<asp:Button runat="server" ID="btn" Text="submit" OnClick="btn_Click" />
<asp:Label runat="server" ID="lblErr" ></asp:Label>
Now let me explain what you are looking at here. First you see the radiobuttonlist control with four buttons in it. Next we have a div that will eventually be the mechanism to show and hide the textbox control and span you see inside of it. The span inside of that div is what is going to server as our custom required field validator. Next you see the traditional submit button with it On Click event handler and finally a label to show us if anything went wrong.
We needed to capture the click event from each button in the radiobuttonlist and do something if it was a certain value (show or hide the div & the control inside of it) so to do that we add the javascript as an attribute in the Page_Load event of the .CS. We also need to add a handler for the submit button to check if text has been entered in the textbox, if it is showing.
protected void Page_Load(object sender, EventArgs e)
{
btn.Attributes.Add("onclick", "return ValidateText()");
RadioButtonList1.Attributes.Add("onclick", "return
rbClick(event)");
}
You might be wondering why we are passing the event as a parameter in the rbClick event. Well we need to get access to the event variable so that we can know what it was that was clicked on the page. With this event, we will know what the value of that item was so that we can make a decision on whether or not to show or hide our div. In IE we can use window.event but that not a standard mechanism so therefore we need to pass the event to our function so that we can be sure to be standards compliant.
In the aspx page we now add our javascript functions. We have three:
- One to handle the clicking of a radiobutton (rbClick)
- One to handle the validation of the textbox (ValidateText)
- One to remove the validator once we begin to type something in the textbox (ValidationError)
Here is the code:
<script type="text/javascript">
<!--
function rbClick(evt)
{
evt = (evt) ? evt : ((window.event) ? window.event : "")
if (evt)
{
var elem
if (evt.target)
{
elem = (evt.target.nodeType == 3) ? evt.target.parentNode:
evt.target
}
else
{
elem = evt.srcElement
}
if (elem)
{
// process event here
if ((elem.value == 0) ||(elem.value == 4) )
{
document.getElementById("divTB").style.display=
"none";
}
else
{
document.getElementById("divTB").style.display= "block";
}
}
}
}
function ValidateText()
{
if(document.getElementById("divTB").style.display== "block")
{
var tbtext = document.getElementById("Text1").value;
if((tbtext == null) ||(tbtext.length==0))
{
if(document.all)
{
document.getElementById("lblValidator").innerText =
"required Field";
}
else
{
document.getElementById("lblValidator").textContent =
"required Field";
}
return false;
}
else
{
return true;
}
}
return true;
}
function ValidationError()
{
document.getElementById("lblValidator").style.display ="none";
}
</script>
Now lets take a look at the rbClick function. First off this is the one that we had to send the event to and we handle window.event IE/Firefox non-standard issue right off the bat. Depending on how the current browser handles the passing of the event to the function, we either leave the event alone as passed, assign the variable the window.event for IE, or give it nothing.
evt = (evt) ? evt : ((window.event) ? window.event : "")
Now we need to get the element that triggered the event but if it's a text object that fired the event we want to get it's parent control. Again, we have to take into consideration the difference between a standards compliant browser and IE
if (evt)
{
var elem
if (evt.target)
{
//if this is a text object, get it's parent
elem = (evt.target.nodeType == 3) ? evt.target.parentNode :
evt.target
}
else
{
//handle IE...
elem = evt.srcElement
}
if (elem)
{
// process event here
}
}
So once we have the element we can then figure out what was clicked, what the value was and either hide or show our div.
if ((elem.value == 0) ||(elem.value == 4) )
{
//hide the div
document.getElementById("divTB").style.display= "none";
}
else
{
//show the div
document.getElementById("divTB").style.display= "block";
}
In the ValidateText function that gets fired when the submit button if pressed, we need to figure out if the div is hidden or displayed firstly.
if(document.getElementById("divTB").style.display== "block")
If the the div is hidden we don't need to do anything because that means that the value clicked did not require any text to be entered into the textbox inside the div. If on the other hand the div is shown (style.display=="block") then we have to see if the user actually put anything inside the textbox. We do that by getting the value of the element and checking if it is null or of 0 length.
If the user has not entered any text we then need to tell them that the textbox is a required field and return false so that the page won't postback. We do this by dynamically adding some text into the empty span we have placed next to our text box. If there is a vlaue in the textbox we post back and process the text. Of course, we have to handle the fact that IE doesn't use standards...
if((tbtext == null) ||(tbtext.length==0))
{
if(document.all)
{
//Handle IE again...
document.getElementById("lblValidator").innerText = "required Field";
}
else
{
document.getElementById("lblValidator").textContent = "required Field";
}
//stop the postback
return false;
}
else
{
return true;
}
Finally, if the user does begin to enter text into the textbox then we need to hide the text we just added into the span. We accomplish this by catching the OnKeyPress event so that we can know that it was an alphanumeric key that was pressed and setting the display of the span to "none".
document.getElementById("lblValidator").style.display = "none";