In this post, we will learn how to validate SmartGWT forms.

We will develop the following form.

User Form

Validation Rules

This form has the following validation rules

[table id=”6″ /]

The SmartGWT API provides a collection of validators in the package in the package com.smartgwt.client.widgets.form.validator.

Constructing the Form

Let’s start  out by building the form. This will include the form items for text fields, password fields and date fields. The form is constructed using the DynamicForm class. This is accomplished with the code fragment below:

[code]

DynamicForm form = new DynamicForm();
form.setErrorOrientation(FormErrorOrientation.RIGHT);

[/code]

In the code, we create an instance of the DynamicForm class. Then we set the orientation style for our error messages. We have the option of placing the error messages to the left or right of each form field. You can simple specify FormErrorOrientation.LEFT or .RIGHT. Alternatively, we can display the error above or below the field using FormErrorOrientation.TOP or .BOTTOM.

Now we can build each one of the fields and add them to the form. Here’s the code for creating the first name, last name and email. They are all text items. We construct the text items by calling the constructor and passing the form field name and title. The form field name is the traditional HTML element name and the title is the text displayed on the page.

[code]

// create form fields
TextItem firstNameTextItem = new TextItem("firstName", "First Name");
firstNameTextItem.setWrapTitle(false);
firstNameTextItem.setRequired(true);

TextItem lastNameTextItem = new TextItem("lastName", "Last Name");
lastNameTextItem.setWrapTitle(false);
lastNameTextItem.setRequired(true);

// email
TextItem emailTextItem = new TextItem("email", "Email");
emailTextItem.setWrapTitle(false);
emailTextItem.setRequired(true);
[/code]

As mentioned, we create each text item by passing in the element name and title. We also set title wrap to false, this will make sure the title text is displayed on one-line. For simple validation, we specify the field  is required. This code generates the following UI.

First Name, Last Name, Email

Password Fields

Now, we’ll construct the fields for the passwords using the PasswordItem. The PasswordItem component will allow the user to enter a password however, the text will not be visible. This works like a traditional password field. We’ll have two fields for the password for the user to confirm the password entered. We’ll add a validation rule for making sure they match later. For now, we’re just focusing on building out the form fields.

[code]

// original user password
PasswordItem userPasswordItem = new PasswordItem("userPassword", "Password");
userPasswordItem.setWrapTitle(false);
userPasswordItem.setRequired(true);

// confirm password
PasswordItem confirmPasswordItem = new PasswordItem("confirmPassword", "Confirm Password");
confirmPasswordItem.setWrapTitle(false);
confirmPasswordItem.setRequired(true);

[/code]

This code generates the following UI:

Password

Date of Birth Field

The date of birth field is constructed using a DateItem. The DateItem component allows the user to select month, day, year using drop-down lists or a date picker. We can create the component using the following code:

[code]

// date of birth
DateItem dateOfBirthDateItem = new DateItem("dob", "Date of Birth");
dateOfBirthDateItem.setWrapTitle(false);
dateOfBirthDateItem.setRequired(true);
Date today = new java.util.Date();
dateOfBirthDateItem.setEndDate(today);

[/code]

This code generates the following UI:

Date of Birth

The final piece in the form construction is to associate the form fields with form object. This is accomplished with the following code:

[code]
// add form fields to form
form.setFields(firstNameTextItem, lastNameTextItem,
emailTextItem, userPasswordItem,
confirmPasswordItem, dateOfBirthDateItem);
[/code]

Form Validation with ClickHandler

We will add a button to the UI for the user to click. The button is labeled “Register”. When the user clicks the “Register” button then the form is validated.  Here’s the code for creating the button and adding the click handler.

[code]
Button registerButton = new Button("Register");
registerButton.addClickHandler(new RegisterButtonClickHandler());

class RegisterButtonClickHandler implements ClickHandler {

@Override
public void onClick(ClickEvent event) {
// perform form validation
boolean valid = form.validate();

// if validation passes then show user an alert message box
if (valid) {
SC.say("Form passed validation");
}
}

}
[/code]

This code creates a button and adds a click handler. The click handler performs validation on the form by calling form.validate(). This returns true if the form passed validation. For our simple test program, we will display a message to the user if validation passed. If validation failed, then the form will have error indicators.

