Jason Salas' WebLog

On-air and online: making people laugh, making people think, pissing people off

Sponsors

ASP.NET sites that kick ass

Pals with blogs

Podcasts I listen to

Server-side/client-side validation for TextBox controls with default values in ASP.NET 1.x

One of the most challenging things facing web developers using is providing great data validation.  You want to ensure that the user won't enter erroneous or malformed information, and try to reduce postbacks as much as possible - all while delivering a solid user interface through which the user can enter their stuff.  Personally, I hate crafting long tables with extraneous rows of unnecessary cells, mainly just containing the name of the field to be entered. 

One of the best ways to get around this is to indicate the field name within a TextBox itself.  But, the default implementation of the RequiredFieldValidator control in ASP.NET 1.x mandates that control determine the page to be invalid if the fields are blank, which defeats the whole point.  So if we provide default values, we negate this, right?  How can we get around it?

In the code sample below, two TextBox fields - txtName and txtEmail - are validated against on both the client and server.  This is accomplished using separate client-side JavaScript routines - clearText() and resetText(), which handle the OnFocus and OnBlur JavaScript events, respectively.  I do this by adding to the Attributes collection of each control in a helper method that's called within the server-side Page_Load event.  The default values are entered into the controls declaratively at design-time, which eliminates the need to add HTML table cells.  Note also that the value of the RequiredFieldValidators' "InitialValue" properties mirror the default values for the TextBoxes.  This ensures they will fail validation if the user doesn't change them.

Next, the OnSubmit client-side event is handled by the validate() routine defined in the JavaScript within the page's <HEAD> tags.  This event fires before the page posts back, so if the fields have been tabbed past (or skipped altogether), the user will be presented with a client-side JavaScript alert dialog window.  The server validation controls for each TextBox guarantee proper processing only if they're empty, aren't matching their InitialValue values (and in the case of txtEmail, an additional RegularExpressionValidator is added to make sure the e-mail address is properly formatted).

It's not totally drag-and-drop friendly to provide effective validation on the client and server in ASP.NET 1.x, but it's actually quite simple to do so on your own.


<%@ Page Language="C#"  %>
<script runat="server">
   
    protected void Page_Load(object sender,EventArgs e)
    {
        GiveTextControlsFocus();
    }

    private void GiveTextControlsFocus()
    {
        txtName.Attributes.Add("onfocus","clearText('txtName')");
        txtName.Attributes.Add("onblur","resetText('txtName')");
        txtEmail.Attributes.Add("onfocus","clearText('txtEmail')");
        txtEmail.Attributes.Add("onblur","resetText('txtEmail')");
    }
   
    private void RegisterUser(object sender,EventArgs e)
    {
        pnlForm.Visible = false;
        lblConfirmation.Text = "Thanks for filling out the form!";
    }
   

</script>
<html>
<head>
    <script language="JavaScript">
        <!--
        function clearText(control) {
            document.frmRegister[control].value = "";
            document.frmRegister[control].focus();
            document.frmRegister[control].style.backgroundColor = "#ffffcc";
        }
       
        function resetText(control,defaultText) {
            if(document.frmRegister[control].value == "") {
                document.frmRegister[control].style.backgroundColor = "#ffffff";
            }
        } 
       
        function validate() {
            if(document.frmRegister["txtName"].value == "") {
                alert("Your NAME is required");
                return false;
            }
           
            if(document.frmRegister["txtEmail"].value == "") {
                alert("Your EMAIL ADDRESS is required");
                return false;
            }
        }
        // -->
    </script>
</head>
<body>
    <form id="frmRegister" onsubmit="return validate()" runat="server">
        Register for cool stuff!
        <br/>
        <asp:Label id="lblConfirmation" font-size="14pt" forecolor="maroon" font-bold="true" runat="server" />
        <asp:Panel id="pnlForm" runat="server">
            <table style="WIDTH: 300px; HEIGHT: 150px">
                <tbody>
                    <tr>
                        <td>
                            <asp:TextBox id="txtName" text="Name" columns="23" maxlength="30" runat="server" />
                            <br />
                            <asp:RequiredFieldValidator id="validateName" initialvalue="Name" controltovalidate="txtName" display="dynamic" text="* Required" runat="server" />
                        </td>
                    </tr>
                    <tr>
                        <td colspan="2" align="center">
                            <asp:TextBox id="txtEmail" text="E-mail" columns="45" maxlength="60" runat="server" />
                            <br />
                            <asp:RequiredFieldValidator id="validateEmail" initialvalue="E-mail" controltovalidate="txtEmail" display="dynamic" text="* Required" runat="server" />
                            <asp:RegularExpressionValidator id="regexValidate" validationexpression="^[\w-]+(?:\.[\w-]+)*@(?:[\w-]+\.)+[a-zA-Z]{2,7}$" controltovalidate="txtEmail" display="dynamic" text="* Invalid Address" runat="server" />
                        </td>
                    </tr>
                    <tr>
                        <td colspan="2" align="center">
                            <asp:Button runat="server" onclick="RegisterUser" Text="Register me!" />
                        </td>
                    </tr>
                </tbody>
            </table>
        </asp:Panel>
    </form>
</body>
</html>

Comments

Jason Row said:

Interesting concept. Personally from a design point I think you should have labels for each of the textbox controls.

I'm using FireFox and if you Tab through the controls without filling each one out in turn then your descriptions end up being lost. Just adds some confusion is all.

If you still want to go with this idea can you create these as custom controls?
# July 27, 2005 3:43 PM

Jason Salas said:

Hi Jason,

Yeah, I guess it would be better design to apply ToolTips to the TextBox controls, too, huh? :)

Here's an interesting case study: goto http://www.kuam.com/decision2004/ in MSIE and mouseover the left navigation bar. I used aspNetMenu to create this. Now view the same thing in FireFox. Ouch.
# July 27, 2005 7:08 PM

Jason Row said:

Well maybe tooltips would reduce my hesitation in using such a design. But hey, you're not building web pages for me so do what you like! :)

Oh the joys of cross-browser development. How I miss the old IE and Netscape days :) Nice to see that while the players change some things stay the same.
# July 27, 2005 7:38 PM

Jason Salas said:

OR...we could just use/extend the Login control that ships with ASP.NET v.2.0 and this would all be a moot point. I haven't tried that control's cross-browser compatability...have you?
# July 27, 2005 7:40 PM

Jason Row said:

Not yet. I've only seen some demos of ASP.NET 2.0 in action and those have all been with IE as the browser.

I just got ASP.NET 2.0: A Developer's Notebook from O'Reilly for my local user group so that should motivate me to build some web apps. Since I use FireFox at home and at the office I'll keep an eye out for cross-browser issues. Geeze I hope the login control is cross-browser. It might not be used otherwise.
# July 27, 2005 8:10 PM
Leave a Comment

(required) 

(required) 

(optional)

(required)