User availability check usability improvements
AJAX, ASP.NET, CSS, UI By Dave Ward on July 9th, 2007This is a follow-up post, building on the foundation laid in ASP.NET AJAX username availability check. In this post, I assume you’ve read and understood the first post.
After originally implementing AJAX username availability checking in my applications, I noticed an edge case scenario that replayed itself too often to ignore. The availability check could potentially take longer than a particularly fast user would need to complete the form. To avoid any trouble in that scenario, I wanted to add a progress indicator to the checking process and disable the submit button’s until an available username was selected.
Adding the progress indicator
For the progress indicator, I basically copied the technique described in my CSS style as AJAX progress indicator post. I added another background image CSS class, progress:
.progress { background-image: url(spinner.gif); }
Then, added this client script to the page:
// Hook the InitializeRequest event. Sys.WebForms.PageRequestManager.getInstance().add_initializeRequest(Init); function Init(sender, args) { // Change div's CSS class and text content. $get('UserAvailability').className = 'progress'; $get('UserAvailability').innerHTML = 'Checking availability...'; }
This causes the div’s class to change to a spinning progress indicator animation when the partial postback begins, and changes the div’s text content to clarify what’s going on.
At the completion of the postback, the div’s content will be replaced by what’s generated in code-behind, so there’s no need to do anything on the client side for endRequest. The server-generated content will overwrite this temporary change and automatically replace the progress indicator with the username’s availability.
Preventing invalid submissions
I decided to declaratively start the button control off disabled, so that it defaults to blocking submissions until an available username is selected. Since I want to be able to manipulate its Enabled property in partial postbacks, I also enclosed it in an UpdatePanel:
<asp:UpdatePanel runat="server" ID="up2"> <ContentTemplate> <asp:Button runat="server" ID="Button1" Text="Sign me up!" Enabled="false" /> </ContentTemplate> </asp:UpdatePanel>
Next, I updated the username availability check to update the button’s enabled state appropriately:
if (Membership.GetUser(Username.Text) != null) { UserAvailability.InnerText = "Username taken, sorry."; UserAvailability.Attributes.Add("class", "taken"); Button1.Enabled = false; } else { UserAvailability.InnerText = "Username available!"; UserAvailability.Attributes.Add("class", "available"); Button1.Enabled = true; }
Now, at the same time the availability check’s result is displayed, the button will also be enabled or disabled depending on the availability of the username.
Because only the username TextBox, the availability div, and the Button are enclosed in UpdatePanels, only their contents will be replaced by partial postbacks. This is crucial so that other elements of the form aren’t reverted to their pre-postback state after the availability check. If your page has other UpdatePanels, make sure to set your UpdateModes and Triggers to properly isolate partial postback results.
Watch out for partial postbacks
Finally, I decided that I should also disable the submit button during availability checks. If a user chose an available username, but then changed it to something unavailable, they could sneak a submit in during the availability check’s callback. To prevent this I disabled the submit button, in the same InitializeRequest handler that displays the progress indicator:
$get('Button1').disabled = true;
This simply disables the button as soon as the partial postback begins. If the username ends up being available, the newly rendered button will be enabled, else it will remain disabled until the user chooses an available username.
In other words, no one with JavaScript enabled should be able to submit a registration for an invalid username now.
Bringing it all together
There are still several more improvements that could be made. For example, if the username is unavailable, we could suggest a few available variants of that username. However, I’m happy with these improvements as a solid first step toward improving the baseline user experience on my registration forms.
To clarify all of my rambling, convoluted source code snippets, here are the aspx, c#, css, and image files used throughout these two posts:
Similar posts
What do you think? Your comments are welcomed.
I appreciate all of your comments, questions, and other feedback, but please try to stay on topic. If you have a question unrelated to this post, I recommend posting on the ASP.NET forums. If you post there and then contact me with a link to the post, I'll try to take a look at it for you.
If you're replying to an existing comment, please use the threading feature. To do this, click the "Reply to this comment" link underneath the comment you're replying to.


Comments
Smart stuff, but don’t you think a (custom) validator would be the way to go here? Although, the current validators don’t always work correctly in an UpdatePanel.
I think you may be right about that. I’ll give some thought to rewriting that to work within the framework of a custom validator.
Thanks for the suggestion.
I am having trouble adapting the code to work within a templated create new user wizard. I keep getting the error Error ‘UserAvailability’ is not declared. A command like (CType(CreateUserWizard1.CreateUserStep.ContentTemplateContainer.FindControl(”cboCountry”), DropDownList)).SelectedValue is not working either. Any help would be appreciated.
I’m not quite sure exactly what you’re asking. Could you email me some code (or post it here, using <pre> tags)?
Hi,
This is a really interesting tutorial, but I’m wondering - how would I do this using Visual Basic, instead of C#?
Oops, nevermind - I feel a little blind. I didn’t catch that that’s a piece of Javascript.