If you like digging into tapestry I suggest you start
by removing beanutils dependancy and adding:
@Inject
private PropertyAccess propertyAccess;
into SelectObject.java
after that use propertyAccess instead of beanutils...
....
I'm currently building a version that doesn't need
SelectObject component, but uses normal select component.
The code is more complicated than it should be, so I suppose
I might post an enhancement ticket for the Select component.
...
if you like to start with working code ...
here's the changed version that works for me ...
-------------------------------------------------------------------------------------------------------------------------------------------
package test.tapestry;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.List;
import org.apache.tapestry.OptionGroupModel;
import org.apache.tapestry.OptionModel;
import org.apache.tapestry.internal.OptionModelImpl;
import org.apache.tapestry.ioc.services.PropertyAccess;
import org.apache.tapestry.ioc.services.PropertyAdapter;
import org.apache.tapestry.util.AbstractSelectModel;
/**
* @author jued
*
* @param <T>
*/
public class GenericSelectionModel<T> extends AbstractSelectModel {
private String labelField;
private List<T> list;
private final PropertyAccess adapter;
public GenericSelectionModel(List<T> list, String labelField,
PropertyAccess adapter) {
this.labelField = labelField;
this.list = list;
this.adapter = adapter;
}
public List<OptionGroupModel> getOptionGroups() {
return null;
}
public List<OptionModel> getOptions() {
List<OptionModel> optionModelList = new
ArrayList<OptionModel>();
for (T obj : list) {
if (labelField == null) {
optionModelList.add(new OptionModelImpl(obj
+ "", false, obj, new String[0]));
} else {
optionModelList.add(new OptionModelImpl(
adapter.get(obj,
labelField)+"", false, obj, new String[0]));
}
}
return optionModelList;
}
}
-------------------------------------------------------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------------------------------------------------------
package test.tapestry;
import java.lang.reflect.InvocationTargetException;
import java.util.List;
import org.apache.tapestry.ValueEncoder;
import org.apache.tapestry.ioc.services.PropertyAccess;
import org.apache.tapestry.ioc.services.PropertyAdapter;
public class GenericValueEncoder<T> implements ValueEncoder<T> {
private List<T> list;
private final PropertyAccess access;
private final String fieldName;
public GenericValueEncoder(List<T> list, String fieldName,
PropertyAccess propertyAccess) {
this.list = list;
this.fieldName = fieldName;
this.access = propertyAccess;
}
public String toClient(T obj) {
if (fieldName == null) {
return obj + "";
} else {
return access.get(obj,fieldName)+"";
}
}
public T toValue(String string) {
for (T obj : list) {
if (fieldName == null) {
if ((obj + "").equals(string)) {
return obj;
}
} else {
if (access.get(obj,
fieldName).equals(string)) {
return obj;
}
}
}
return null;
}
}
-------------------------------------------------------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------------------------------------------------------
package test.tapestry.components;
import java.util.List;
import java.util.Locale;
import org.apache.tapestry.Binding;
import org.apache.tapestry.ComponentResources;
import org.apache.tapestry.FieldValidator;
import org.apache.tapestry.MarkupWriter;
import org.apache.tapestry.OptionModel;
import org.apache.tapestry.SelectModel;
import org.apache.tapestry.SelectModelVisitor;
import org.apache.tapestry.ValidationException;
import org.apache.tapestry.ValidationTracker;
import org.apache.tapestry.ValueEncoder;
import org.apache.tapestry.annotations.BeforeRenderTemplate;
import org.apache.tapestry.annotations.Environmental;
import org.apache.tapestry.annotations.Inject;
import org.apache.tapestry.annotations.Parameter;
import org.apache.tapestry.corelib.base.AbstractField;
import org.apache.tapestry.internal.util.SelectModelRenderer;
import org.apache.tapestry.ioc.services.PropertyAccess;
import org.apache.tapestry.services.FieldValidatorDefaultSource;
import org.apache.tapestry.services.FormSupport;
import org.apache.tapestry.services.Request;
import org.apache.tapestry.services.ValueEncoderFactory;
import org.apache.tapestry.services.ValueEncoderSource;
import org.apache.tapestry.util.EnumSelectModel;
import test.tapestry.GenericSelectionModel;
import test.tapestry.GenericValueEncoder;
/**
* Select an item from a list of values, using an [X]HTML <select>
element on the client side.
* An validation decorations will go around the entire <select>
element.
* <p>
* A core part of this component is the [EMAIL PROTECTED] ValueEncoder} (the
encoder
parameter) that is used to
* convert between server-side values and client-side strings. In many
cases, a [EMAIL PROTECTED] ValueEncoder}
* can be generated automatically from the type of the value parameter. The
* [EMAIL PROTECTED] ValueEncoderSource} service provides an encoder in these
situations; it can be overriden
* by binding the encoder parameter, or extended by contributing a [EMAIL
PROTECTED]
ValueEncoderFactory} into
* the service's configuration.
*/
public final class SelectObject extends AbstractField
{
private class Renderer extends SelectModelRenderer
{
public Renderer(MarkupWriter writer)
{
super(writer, _encoder);
}
@Override
protected boolean isOptionSelected(OptionModel optionModel)
{
Object value = optionModel.getValue();
return value == _value || (value != null && value.equals
(_value));
}
}
@Inject
private FieldValidatorDefaultSource _fieldValidatorDefaultSource;
@Inject
private Locale _locale;
@Inject
private PropertyAccess propertyAccess;
@Parameter(required = true)
private List<Object> _list;
@Parameter
private String _labelField = null;
// Maybe this should default to property "<componentId>Model"?
/**
* The model used to identify the option groups and options to be
presented to the user. This
* can be generated automatically for Enum types.
*/
// @Parameter(required = true)
// private SelectModel _model;
private GenericSelectionModel<Object> _model;
/**
* Allows a specific implementation of [EMAIL PROTECTED] ValueEncoder} to be
supplied. This is used to
* create client-side string values for the different options.
*
* @see ValueEncoderSource
*/
// @Parameter
// private ValueEncoder _encoder;
private GenericValueEncoder<Object> _encoder;
@Inject
private Request _request;
@Inject
private ComponentResources _resources;
@Environmental
private ValidationTracker _tracker;
/** Performs input validation on the value supplied by the user in the
form submission. */
@Parameter(defaultPrefix = "validate")
@SuppressWarnings("unchecked")
private FieldValidator<Object> _validate = NOOP_VALIDATOR;
/** The value to read or update. */
@Parameter(required = true, principal = true)
private Object _value;
@Inject
private ValueEncoderSource _valueEncoderSource;
@Override
protected void processSubmission(FormSupport formSupport, String
elementName)
{
_encoder = new GenericValueEncoder<Object>(_list, _labelField,
propertyAccess);
String primaryKey = _request.getParameter(elementName);
Object selectedValue = _encoder.toValue(primaryKey);
try
{
_validate.validate(selectedValue);
_value = selectedValue;
}
catch (ValidationException ex)
{
_tracker.recordError(this, ex.getMessage());
return;
}
}
void afterRender(MarkupWriter writer)
{
writer.end();
}
void beginRender(MarkupWriter writer)
{
writer.element("select", "name", getElementName(), "id",
getClientId());
_encoder = new GenericValueEncoder<Object>(_list, _labelField,
propertyAccess);
_model = new GenericSelectionModel<Object>(_list, _labelField,
propertyAccess);
// Disabled, informals via mixins
}
@SuppressWarnings("unchecked")
ValueEncoder defaultEncoder()
{
return _valueEncoderSource.createEncoder("value", _resources);
}
@SuppressWarnings("unchecked")
SelectModel defaultModel()
{
Class valueType = _resources.getBoundType("value");
if (valueType == null) return null;
if (Enum.class.isAssignableFrom(valueType))
return new EnumSelectModel(valueType,
_resources.getContainerMessages());
return null;
}
/**
* Computes a default value for the "validate" parameter using
* [EMAIL PROTECTED] FieldValidatorDefaultSource}.
*/
FieldValidator defaultValidate()
{
Class type = _resources.getBoundType("value");
if (type == null) return null;
return _fieldValidatorDefaultSource.createDefaultValidator(
this,
_resources.getId(),
_resources.getContainerMessages(),
_locale,
type,
_resources.getAnnotationProvider("value"));
}
Binding defaultValue()
{
return createDefaultParameterBinding("value");
}
@BeforeRenderTemplate
void options(MarkupWriter writer)
{
SelectModelVisitor renderer = new Renderer(writer);
_model.visit(renderer);
}
// For testing.
void setModel(GenericSelectionModel model)
{
_model = model;
}
void setValue(Object value)
{
_value = value;
}
void setValueEncoder(GenericValueEncoder encoder)
{
_encoder = encoder;
}
}
-------------------------------------------------------------------------------------------------------------------------------------------
On 8/29/07, Marcelo lotif <[EMAIL PROTECTED]> wrote:
>
> Hi Davor,
> Can you send it to me?
>
> 2007/8/29, Davor Hrg <[EMAIL PROTECTED]>:
> >
> > thnx,
> > very nice example,
> >
> > I've liked it and modified it to use Tapestry builtin service:
> > PropertyAccess
> > instead of beanutils. If you like I can update the wiki..
> >
> > Davor Hrg
> >
> > On 8/28/07, Marcelo lotif <[EMAIL PROTECTED]> wrote:
> > >
> > > http://wiki.apache.org/tapestry/Tapestry5SelectObject
> > >
> > > --
> > > Atenciosamente,
> > > Marcelo Lotif
> > >
> >
>
>
>
> --
> Atenciosamente,
> Marcelo Lotif
>