Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: fixed language param of code macro

...

Finally, Tapestry is able to not only present the errors back to the user, but to decorate the fields and the labels for the fields, marking them as containing errors (primarily, using CSS effects).

Contents

Table of Contents

The Form Component

The core of Tapestry's form support is the Form component. The Form component encloses (wraps around) all the other field components such as TextField, TextArea, Checkbox, etc.

...

For example, a Login page, which collects a user name and a password, might look like:

Code Block
java
languagejava

public class Login
{
    @Persist
    @Property
    private String userName;

    @Property
    private String password;

    @Inject
    private UserAuthenticator authenticator;

    @InjectComponent(id = "password")
    private PasswordField passwordField;

    @Component
    private Form form;

    /**
     * Do the cross-field validation
     */
    void onValidateFromLoginForm()
    {
        if (!authenticator.isValid(userName, password))
        {
            // record an error, and thereby prevent Tapestry from emitting a "success" event
            form.recordError(passwordField, "Invalid user name or password.");
        }
    }

    /**
     * Validation passed, so we'll go to the "PostLogin" page
     */
    Object onSuccess()
    {
        return PostLogin.class;
    }
}

...

The template for the Login page contains a minimal amount of Tapestry instrumentation:

Code Block
html
languagehtmlxml

<html xmlns:t="http://tapestry.apache.org/schema/tapestry_5_1_0.xsd">
    <head>
        <title>Login</title>
    </head>
    <body>
        <h1>Please Login</h1>

        <form t:type="form" t:id="loginForm">

            <t:errors/>

            <t:label for="userName"/>:
            <input t:type="TextField" t:id="userName" t:validate="required,minlength=3" size="30"/>
            <br/>
            <t:label for="password"/>:
            <input t:type="PasswordField" t:id="password" t:validate="required,minlength=3" size="30"/>
            <br/>
            <input type="submit" value="Login"/>
        </form>
    </body>
</html>

...

For example, your template may have the following:

Code Block
html
languagehtmlxml

  <t:textfield t:id="ssn" validate="required,regexp"/>

And your message catalog can contain:

Code Block
java
languagejava

ssn-regexp=\d{3}-\d{2}-\d{4}
ssn-regexp-message=Social security numbers are in the format 12-34-5678.

...

Validation Macros

Since
since5.2
 

Lists of validators can be combined into validation macros. This mechanism is convenient for ensuring consistent validation rules across an application. To create a validation macro, just contribute to the ValidatorMacro Service in your module class (normally AppModule.java), by adding a new entry to the configuration object, as shown below. The first parameter is the name of your macro, the second is a comma-separated list of validators:

Code Block
java
languagejava

@Contribute(ValidatorMacro.class)
public static void combinePasswordValidators(MappedConfiguration<String, String> configuration) {
      configuration.add("password","required,minlength=5,maxlength=15,");
}

Then, you can use this new macro in component templates and classes:

Code Block
html
languagehtmlxml

<input t:type="textField" t:id="password" t:validate="password" />
Code Block
java
languagejava

@Validate("password")
private String password;

...

For example, you may have a quantity field that you wish to display as blank, rather than zero, initially:

Code Block
java
languagejava

  <t:textfield t:id="quantity" size="10"/>

  . . .

  private int quantity;

  String onToClientFromQuantity()
  {
    if (quantity == 0) return "";

    return null;
  }

...

That's where the "parseclient" event comes in:

Code Block
java
languagejava

  Object onParseClientFromQuantity(String input)
  {
    if ("".equals(input)) return 0;

    return null;
  }

...

Now, what if you want to perform your own custom validation? That's another event: "validate":

Code Block
java
languagejava

  void onValidateFromCount(Integer value) throws ValidationException
  {
    if (value.equals(13)) throw new ValidationException("Thirteen is an unlucky number.");
  }

...