Actually I would do this using a custom converter. Then you don't have to decorate it.
You can have a public class BooleanLabel { ... IConverter getConverter() { return new IConverter() { ... } } } In your converter decide how to display the value. I don't think there is anything wrong with your model, just that the custom components like this are IMHO easier to use. -Matej Logi Ragnarsson wrote: > Hello everyone, > > I'm relatively new to wicket, but I'm building a web application where > several > forms are backed by compound models with boolean and enum constituent models. > The straight-forward implementation of this would display true/false values, > and the names of the enum values in the code, which is generally not very > user friendly (peopel say "yes" and "no" and they don't generally put choices > in all upper case) and not internationalized, so Something Must Be Done. > > I'd like to show my solution, with input from Igor Vaynberg, for comment and > perhaps re-use. I've only got the boolean case implemented, but the enum case > is basically more of the same with more localization resources needing to be > loaded. > > The simplest case (and one not worth all this effort) is when displaying a > boolean value in a ListView: > new Label("active"); > which becomes: > new Label("active", new I18nBooleanModelDecorator(item.getModel())); > where the (attached) I18nBooleanModelDecorator has been applied to the model. > This will display "yes" or "no" for the boolean values unless those strings > have been replaced by setting the I18nBooleanModelDecorator.TRUE and > I18nBooleanModelDecorator.FALSE licalization strings to something else. > > Usually on a form you'd use a check-box for setting boolean values, such as > this: > new CheckBox("active"); > but for illustrative purposes suppose we have this text field instead: > new TextField("active"); > The following will work if the component's compound model has been set before > the form is populated with fields and will not be changed later: > new TextField("active", new I18nBooleanModelDecorator(getModel())); > but in reality getModel() is likely to return null or to return a model which > is later replaced with another in response to user or application events, so > the text field would now either have no underlying model or an out-dated one. > > For this I wrote a ComponentModelDelegator which takes a Component and > delegates all model operations to the current model of that component like > so: > IModel model = new ComponentModelDelegator(this) > new TextField("active", new I18nBooleanModelDecorator(model)); > > This works like a charm and you can write "nei" in my Icelandic locale to set > the value of the active property of my underlying model to false... before > you then change the code back to using the much more reasonable CheckBox > class. > > Is there anything terribly wrong with this? Would this be useful for other > wicket users, probably in combination with the similar decorator for > enumerations? > > PS The attached code is hereby published under the Apache license. > > > ------------------------------------------------------------------------ > > package is.gig.wicket.models; > > import org.apache.log4j.Logger; > import wicket.Component; > import wicket.model.IModel; > > /** Model which delegates to the model of a given component. */ > public class ComponentModelDelegator/*T*/ > implements IModel/*T*/ > { > private static final Logger LOG = > Logger.getLogger(ComponentModelDelegator.class); > > private Component component; > > /** Create a new delegator to the model of the givne component. */ > public ComponentModelDelegator(Component component) { > this.component = component; > } > > public Component getComponent() { > return component; > } > > public void setComponent(Component component) { > this.component = component; > } > > public IModel /*T*/ getNestedModel() { > return component.getModel(); > } > > public Object getObject(final Component component) { > IModel nested = getNestedModel(); > if (nested != null) { > return nested.getObject(component); > } else { > return null; > } > } > > public void setObject(final Component component, final Object object) { > IModel nested = getNestedModel(); > if (nested != null) { > nested.setObject(component, object); > } > } > > public void detach() { > IModel nested = getNestedModel(); > if (nested != null) nested.detach(); > } > } > > > ------------------------------------------------------------------------ > > package is.gig.wicket.models.i18n; > > import wicket.Component; > import wicket.model.IModel; > > /** > * Decorator for a boolean model which converts to and from localized and > human-friendly display values, falling back to > * "yes" and "no". > * > * <p/>The display values are taken from the localization strings with keys > <code>I18nBooleanModelDecorator.TRUE</code> > * and <code>I18nBooleanModelDecorator.FALSE</code> respectively. > */ > public class I18nBooleanModelDecorator > implements IModel/*Boolean*/ > { > private static final String I18N_KEY_PREFIX = "I18nBooleanModelDecorator"; > > private IModel /*Boolean*/ nestedModel; > private Boolean defaultValue = Boolean.FALSE; > > // CONSTRUCTION AND CONFIGURATION > > /** > * Create a new i18n decorator. > * > * @param nestedModel the model to decorate > * @param defaultValue the value to set in the nested model if the > display string being set is not recognized. > */ > public I18nBooleanModelDecorator(IModel /*Boolean*/ nestedModel, Boolean > defaultValue) { > this.defaultValue = defaultValue; > this.nestedModel = nestedModel; > } > > /** > * Create a new i18n decorator. > * > * @param nestedModel the model to decorate > */ > public I18nBooleanModelDecorator(IModel /*Boolean*/ nestedModel) { > this(nestedModel, Boolean.FALSE); > } > > public IModel /*Boolean*/ getNestedModel() { > return nestedModel; > } > > public void setNestedModel(IModel /*Boolean*/ nestedModel) { > this.nestedModel = nestedModel; > } > > /** et the value used in the nested model if the display string being set > is not recognized. */ > public Boolean getDefaultValue() { > return defaultValue; > } > > /** Set the value to set in the nested model if the display string being > set is not recognized. */ > public void setDefaultValue(Boolean defaultValue) { > this.defaultValue = defaultValue; > } > > // MODEL IMPLEMENTATION > > private String getHumanReadableValue(Component component, boolean b) { > if (b) { > return component.getString(I18N_KEY_PREFIX + ".TRUE", > nestedModel, "yes"); > } else { > return component.getString(I18N_KEY_PREFIX + ".FALSE", > nestedModel, "no"); > } > } > > public Object getObject(final Component component) { > Boolean b = (Boolean) nestedModel.getObject(component); > if (b == null) return null; > return getHumanReadableValue(component, b.booleanValue()); > } > > public void setObject(final Component component, final Object object) { > if (object == null) nestedModel.setObject(component, null); > String str = object.toString(); > if (getHumanReadableValue(component, true).equalsIgnoreCase(str)) { > nestedModel.setObject(component, Boolean.TRUE); > } else if (getHumanReadableValue(component, > false).equalsIgnoreCase(str)) { > nestedModel.setObject(component, Boolean.FALSE); > } else { > nestedModel.setObject(component, defaultValue); > } > } > > public void detach() { > nestedModel.detach(); > } > } > > > ------------------------------------------------------------------------ > > ------------------------------------------------------------------------- > Take Surveys. Earn Cash. Influence the Future of IT > Join SourceForge.net's Techsay panel and you'll get the chance to share your > opinions on IT & business topics through brief surveys - and earn cash > http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV > > > ------------------------------------------------------------------------ > > _______________________________________________ > Wicket-user mailing list > Wicket-user@lists.sourceforge.net > https://lists.sourceforge.net/lists/listinfo/wicket-user -- get professional wicket training and consultation http://www.wicket-support.com ------------------------------------------------------------------------- Take Surveys. Earn Cash. Influence the Future of IT Join SourceForge.net's Techsay panel and you'll get the chance to share your opinions on IT & business topics through brief surveys - and earn cash http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV _______________________________________________ Wicket-user mailing list Wicket-user@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/wicket-user