我有一个国家级:
public class Country{
private Long id;
private String name;
}
和具有两个国家/地区字段的人员类
public class Person{
private Country nationality;
private Country nationality2;
}
现在在JSF中,我使用<f:selectItems>
返回选择国籍的国家/地区列表,如下所示:
<h:form id="form1">
<h:selectOneMenu value="#{mybean.person.nationality.id}">
<f:selectItems value="#{mybean.countryList}" var="var" itemValue="#{var.id}"/>
</h:selectOneMenu>
<h:selectOneMenu value="#{mybean.person.nationality2.id}">
<f:selectItems value="#{mybean.countryList}" var="var" itemValue="#{var.id}"/>
</h:selectOneMenu>
<p:commandButton actionListener="#{mybean.save}" update="sometable @form"/>
</h:form>
现在奇怪的问题是,当我提交表格时,分配给第二个字段(国籍2)的值被分配给国籍和国籍2,而不管第一个字段选择了什么。例如,当我提交表单selected value for nationality is 1
时,selected value for nationality2 is 2
和both fields have the value 2
。为什么会这样?
PS:JSF实现是Mojarra 2.1.3
答案 0 :(得分:2)
导致您的具体问题是因为您将相同Country
引用的副本设置为选定值,然后仅操作id
属性。在一个引用中进行的所有更改也会反映在所有其他引用中。
E.g。
Country country = new Country();
person.setNationality1(country);
person.setNationality2(country);
country.setId(1); // Gets reflected in both nationalities!
您最好将整个Country
实体设置为值,而不是操纵其属性。创建一个Converter
,可在Country
和id
之间进行转换:
@FacesConverter(forClass=Country.class)
public class CountryConverter implements Converter {
@Override
public String getAsString(FacesContext context, UIComponent component, Object value) {
return (value instanceof Country) ? ((Country) value).getId() : null;
}
@Override
public Object getAsObject(FacesContext context, UIComponent component, String value) {
if (value == null || value.isEmpty()) {
return null;
}
if (!value.matches("\\d+")) {
throw new ConverterException(new FacesMessage("Invalid country ID: " + value));
}
Long countryId = Long.valueOf(value);
MyBean myBean = context.getApplication().evaluateExpressionGet(context, "#{myBean}", MyBean.class);
for (Country country : myBean.getCountries()) {
if (countryId.equals(country.getId())) {
return country;
}
}
throw new ConverterException(new FacesMessage("Unknown country ID: " + value));
}
}
并按如下方式使用:
<h:selectOneMenu value="#{mybean.person.nationality1}">
<f:selectItems value="#{mybean.countries}" var="country" itemValue="#{country}" itemLabel="#{country.name}" />
</h:selectOneMenu>
<h:selectOneMenu value="#{mybean.person.nationality2}">
<f:selectItems value="#{mybean.countries}" var="country" itemValue="#{country}" itemLabel="#{country.name}" />
</h:selectOneMenu>
答案 1 :(得分:1)
尝试为selectOneMenu
提供第二个var
其他名称。例如:
<h:selectOneMenu value="#{mybean.person.nationality2.id}">
<f:selectItems value="#{mybean.countryList}" var="var2" itemValue="#{var2.code}"/>
</h:selectOneMenu>
否则,您可以通过更改第二个var
来覆盖(第一个)变量selectOneMenu
中的更改。
修改强>
如果它没有解决问题,请尝试测试以创建第二个countryList
(countryList2)并将其附加到第二个selectOneMenu
。
如果值仍然保持不变,则失败必须在getter或setter中。