This chapter focuses on the utility
methods that were referenced in the previous chapters. Also we show
a few more ways about how you can manipulate the UI components from
within your model classes.
9.1) Disabling Components
There are a few ways to disable
components:
- Remove the setter method from the model or make it
@Hidden
or non public.
- Leave the value of a nested model
null, this
will keep the nested controls disabled, because they cannot be
accessed anyway.
- Add the disabled attribute in the HTML file to the
appropriate tag.
- Add a
@Disabled annotaton to the field,
getter/setter or action method.
These approaches always keep a
component more or less statically disabled. To make this a dynamic
decision from within the model, you can make use of a disabler
utility method:
public String disable<NameOfProperty/NameOfAction>() { ... }
The returned string will be displayed as a tooltip on the disabled
component and should state the reason why this is the case.
Returning
null
keeps the component enabled. Here you can also change the return
type into a boolean, to make it a binary decision without giving a
reason:
public boolean disable<NameOfProperty/NameOfAction>() { ... }
9.2) Hiding Components
Analogous to disabling components,
there are a few ways to hide a component:
- Remove the getter and setter method from the model or make
it non public.
- Add the css style
display:none to the
component in the HTML or comment out the tag (so that the Wicket
ID is still present to let the HTML generator skip generating it
again).
- Add a
@Hidden annotaton to the field,
getter/setter or action method.
Again you might have the
requirement to dynamically hide a component, for this there is also
a hider utility method you can implement:
public String hide<NameOfProperty/NameOfAction>() { ... }
This time the returned string is
not used anywhere and can only give a hint during code debugging.
It is more common to use the boolean alternative:
public boolean hide<NameOfProperty/NameOfAction>() { ... }
Remember that you can make more markup follow a visibility state of
a Wicket component by adding the wicket:enclosure
tag in your HTML file. So that the label also disappears
dynamically when you hide your input.
9.3) Adding Tooltips
Despite adding
title
attributes to your HTML tags, you can also add the
@Tooltip
to your getters/setters or action methods. Again if you need a more
dynamic way to do this, there is an utility method available for
this:
public String get<NameOfProperty>Tooltip() { ... }
For an action method, you have to
omit the getter prefix:
public String <NameOfAction>Tooltip() { ... }
9.4) Changing Titles
Every model class, property and
action element has a default title representation of the name being
printed in a readable manner. To provide your own titles, you have
a few options.
- Add the
@Title annotation to replace the
automatically generated string representation. Though this will
mostly only change the property value in the Wicket
internationalization properties file. But it is useful when
generated UI models from a UML diagram.
- Change the Wicket components to use different label models
by defining a custom binding via a BindingInterceptor in your
pages.
- Change the internationalization property file value for
the corresponding Wicket ID like you are used to from Wicket. The
properties file has a higher priority than the title annotation.
Though to have this more dynamic
and to maybe even reuse model state inside of titles, you can again
implement some utility methods:
public String title() { ... } // for dynamic model class titles and page titles
public String get<NameOfProperty>Title() { ... } // for property titles visible in labels
public String <NameOfAction>Title() { ... } // for action titles visible as button texts
9.5) Column & Element Order
Normally everything is generated in alphabetical order. The element
order can be manually specified using the
@ColumnOrder
annotation on your classes. Alternatively you can implement a
dynamic utility element for this:
public String[] columnOrder() { ... } // can also return Iterable, Collection, etc
public String[] get<NameOfProperty>ColumnOrder() { ... } // also available as a suffix utility method
This is normally used to define the
column order of table models, but you can also use it to define the
order of tabbed panes and the order in which the HTML generator
generates the tags. In tables and tabbed panes, any element that is
missing from the order will automatically be hidden (as an
alternative to the other hiding approaches).
9.6) Removing Rows From Tables
Removing a row from a table is
possible via action columns. Though the problem is, a row needs to
know the list where it is contained for it to be able to remove
itself. This binds the row class to the model class where it is
displayed as a table, which is sometimes unhandy. To give the
outside model complete control over removing rows, there is a
utility method you can add next to the table property:
public void removeFrom<NameOfProperty>(<TypeOfProperty> row) { ... }
This makes a special column appear for this action inside the
table. You can reference this action column from within a
@ColumnOrder
via the method prefix
"removeFrom"
or the constant
TableRemoveFromButtonColumnBeanPathElement.COLUMN_ID
. Again the Ajax Data
Table page provides an example for this. Click
here for the source code.
9.7) Date & Number Formatting
You can use the
@Format
annotation on your property fields and getters/setters to change
the presentation of your dates and numbers in the components. The
format string follows the standard Java DecimalFormat
and SimpleDateFormat
conventions.
9.8) Internationalization
Internationalization is mostly what you are used
to from Wicket. The addition to consider when working with model
classes is that every string returned from a title, tooltip,
disabled reason and others can be a property that you want to
reference from the Wicket internationalization properties file. See
the Form Input page again
for an example of this. Click
here for the source code.
9.9) Try It
The car below shows examples of a
dynamic disable utility method to prevent duplicate actions on the
motor state. Also there have been added a few tooltips and a
special date format.
public class Car implements Serializable {
// uninteresting fields, getters and setters omitted
@Pattern(regexp = "[A-Z]{1,3}-[A-Z]{1,2} [1-9][0-9]{0,3}")
@Tooltip("Pattern Example: MO-ON 1234")
public String getLicenseNumber() { return licenseNumber; }
public String getBrand() { return brand; }
public String getBrandTooltip() {
String message = "Popular Brands: ";
for (final CarBrand brand : CarBrand.values()) {
message += brand + ", ";
}
message = Strings.removeEnd(message, ", ");
return message;
}
@Format("yyyy -_- MM /_/ dd")
public Date getRegistrationDate() { return registrationDate; }
public void turnOn() {
this.state = MotorState.on;
}
public String disableTurnOn() {
if (state == MotorState.on) {
return "Car is already running";
} else {
return null;
}
}
public void turnOff() {
this.state = MotorState.off;
}
public String disableTurnOff() {
if (state == MotorState.off) {
return "Car is already stopped";
} else {
return null;
}
}
}
Hover over the components in the
panel below to see the tooltips.