Notice: There is a newer version of this post available

As was illustrated with our Dive Into Dijit post, the Dijit library provides an extremely powerful, flexible set of Dojo-based widgets with which you may easily enhance the look and functionality of your web application.  These widgets include drop down / popup menus, dialogs, page layouts, trees, progress bars, and form elements.  When looking at these elements, it’s easy to see that Dijit enhances their presentation but this post will focus on enhancing functionality;  specifically, enhancing a basic form with usability improvements and validation.

Quick Dijit Implementation Review

The first step in introducing Dijit to any page is including Dojo:

<script src="http://ajax.googleapis.com/ajax/libs/dojo/1.5/dojo/dojo.xd.js.uncompressed.js" djConfig="isDebug:true,parseOnLoad:true"></script>

The next step is requesting the Dijit theme stylesheet:

<style type="text/css">
@import "http://ajax.googleapis.com/ajax/libs/dojo/1.5/dojo/resources/dojo.css";
@import dojox/"http://ajax.googleapis.com/ajax/libs/dojo/1.5/dijit/themes/claro/claro.css";
</style>

The last step is adding the theme name as a class for the BODY element:

<body class="claro">

Enhancing Basic Form Elements

Note: this tutorial will use the declarative method of widget creation. You may create any Dijit widget programatically using dojo.behavior as described in Dive Into Dijit.

The first step in enhancing our static form is enhancing the form elements themselves.  Dijit provides a corresponding widget (sometimes two or three) for the different types of form elements. Using the declarative method of Dijit widget creation and the dojoType attribute, we’ll quickly widget-ize every piece of our static form:

<form action="process.php" method="get">
<!-- text inputs:  dijit.form.TextBox -->
<strong>First Name: </strong>
<input type="text" name="firstName" placeholder="Your Name" id="firstName" dojoType="dijit.form.TextBox" />

<strong>Website:  </strong>
<input type="text" name="website" placeholder="Your Website" id="website" dojoType="dijit.form.TextBox" />

<!-- radio buttons:  dijit.form.FilteringSelect -->
<strong>Favorite Color: </strong>
<select name="color" id="color" dojoType="dijit.form.FilteringSelect">
	<option value="">Select a Color</option>
	<option value="Red">Red</option>
	<option value="Green">Green</option>
	<option value="Blue">Blue</option>
</select>

<!-- radio buttons:  dijit.form.CheckBox -->
<strong>Send Emails? </strong>
<input type="checkbox" id="checkbox" checked="checked" dojoType="dijit.form.CheckBox" />

<!-- radio buttons:  dijit.form.RadioButton -->
<strong>Email Format: </strong>
<input type="radio" id="radio1" name="format" checked="checked" dojoType="dijit.form.RadioButton" /> 
<label for="radio1">HTML</label>
   
<input type="radio" id="radio2" name="format" dojoType="dijit.form.RadioButton" />
<label for="radio2">Text</label>

<!-- submit button:  dijit.form.Button -->
<input type="submit" value="Submit Form" label="Submit Form" id="submitButton" dojoType="dijit.form.Button" />
</form>

Boom: our static, boring form elements have been themed and extended with extra functionality. A few notes with regard to widgets we created above:

  • The FilteringSelect widget duplicates the functionality of a native SELECT element by:
    • Setting an initial value based on one of its options having a selected attribute.
    • Enforcing a fixed set of possible results based upon the values and text of each OPTION element.
    • Providing keyboard accessibility
  • The FilteringSelect widget adds the following functionality to the basic SELECT element:

    • You may type values into the FilteringSelect; autocomplete is employed.
    • If an invalid value is provided, an error message is provided to the user.
    • You get more control over the display when the widget is disabled.
  • Dojo 1.5 introduces strategies for employing placeholder text within INPUT elements to save you time in adding focus/blur events to accomplish the same functionality.

Now that the basic form has been widget-ized and themed, we can add basic validation functionality.

Form Validation with Dojo

As with just about every client-side problem, Dojo’s got a great solution for form validation. Luckily there are only a few key components required for basic form validation.

dijit.form.ValidationTextBox

A precursor to the overall validation of a form is deciding which elements are required. Say we want to require the first field; the dojoType of that will will change from dijit.form.TextBox to dijit.form.ValidationTextBox:

<input dojoType="dijit.form.ValidationTextBox" required="true" placeholder="Your Name" missingMessage="Ooops!  You forgot your first name!" name="firstName" id="firstName" type="text" />

Since required="true" has been added to the widget, an error icon and tooltip (with error message) will display if the user fails to place text into the box. A custom error message can be placed within the missingMessage attribute, otherwise a generic message will display.

What if the field requires special validation of the pattern of input? That’s where the regExp attribute comes in:

<input dojoType="dijit.form.ValidationTextBox" required="true" regExp="(https?|ftp)://[A-Za-z0-9-_]+\.[A-Za-z0-9-_%&\?\/\.=]+" name="website" placeholder="Your Website" id="website" type="text" />

Not only is the website field now required but the value of the field must pass the regular expression test provided by the regExp attribute.

Validation Utilities with dojox.validate

The dojox.validate library includes numerous utility functions and regular expressions for validating form element values. These utility functions can validate email addresses, URLs, phone numbers, zip codes, and much more. An example usage of dojox.validate with a ValidationTextBox would look like:

<script type="text/javascript">
dojo.require("dojox.validate");
dojo.require("dojox.validate.web");
</script>

