3

我有一个国家课程:

public class Country{
     private Long id;
     private String name;
}

和一个有两个 Country 字段的 person 类

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>

现在奇怪的问题是,当我提交表单时,分配给第二个字段(nationality2)的值会同时分配给nationality 和nationality2,而不管第一个字段选择了什么。例如,如果selected value for nationality is 1selected value for nationality2 is 2,当我提交表单时both fields have the value 2。为什么会出现这种情况?

PS:JSF 实现是 Mojarra 2.1.3

4

2 回答 2

2

您的具体问题是因为您将相同Country参考的副本设置为选定值,然后仅操作该id属性。在一个参考中所做的所有更改也会反映在所有其他参考中。

例如

Country country = new Country();
person.setNationality1(country);
person.setNationality2(country);
country.setId(1); // Gets reflected in both nationalities!

您最好将整个Country实体设置为值,而不是操纵其属性。创建一个在和Converter之间转换的:Countryid

@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>
于 2013-02-20T11:08:38.257 回答
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 中。

于 2013-02-19T07:47:04.407 回答