[英]JSF2 h:selectOneMenu shows old value when Validation Failed
我有一個包含少量輸入字段和一個選擇菜單的表單。 所有字段都是必需的=“true”,firstName,lastName,emailAddress,密碼,國家/地區。
測試用例#1:1)在所有輸入字段中輸入值,保留firstName字段而不輸入任何值,
選擇一個國家/地區(例如:美國)並提交表單,我們可以看到firstName字段所需的錯誤消息。
2)保持表單不變,保留firstName字段而不輸入任何值,然后選擇country to“select one”,並提交表單。 我們可以看到firstName和country字段的錯誤消息,但是在下拉列表中它沒有顯示“Select One”,它顯示美國(之前的選擇)。
我對輸入字段有同樣的問題,但我用轉換器解決了。 有沒有辦法解決這個問題。 我在stackoverflow中發布了一些帖子,后來才知道這是mojarra中的一個bug。
這是我的代碼......
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core" >
<h:body>
<h:form id="registrationForm">
<h:messages layout="table" infoClass="infoMsgs" errorClass="errMsgs"/>
<table>
<tr>
<td>First Name:</td>
<td>
<h:inputText size="40" maxlength="100"
required="true"
styleClass="#{component.valid ? '' : 'text_error'}"
value="#{registrationAction.firstName}" />
</td>
</tr>
<tr>
<td>Last Name:</td>
<td>
<h:inputText size="40" maxlength="100"
required="true"
styleClass="#{component.valid ? '' : 'text_error'}"
value="#{registrationAction.lastName}" />
</td>
</tr>
<tr>
<td>Email Address:</td>
<td>
<h:inputText size="40" maxlength="100"
required="true"
styleClass="#{component.valid ? '' : 'text_error'}"
value="#{registrationAction.emailAddress}" />
</td>
</tr>
<tr>
<td>Password:</td>
<td>
<h:inputSecret size="20" maxlength="15"
required="true"
styleClass="#{component.valid ? '' : 'text_error'}"
value="#{registrationAction.password}" />
</td>
</tr>
<tr>
<td>Country:</td>
<td>
<h:selectOneMenu id="yourCountry" name="yourCountry"
value="#{shortRegistrationAction.shortRegistrationForm.selectedCountry}"
required="true"
styleClass="#{component.valid ? '' : 'text_error'}">
<f:selectItem itemValue="#{null}" itemLabel="-Select One-" />
<f:selectItems value="#{registrationAction.countryList}" />
</h:selectOneMenu>
</td>
</tr>
<tr>
<td> </td>
<td>
<h:commandButton name="RegisterButton" id="RegisterButton"
styleClass="submitbutton"
value="Register"
action="#{registrationAction.registerUser}" />
</td>
</table>
</h:form>
</h:body>
</html>
package com.ebiz.web.bean;
import java.io.Serializable;
import java.util.List;
import javax.annotation.PostConstruct;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ManagedProperty;
import javax.faces.bean.ViewScoped;
import com.ebiz.service.ICountryService;
import com.ebiz.service.IUserService;
import com.ebiz.vo.UserVO;
import org.apache.log4j.Logger;
@ManagedBean(name = "registrationAction")
@ViewScoped
public class RegistrationAction implements Serializable {
private static final long serialVersionUID = 1L;
private static final Logger log = Logger.getLogger(RegistrationAction.class);
@ManagedProperty("#{countryService}")
private ICountryService countryService;
@ManagedProperty("#{userService}")
private IUserService userService;
private String firstName;
private String lastName;
private String emailAddress;
private String password;
private String selectedCountry;
private List<String> countryList;
@PostConstruct
public void init(){
countryList = countryService.getCountryList();
}
public void registerUser() {
UserVO userVO = new UserVO();
userVO.setFirstName(firstName);
userVO.setLastName(lastName);
userVO.setEmailAddress(emailAddress);
userVO.setPassword(password);
userVO.setCountry(selectedCountry);
userService.registerUser(userVO);
}
}
package com.ebiz.web.converter;
import javax.faces.component.EditableValueHolder;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.convert.Converter;
import javax.faces.convert.FacesConverter;
@FacesConverter(forClass=String.class)
public class InputTextTrimmer implements Converter {
@Override
public Object getAsObject(FacesContext context, UIComponent component, String value) {
//return value != null ? value.trim() : null;
if (value == null || value.trim().isEmpty()) {
if (component instanceof EditableValueHolder) {
((EditableValueHolder) component).setSubmittedValue(null);
((EditableValueHolder) component).resetValue();
}
return null;
}
return value;
}
@Override
public String getAsString(FacesContext context, UIComponent component, Object value) {
return (value == null) ? null : value.toString();
}
}
在ajax更新中查看以下BalusC博客文章重置未處理的輸入組件
您可以將OmniFaces添加到項目中並使用其ResetInputAjaxActionListener
因此,您必須將代碼更新為此(您最好使用f:ajax
):
<h:commandButton name="RegisterButton" id="RegisterButton"
styleClass="submitbutton"
value="Register"
action="#{registrationAction.registerUser}">
<f:ajax execute="@form" render="@form" />
<f:actionListener type="org.omnifaces.eventlistener.ResetInputAjaxActionListener"/>
</h:commandButton>
另外,看看這個BalusC答案如何在驗證錯誤發生后使用primefaces ajax填充文本字段?
經過長時間的研究,我沒有找到任何方法在JSF中實現它。 所以我使用jQuery來處理它的客戶端,可能這個答案不是最好的解決方案,但至少對需要解決方案的人有用。
此處下拉值將顯示為舊值,但仍顯示下拉列表的驗證錯誤。 在上面的xhtml頁面中,如果你查看下拉菜單部分,
<h:selectOneMenu id="yourCountry" name="yourCountry"
value="#{shortRegistrationAction.shortRegistrationForm.selectedCountry}"
required="true"
styleClass="#{component.valid ? '' : 'text_error'}">
<f:selectItem itemValue="#{null}" itemLabel="-Select One-" />
<f:selectItems value="#{registrationAction.countryList}" />
</h:selectOneMenu>
即使它顯示驗證失敗案例的舊值,仍然styleClass變為text_error。 在關閉<h:body>
標記后,我在xhtml頁面中添加了以下代碼。 ie( </h:body>
)它只適用於這個特定xhtml頁面中的所有下拉菜單,但是我們可以將它放在commonTemplate.xhtml這樣的公共位置,以便在所有頁面上執行它。
<script>
//<![CDATA[
jQuery(document).ready(function() {
jQuery("select").each(function () {
var dropDownClass = jQuery(this).attr('class');
if(dropDownClass == 'text_error'){
jQuery(this).val('');
}
});
});
//]]>
</script>
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.