问题
When I enter edit mode of my Table, I want the data validation exclamation mark icon (!) to be shown as soon as the user goes out of bounds of any of the validation constraints.
First, a couple of notes:
- I'm using Vaadin 7, so the Bean Validation addon sadly won't work.
- The data validation works as intended.
Now, I have a perfectly working table for which I am using a BeanItemContainer to keep my Person beans inside.
The code for the table and the TableFieldFactory looks something like this:
table.setContainerDataSource(buildContainer());
table.setTableFieldFactory(new TableFieldFactory() {
@Override
public Field createField(Container container, Object itemId, Object propertyId, Component uiContext) {
TextField field = (TextField) DefaultFieldFactory.get().createField(container, itemId, propertyId,
uiContext);
field.setImmediate(true);
if (propertyId.equals("firstName")) {
field.addValidator(new BeanValidator(Person.class, "firstName"));
}
return field;
}
});
The Person bean looks as follows:
public class Person {
@Size(min = 5, max = 50)
private String firstName;
... setters + getters...
}
The problem is that when I type something in the firstName field and then press enter or blur/unfocus that field, no indication whatsoever of error is shown. I have to mouseover the field to see that something is wrong.
My question is two folded...
- How do I get the exclamation mark icon to appear when the field is invalid? (This works for a normal TextField that is not in a Table)
- Is there a way to get an immediate response from the invalid field (show the icon) (i.e. immediately after you type under 5 chars, without having to press enter or blur/unfocus the field in question).
Would be great if I could have both questions answered! =)
Thanks in advance!
回答1:
The Caption, Required Indicator (the red asterisk) and - most importantly here - Error Indicator (exclamation mark) are actually provided by the layouts containing the component, not the component themselves. When editable components are displayed in a table, they are displayed without a layout - that's why no error indicator is displayed.
If I were trying to square this circle, I would look at creating a CustomField as a wrapper for the editable field - and within that CustomField display an error indicator when the wrapped/delegate field becomes invalid. I've not tried this - I've not used editable fields in a table at all - but should be fairly easy to do.
Add a TextChangeListener to the field in FieldFactory, and call field.validate() in the listener. Note, though, that field.getValue() value is not normally changed until blur/unfocus, ergo the validator will be validating the old value - unless you do field.setValue(event.getText()) in the listener. See this post on the Vaadin forum for more details.
This is the sort of thing I meant for a validating wrapper - not tried using it. You'll see initComponent simply returns the field inside a FormLayout, which should give you the icon(s) you're seeking. (You may need to delegate more methods from ValidatingWrapper to delegate than I have- but quick look suggests this may be enough.)
You'd then wrap the field in your tableFieldFactory (second code block)
public class ValidatingWrapper<T> extends CustomField<T> {
private static final long serialVersionUID = 9208404294767862319L;
protected Field<T> delegate;
public ValidatingWrapper(final Field<T> delegate) {
this.delegate = delegate;
if (delegate instanceof TextField) {
final TextField textField = (TextField) delegate;
textField.setTextChangeEventMode(AbstractTextField.TextChangeEventMode.TIMEOUT);
textField.setTextChangeTimeout(200);
textField.addTextChangeListener(new FieldEvents.TextChangeListener() {
@Override
public void textChange(FieldEvents.TextChangeEvent event) {
textField.setValue(event.getText());
textField.validate();
}
});
}
}
@Override
public Class<? extends T> getType() {
return delegate.getType();
}
@Override
protected Component initContent() {
return new FormLayout(delegate);
}
@Override
public Property getPropertyDataSource() {
return delegate.getPropertyDataSource();
}
@Override
public void setPropertyDataSource(Property newDataSource) {
delegate.setPropertyDataSource(newDataSource);
}
}
table.setContainerDataSource(buildContainer());
table.setTableFieldFactory(new TableFieldFactory() {
@Override
public Field createField(Container container, Object itemId, Object propertyId, Component uiContext) {
TextField field = (TextField) DefaultFieldFactory.get().createField(container, itemId, propertyId,
uiContext);
field.setImmediate(true);
if (propertyId.equals("firstName")) {
field.addValidator(new BeanValidator(Person.class, "firstName"));
}
return ValidatingWrapper(field);
}
});
来源:https://stackoverflow.com/questions/17950121/validation-icon-not-shown-in-table-fields