I have some POJO with JSR 303 validation like this one :
@NotNull
@Size(max = 80)
@Column(name = "trs_name")
private String name;
In the application, I render it with a GXT TextField wrapped in a GXT FieldLabel, inside a GWT Editor. If the validation fails, the FieldLabel automatically displays a red wave and a red flag :
And this is exactly what I need.
But for more complex validation like this one :
@Size(min = 1)
private Set<EnumRole> roles;
I created a custom Editor<Set<Enum>>
:
public class EnumSetEditor<T extends Enum<T>> extends Composite implements LeafValueEditor<Set<T>> {
private Map<T, CheckBox> map;
public EnumSetEditor(Class<T> clazz) {
FlowPanel panel = new FlowPanel();
this.map = new HashMap<T, CheckBox>();
for(T t : clazz.getEnumConstants()) {
CheckBox cb = new CheckBox();
cb.setBoxLabel(I18nEnum.i18nEnum(t)); //translates the enum
panel.add(cb);
map.put(t, cb);
}
this.initWidget(panel);
}
@Override
public void setValue(Set<T> value) {
for(Map.Entry<T, CheckBox> entry : map.entrySet()) {
entry.getValue().setValue(value.contains(entry.getKey()));
}
}
@Override
public Set<T> getValue() {
Set<T> result = new HashSet<T>();
for(Map.Entry<T, CheckBox> entry : map.entrySet()) {
if(entry.getValue().getValue()) {
result.add(entry.getKey());
}
}
return result;
}
}
It is rendred like this :
The problem is that, even wrapped in a GXT FieldLabel, I have no feedback if no option is checked. Hence, the validation fails and the user has no feedback.
I thought that the GXT FieldLabel would automatically add the red flag on the right of the editor in case of validation failure.
I finally found the solution myself : I believed that the FieldLabel handled the feedback itself but this is wrong.
My class must implement HasEditorErrors<Set<T>>
so that method void showErrors(List<EditorError> errors)
is called. I can do whatever I want in this case : display an icon, underline something etc.
There is a predefined class in GXT which handles the icon + the validation message : SideErrorHandler
.
Hence, I modified the class like this :
public class EnumSetEditor<T extends Enum<T>> extends Composite implements LeafValueEditor<Set<T>>, HasEditorErrors<Set<T>> {
//Added errorHandler attribute
private SideErrorHandler errorHandler;
public EnumSetEditor(Class<T> clazz) {
...
//Initialize the ErrorHandler
this.errorHandler = new SideErrorHandler(this);
}
/*
* Implemented showErrors(List<EditorError> errors)
* I only delegate the errors to the ErrorHandler.
*/
@Override
public void showErrors(List<EditorError> errors) {
if(errors.isEmpty()) {
errorHandler.clearInvalid();
} else {
errorHandler.markInvalid(errors);
}
}
}