Some knowledge of wicket property-resource loading is required to understand this article.

As of wicket-1.1 post rc2 there is an easier way to provide validation messages for form components.

In wicket-1.1-rc2 and before the validation messages were provided through resource keys defined as form-id.form-component-id.validator-class-name. This approach entailed a lot of repetitive resource messages. For example, the following form:

Form form=new Form("myform");
form.add(new RequiredTextField("firstname").add(LengthValidator.max(15));
form.add(new RequiredTextField("lastname").add(LengthValidator.max(15));

would have required the following resource keys:

[page-class-name].properties
----------------------------
myform.firstname.RequiredValidator=Field 'customer first name' is required
myform.firstname.LengthValidator=Field 'customer first name' must be between ${min} and ${max} characters
myform.lastname.RequiredValidator=Field 'customer last name' is required
myform.lastname.LengthValidator=Field 'customer last name' must be between ${min} and ${max} characters

Wicket-1.1 post rc2 provides a much simplified approach by introducing the ${label} variable in the validation context which represents the user-centric name of the form component and allows factoring out validator-specific messages into one place.
_IMPORTANT: This only works correctly, when getResourceSettings().getUseDefaultOnMissingResource is true !

The ${label} variable can be provided by one of two ways:
It can either be set directly on the form component instance by calling setLabel(IModel model) method, or by including a resource key of the form form-id.relative_path_to_form-component-id.

IMPORTANT: If your form component is a child of another component (e.g. Border) and isn't being directly added to the form component itself, then you need to use the relative path to the component.  

The example above can now be rewritten as following:

Specify the general validator messages:

[webapplication-subclass-name].properties
RequiredValidator=Field '${label}' is required
LengthValidator=Field '${label}' must be between ${min} and ${max} characters

Specify the user-centric form component labels:

[page-class-name].properties
myform.firstname=customer first name
myform.lastname=customer last name

IMPORTANT:

or specify labels directly in java code:

FormComponent firstname=new RequiredTextField("firstname").add(LengthValidator.max(15));
firstname.setLabel(new Model("customer first name"));
form.add(firstname);
FormComponent lastname=new RequiredTextField("lastname").add(LengthValidator.max(15));
lastname.setLabel(new Model("customer last name"));
form.add(lastname);

This approach makes it much simpler to maintain error messages in forms.

Since 1.2 the following features have been added:
Let's say you have the following component hierarchy:

APage
->BForm id="b"
 -->XPanel id="x"
    ---->RequiredTextField id="foo"
 -->YPanel id="y"
    ---->RequiredTextField id="foo"

XPanel knows nothing about its containing form or page, nevertheless XPanel's validation keys was required to be prefixed with the form's id

XPanel.properties:
   b.foo.RequiredValidator = Foo is required.

That introduced an unwanted dependency of XPanel on its parental form (i.e. id="b").

Furthermore there was no way to override the foo messages separately for XPanel and YPanel:

APage.properties:
   b.foo.RequiredValidator = Foo is required in x ??
   b.foo.RequiredValidator = Foo is required in y ??

That has been changed. The search order has been changed like that:

APage.properties:
   b.x.foo.RequiredValidator = Foo is extremely required.
 XPanel.properties:
   foo.RequiredValidator = Foo is required.

YPanel's validation text could stay unaltered:

YPanel.properties:
   foo.RequiredValidator = Foo is required.

Changes in Wicket 1.3

Wether a field is required is now determined by testing the isRequired() method of FormComponent, therefore 'RequiredValidator' in the above examples has to be replaced by 'Required'.

  • No labels