The diagram below shows a successful form validation.

Successful Validation

The diagram below shows a form that has failed validation. When you mouse over the error icons, then it displays the actual error message. If you’d like you can customize the form to also show the error messages with form.setShowErrorText(true).

Form Failed Validation

Regular Expressions

SmartGWT supports regular expressions for validation via the RegExpValidator class. The RegExpValidator class is defined in the package com.smartgwt.client.widgets.form.validator. We’ll use this validator for the email address field. We will provide a regular expression that make sure the email address follow the basic format of foo@bar.com. The code below sets up the validator for the email address field:

[code]
final String EMAIL_VALIDATION_REGEX = "^[_A-Za-z0-9-+]+(\\.[_A-Za-z0-9-+]+)*@[A-Za-z0-9-]+(\\.[A-Za-z0-9]+)*(\\.[A-Za-z]{2,})$";

// email validator using regular expressions
RegExpValidator regExpValidator = new RegExpValidator();
regExpValidator.setExpression(EMAIL_VALIDATION_REGEX);
regExpValidator.setErrorMessage("User ID must be a valid email address.");
emailTextItem.setValidators(regExpValidator);
emailTextItem.setValidateOnExit(true);
[/code]

Matching Fields

For the password fields, we have the user enter the password twice to make sure it is correct. We can make use of another SmartGWT validator for making sure fields two fields match, MatchesFieldValidator. The MatchesFieldValidator class is defined in the package com.smartgwt.client.widgets.form.validator. The code below shows how to setup the validation:

[code]
// original user password
PasswordItem userPasswordItem = new PasswordItem("userPassword", "Password");
userPasswordItem.setWrapTitle(false);
userPasswordItem.setRequired(true);

// confirm password
PasswordItem confirmPasswordItem = new PasswordItem("confirmPassword", "Confirm Password");
confirmPasswordItem.setWrapTitle(false);
confirmPasswordItem.setRequired(true);

// password validator
MatchesFieldValidator matchValidator = new MatchesFieldValidator();
matchValidator.setOtherField("userPassword"); // refs back to the "name" of original user password field
matchValidator.setErrorMessage("Passwords do not match.");
confirmPasswordItem.setValidators(matchValidator);
confirmPasswordItem.setValidateOnExit(true);
[/code]

Date Range

Our last validation rule on the date of birth field. When we register a new user, they can not select a future date of birth. So effectively, they can only choose today or a prior date. SmartGWT provides a DateRangeValidator class for handling this. The DateRangeValidator class is defined in the package com.smartgwt.client.widgets.form.validator. When you use this validator, you set up the maximum date allowed. In our case, the max day is the current date. The code below sets up the date range validation:

[code]
// date of birth
DateItem dateOfBirthDateItem = new DateItem("dob", "Date of Birth");
dateOfBirthDateItem.setWrapTitle(false);
dateOfBirthDateItem.setRequired(true);
Date today = new java.util.Date();
dateOfBirthDateItem.setEndDate(today);

// custom date range validator for date of birth
DateRangeValidator dateRangeValidator = new DateRangeValidator();
dateRangeValidator.setMax(today);
dateRangeValidator.setErrorMessage("Date must be today’s date or prior.");
dateOfBirthDateItem.setValidators(dateRangeValidator);
dateOfBirthDateItem.setValidateOnExit(false);
dateOfBirthDateItem.setValidateOnChange(true);
[/code]

Final Code

We looked at the code in bits and pieces. Now, let’s pull it all together. The complete code for the  form validation is shown below:

[code]
package com.luv2code.form.client;

import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.user.client.ui.RootPanel;
import com.smartgwt.client.types.FormErrorOrientation;
import com.smartgwt.client.util.SC;
import com.smartgwt.client.widgets.Button;
import com.smartgwt.client.widgets.events.ClickEvent;
import com.smartgwt.client.widgets.events.ClickHandler;
import com.smartgwt.client.widgets.form.DynamicForm;
import com.smartgwt.client.widgets.form.fields.DateItem;
import com.smartgwt.client.widgets.form.fields.PasswordItem;
import com.smartgwt.client.widgets.form.fields.TextItem;
import com.smartgwt.client.widgets.form.validator.DateRangeValidator;
import com.smartgwt.client.widgets.form.validator.MatchesFieldValidator;
import com.smartgwt.client.widgets.form.validator.RegExpValidator;
import com.smartgwt.client.widgets.layout.VLayout;
import java.util.Date;