<strong>Email:</strong>
<input type="text" required="true" name="email" id="email" dojoType="dijit.form.ValidationTextBox" validator="dojox.validate.isEmailAddress" />

The validator attribute is a link to the validation function for emails. dojox.validate is especially helpful if you don’t feel comfortable with regular expressions. There are also locale-specific packages within dojox.validate. The API docs provide a complete listing of dojox.validate helpers.

dijit.form.Form with the onSubmit Event

Now that our required fields are in place, we’ll enhance the wrapping form element with a dijit.form.Form dojoType:

<form dojoType="dijit.form.Form" action="process.php" method="get">
<script type="dojo/method" event="onSubmit">
<!--
if (this.validate()) {
	alert('Form is valid, submitting!');
} else {
	alert('Form contains invalid.  Please complete all required fields.');
	return false;
}
return true;
-->
</script>
<!-- form fields here -->
</form>

Accompanying the dijit.form.Form is a special script element. Within this Dojo-specific script is a this.validate() test, acting on the dijit.form.Form instance, which validates the entire form based on require="true" inputs. You could also add your own custom validation within the code block as well.

The dijit.form Collection

I’ve only touched the most-used Dijit widgets within my example above. There are several more outstanding form widgets within Dijit; let’s take a look at a few other helpful widgets!

DateTextBox

Asking the user to format a date properly can be a nightmare, especially if other form fields within the page rely on the contents of a given date field. Dijit provides a dijit.form.DateTextBox class which displays a user-friendly calendar widget for users to select a date on.

<!-- when the user focuses on this element, the calendar appears -->
<input dojoType="dijit.form.DateTextBox" required="true" invalidMessage="Please provide a valid date." type="text" name="date" id="date" />

CurrencyTextBox

The dijit.form.CurrencyTextBox class helps the user to properly format and validate currency per a given locale.

<!-- {fractional:true} means you must provide cents -->
<input dojoType="dijit.form.CurrencyTextBox" required="true" constraints="{fractional:true}" currency="USD" invalidMessage="Please provide both dollars and cents." type="text" name="weekly_wages" id="weekly_wages" value="2000" />

Textarea

The dojox.form.Textarea class enhances a given TEXTAREA element so that the element grows in height as the user types.

<textarea dojoType="dijit.form.Textarea" name="comments"></textarea>

Enhancing Basic Dijit Widgets with DojoX Alternatives

As nice as many of the Dijit widgets are, DojoX hosts numerous enhanced widgets that solve problems that many basic widgets cannot. The following are a few notable DojoX form widgets.

BusyButton

dijit.form.Button works great but what if I want to disable the button (to avoid double submissions) and provide a feedback message (i.e. “Sending form….”) when clicked? We could use dojox.form.BusyButton to do just that:

<!-- assuming dojox.form.BusyButton has been required... -->
<button dojoType="dojox.form.BusyButton" busyLabel="Sending Data...">
    Send Data
</button>

CheckedMultiSelect

What if our SELECT element allows for multiple selections? That’s the perfect opportunity to use the dojox.form.CheckedMultiSelect widget:

<!-- assuming dojox.form.CheckedMultiSelect has been required... -->
<select multiple="true" name="rockers" dojoType="dojox.form.CheckedMultiSelect">
	<option value="Oasis">Oasis</option>
	<option value="Rod Stewart" selected="selected">Rod Stewart</option>
	<option value="Coldplay" selected="selected">Coldplay</option>
	<option value="Kings of Leon">Kings of Leon</option>
</select>

PasswordValidator

What if our website features a form that allows updating/changing of passwords? The dojox.form.PasswordValidator provides all the functionality you need to quickly implement that system:

<!-- assuming dojox.form.PasswordValidator has been required... -->
<!-- pwValidate is the name of your function that verifies the current password is correct -->	
<div dojoType="dojox.form.PasswordValidator" name="pwValidate">
	<!-- pwType=old is where the user must place their current password -->
	<input type="password" pwType="old" />
	<!-- pwType=new is where the proposed new password must be placed -->
	<input type="password" pwType="new" />
	<!-- pwType=new is where the user verifies their new pass -->
	<input type="password" pwType="verify" />
</div>

Reminder: JavaScript validation is not a substitute for server-side validation; JavaScript simply enhances the user experience by providing instant feedback to the user.

FileUploader

File uploading without enhancement is probably the worst form control available. The dojox.form.FileUploader provides a great solution for making the process more streamlined:

<!-- assuming dojox.form.FileUploader has been required... -->
<div class="uploadBtn" dojoType="dojox.form.FileUploader" hoverClass="uploadHover" pressClas="uploadPress" activeClass="uploadBtn" disabledClass="uploadDisable" uploadUrl="/upload-files.php">Select Files</div>

The dojox.form Collection

The dojox.form namespace hosts a huge host of widget enhancements, including:

  • BusyButton – button with special disable/busy label states
  • CheckedMultiSelect – turns your SELECT element with the “multiple” attribute into a series of checkboxes for usability
  • DropDownStack – disable/enable form elements based upon a selection
  • RangeSlider – allows values to be chosen via a sliding scale
  • Rating – easily creates UI for ratings (star ratings)
  • …and much more!™

Great Dijit & Dojox Resources

The Dijit library is much more than just gloss on your elements — it’s a hugely functional set of classes to make life easier for both you, the developer, and your users.