0

使用 JSF2 (MyFaces 2.1) 和 CDI (Weld) 我使用一个填充了枚举的 selectOneMenu 来有条件地呈现第二个 selectOneMenu(代码中的doublemenu)。表单中还有其他几个字段使用 bean 验证进行验证。

问题:

如果单击命令按钮后出现验证错误并显示错误消息,则不会再次出现双菜单。似乎bean.type =='double'不正确。但为什么?selectOneMenu 本身将选项双重显示为所选项目。

@javax.inject.Named
@javax.enterprise.context.RequestScoped
public class Bean {

private enum MyEnum {
    Single, Double
}

private MyEnum type;

public MyEnum getType() {
    return type;
}

public void setType(MyEnum type) {
    this.type = type;
}

public MyEnum [] getTypes() {
    return MyEnum.values();
}


<h:form>
<h:selectOneMenu value="#{bean.type}">
  <f:selectItems value="#{bean.types}" />
  <f:ajax render="doublemenu" />
</h:selectOneMenu>

<h:panelGroup id="doublemenu">
  <h:panelGroup rendered="#{bean.type == 'double'}">
    <h:selectOneMenu ...>
    </h:selectOneMenu>
  </h:panelGroup>
</h:panelGroup>
<h:inputText id="VALIDATED"/>
<h:commandButtonaction="#{bean.save}"
</h:form>

顺便说一句:bean.save未执行

4

1 回答 1

4

这是因为您的 bean 是请求范围的。请求范围的 bean 在每个请求结束时被丢弃,并在每个请求开始时新创建。这也适用于同一视图上的单个 ajax 请求。

在收集提交的值(应用请求值阶段)期间也会评估该rendered属性。但是,在要收集提交的值时,显然还没有设置(它仍然需要在更新模型值阶段根据收集的提交值进行设置)。由于您的 bean 是请求范围的,因此它将返回默认值,而不是先前请求中提交的值。#{bean.type}

基本上有两种方法可以解决这个问题。

  1. 将 bean 放在更广泛的范围内。JSF@ViewScoped正是为此目的而提供的。这在当前的 JSF 2.1 版本中仅与 CDI 不兼容。如果切换到 JSF@ManagedBean不是一个选项,那么您需要MyFaces CODI将 JSF 透明地桥@ViewScoped接到 CDI,或者等待 JSF 2.2 获得@ViewScoped开箱即用的 CDI 兼容。

  2. 检查请求参数而不是 bean 属性。

    <h:selectOneMenu binding="#{type}" ...>
        ...
    </h:selectOneMenu>
    
    <h:panelGroup rendered="#{param[type.clientId] == 'Double'}">
    

请注意,这一切都与枚举完全无关。使用例如 a 时,您会遇到完全相同的问题String。另请注意,我在您的代码示例中修正了一个错字,枚举值Double肯定与double.

也可以看看:

于 2013-02-12T18:07:55.817 回答