/**
* Entry point classes define
* <code>onModuleLoad()</code>.
*
* @author Chad Darby
*/
public class FormValidationApp implements EntryPoint {

private DynamicForm form;

private static final String EMAIL_VALIDATION_REGEX = "^[_A-Za-z0-9-+]+(\\.[_A-Za-z0-9-+]+)*@[A-Za-z0-9-]+(\\.[A-Za-z0-9]+)*(\\.[A-Za-z]{2,})$";

/**
* This is the entry point method.
*/
public void onModuleLoad() {

buildGui();
}

private void buildGui() {

// build the form
form = buildForm();

// create button and add handler
Button registerButton = new Button("Register");
registerButton.addClickHandler(new RegisterButtonClickHandler());

// layout components
VLayout layout = new VLayout();
layout.addMember(form);
layout.addMember(registerButton);

// add layout to main HTML host page
RootPanel rootPanel = RootPanel.get("app");
rootPanel.add(layout);
}

private DynamicForm buildForm() {
DynamicForm form = new DynamicForm();
form.setWidth(800);
form.setStyleName("formLayout");
form.setErrorOrientation(FormErrorOrientation.RIGHT);

// create form fields
TextItem firstNameTextItem = new TextItem("firstName", "First Name");
firstNameTextItem.setWrapTitle(false);
firstNameTextItem.setRequired(true);

TextItem lastNameTextItem = new TextItem("lastName", "Last Name");
lastNameTextItem.setWrapTitle(false);
lastNameTextItem.setRequired(true);

// email
TextItem emailTextItem = new TextItem("email", "Email");
emailTextItem.setWrapTitle(false);
emailTextItem.setRequired(true);

// email validator using regular expressions
RegExpValidator regExpValidator = new RegExpValidator();
regExpValidator.setExpression(EMAIL_VALIDATION_REGEX);
regExpValidator.setErrorMessage("User ID must be a valid email address.");
emailTextItem.setValidators(regExpValidator);
emailTextItem.setValidateOnExit(true);

// original user password
PasswordItem userPasswordItem = new PasswordItem("userPassword", "Password");
userPasswordItem.setWrapTitle(false);
userPasswordItem.setRequired(true);

// confirm password
PasswordItem confirmPasswordItem = new PasswordItem("confirmPassword", "Confirm Password");
confirmPasswordItem.setWrapTitle(false);
confirmPasswordItem.setRequired(true);

// password validator
MatchesFieldValidator matchValidator = new MatchesFieldValidator();
matchValidator.setOtherField("userPassword"); // refs back to the name" of original user password field
matchValidator.setErrorMessage("Passwords do not match.");
confirmPasswordItem.setValidators(matchValidator);
confirmPasswordItem.setValidateOnExit(true);

// date of birth
DateItem dateOfBirthDateItem = new DateItem("dob", "Date of Birth");
dateOfBirthDateItem.setWrapTitle(false);
dateOfBirthDateItem.setRequired(true);
Date today = new java.util.Date();
dateOfBirthDateItem.setEndDate(today);

// custom date range validator for date of birth
DateRangeValidator dateRangeValidator = new DateRangeValidator();
dateRangeValidator.setMax(today);
dateRangeValidator.setErrorMessage("Date must be today’s date or prior.");
dateOfBirthDateItem.setValidators(dateRangeValidator);
dateOfBirthDateItem.setValidateOnExit(false);
dateOfBirthDateItem.setValidateOnChange(true);

// add form fields to form
form.setFields(firstNameTextItem, lastNameTextItem, emailTextItem, userPasswordItem, confirmPasswordItem, dateOfBirthDateItem);

return form;
}

class RegisterButtonClickHandler implements ClickHandler {

@Override
public void onClick(ClickEvent event) {
boolean valid = form.validate();

if (valid) {
SC.say("Form passed validation");
}
}

}
}
[/code]

Wrap Up

That’s pretty much it. We developed a SmartGWT form and added validation rules for the various fields. The rules included required fields, regular expressions, matching fields and data range.

The complete source is available for download.

Enjoy!