问题
Is there (there must be?) a way to clear a form field that has validation errors in Spring 3? I know that clearing the "command" object properties works ... but only if there are no errors. Somehow the fields gets repopulated by Spring when there are validation errors (FieldErrors or GlobalErrors).
回答1:
So I have found a solution to the problem. It works very well but It seems a bit overkill for something as simple as clearing a field.
Maybe a javascript snippet is a cleaner solution?
Well enough with the ranting here is the solution: Clear the form field in the "command" object (the form backing object) when there are no error in the field.
When there is validation errors Spring picks up the values "rejectedValuse" from the BindingResult object so make a "proxy" of the BindingResult and return "" when the getFieldValue(String s) function is called.. Make a "what did you say"? ... a proxy. Like this:
public class BindingResultProxy implements BindingResult {
final private BindingResult proxied;
final private Set<String> fieldsToClearValueFor;
public BindingResultProxy(BindingResult proxied) {
this.proxied = proxied;
fieldsToClearValueFor = new TreeSet<String>();
}
public void clearFieldValueFor(String fieldname) {
fieldsToClearValueFor.add(fieldname);
}
@Override
public Object getTarget() {
return proxied.getTarget();
}
@Override
public Map<String, Object> getModel() {
return proxied.getModel();
}
.... And it goes on to override all the methods in BindingResults using proxied like the above method .. then in getFieldValue() return "" when decided by some mechanism.. (list) you get the point? :-)
@Override
public Object getFieldValue(String s) {
if (fieldsToClearValueFor.contains(s)) return "";
return proxied.getFieldValue(s);
}
Then in the controller use:
if(result.hasErrors()){
//If there are errors, clear the fields
ArrayList<String> fieldsToClear = new ArrayList<String>(3);
for(FieldError fieldError: result.getFieldErrors()) {
fieldsToClear.add(fieldError.getField());
}
if(result.hasGlobalErrors()){
//there is only one global error here in case the new password does not match the confirm password
//so clear the confirmPassword as well
fieldsToClear.add("confirmPassword");
}
clearFormFieldValues(result, model, fieldsToClear.toArray(new String[fieldsToClear.size()]));
return "/account/changePassword";
.....
private void clearFormFieldValues(BindingResult result, Model model, String... fieldsToClear) {
final BindingResultProxy configuredBindingResult = new BindingResultProxy(result);
for (String fieldToClear : fieldsToClear) {
configuredBindingResult.clearFieldValueFor(fieldToClear);
}
model.addAttribute("org.springframework.validation.BindingResult.changePasswordForm",
configuredBindingResult);
}
Very simple indeed?!??!?
回答2:
Cleaner solution, after seven years. Courtesy of https://stackoverflow.com/a/61609112/4618338
if(result.hasErrors()) {
BeanPropertyBindingResult result2 = new BeanPropertyBindingResult(watchedDirectory, theBindingResult.getObjectName());
for(ObjectError error : result.getGlobalErrors()) {
result2.addError(error);
}
for(FieldError error :result.getFieldErrors()) {
Object rejectedValue = shouldBeCleared(error.getField()) ? null : error.getRejectedValue();
result2.addError(new FieldError(error.getObjectName(), error.getField(), rejectedValue, error.isBindingFailure(), error.getCodes(), error.getArguments(), error.getDefaultMessage()));
}
model.addAllAttributes(result2.getModel());
return "/account/changePassword";
}
// ... no errors; persist changes, return appropriate view
The alternative is to make 200+ lines proxy-class and configuring it in the controller method anyway.
来源:https://stackoverflow.com/questions/16837433/clear-form-fields-after-validation-errors-in-spring-3