当页面加载了绑定到视图作用域支持bean中的值的输入并且如果该值已预先初始化时,则在要求的字段验证之后,将再次使用先前的值填充输入。
这是托管bean:
@ManagedBean(name = "adminController")
@ViewScoped
public class AdminController extends BaseWebController implements Serializable {
private static final long serialVersionUID = 1019716974557397635L;
private transient CustomerDTO customerDTO;
public AdminController() {
log.debug("Inside AdminController");
}
@PostConstruct
public void init() {
initCustomerDTO();
customerDTO.setCustomerName("Test");
}
public void saveCustomer(ActionEvent event) {
try {
getServiceProvider().getCustomerService().addNewCustomer(customerDTO);
getFacesContext().addMessage(null, FacesMessageUtils.getMessageForCustomerSaveSuccess(getFacesContext()));
} catch (Throwable throwable) {
getFacesContext().addMessage(null, FacesMessageUtils.getMessageForCustomerSaveError(getFacesContext()));
printStackTrace(throwable);
}
initCustomerDTO();
}
private void initCustomerDTO() {
customerDTO = new CustomerDTO();
}
public CustomerDTO getCustomerDTO() {
return customerDTO;
}
public void setCustomerDTO(CustomerDTO customerDTO) {
this.customerDTO = customerDTO;
}
}
CustomerDTO
是一个POJO。jsf包含:
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:p="http://primefaces.org/ui"
xmlns:pe="http://primefaces.org/ui/extensions">
<h:form id="customerForm">
<p:inputText id="customerName" styleClass="customerName"
autocomplete="off"
label="#{adbBundle['admin.addCustomerPanel.addCustomerTable.customerName']}"
value="#{adminController.customerDTO.customerName}"
required="true" />
<p:commandButton value="#{adbBundle['saveButton']}"
actionListener="#{adminController.saveCustomer}"
icon="ui-icon-check"
update=":growl, @form, :adminTabView:customerListForm:customerListPanel" />
</h:form>
</ui:composition>
我还有一个自定义转换器类,用于修剪空白
String
。@FacesConverter(forClass = String.class)
public class StringTrimmer implements Converter {
@Override
public Object getAsObject(FacesContext context, UIComponent component, String value) {
if (StringUtils.isBlank(value)) {
if (component instanceof EditableValueHolder) {
((EditableValueHolder) component).setSubmittedValue(null);
}
return null;
}
return value;
}
@Override
public String getAsString(FacesContext context, UIComponent component, Object value) {
return value.toString();
}
}
因此,在首次加载页面时,输入字段将包含“测试”。我清理了测试字段,然后单击保存按钮。我收到了用于必填字段验证的错误消息,但是再次使用我之前设置的默认值“ Test”填充了输入。
我该如何解决这个问题?
更新:
我在带有Mojarra 2.1.7的JBoss AS7中运行,这是JBoss的实现和Primefaces 3.4.2。
最佳答案
您的问题是由转换器引起的。
当针对特定组件的JSF验证失败时,所提交的值将保留在该组件中,否则将被清空并设置为本地值。当JSF完成对所有组件的验证并且没有人通过验证时,所有本地值都将被清空并设置为模型值(一个称为value
属性的值)。当JSF需要用值重新显示表单时,它首先检查提交的值是否不为null,然后显示它,否则它检查本地值是否不为null,然后显示它,否则它直接显示模型值。
就您而言,无论验证结果如何,您都将将空字符串提交的值转换为null
。因此,提交的值始终为null
,因此JSF将始终重新显示模型值,而不是空字符串提交的值。
我相信您宁愿使用以下上下文参数而不是转换器,当然,如果唯一的目标是防止在提交空输入时模型值被空字符串污染,则可以肯定。
<context-param>
<param-name>javax.faces.INTERPRET_EMPTY_STRING_SUBMITTED_VALUES_AS_NULL</param-name>
<param-value>true</param-value>
</context-param>
或者,如果您的唯一目标确实是从字符串中修剪空白,如转换器类名称所建议的那样,那么您根本不应该触摸提交的值。您可以在此处找到一个具体示例:Why does <h:inputText required="true"> allow blank spaces?
getAsObject()
不会设置为提交值,而是设置为本地值(验证成功时),最终设置为模型值。