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.
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.form-component-id.
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
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 (CVS HEAD) the following features have been added:
Let's say you have the following component hierarchy:
APage ->BForm id="b" {panel} -->XPanel id="x" ---->RequiredTextField id="foo" -->YPanel id="y" ---->RequiredTextField id="foo" {panel}
XPanel knows nothing about its containing form or page, nevertheless XPanel's validation keys was required to be prefixed with the form's id
{panel} XPanel.properties: b.foo.RequiredValidator = Foo is required. {panel}
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:
{panel} APage.properties: b.foo.RequiredValidator = Foo is required in x ?? b.foo.RequiredValidator = Foo is required in y ?? {panel}
That has been changed. The search order has been changed like that:
{panel} APage.properties: b.x.foo.RequiredValidator = Foo is extremely required. XPanel.properties: foo.RequiredValidator = Foo is required. {panel}
YPanel's validation text could stay unaltered:
{panel} YPanel.properties: foo.RequiredValidator = Foo is required. {panel}