使用JSF2(MyFaces 2.1)和CDI(Weld)我使用一个带有枚举的selectOneMenu来有条件地渲染第二个selectOneMenu(代码中的 doublemenu )。表单中还有其他几个字段,使用bean验证进行验证。
问题:
如果在单击commandButton后出现验证错误并显示错误消息,则不会再出现doublemenu。似乎 bean.type =='double'不正确。但为什么? selectOneMenu本身会将选项 double 显示为所选项目。
@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>
BTW: bean.save 未执行
答案 0 :(得分:4)
这是因为你的bean是请求作用域。请求范围的bean在每个请求结束时被包含,并在每个请求的开始时新创建。这也适用于同一视图上的单个ajax请求。
在收集提交的值(应用请求值阶段)期间,还会评估rendered
属性。但是,在收集提交的值时,#{bean.type}
显然尚未设置(在更新模型值阶段期间仍需根据收集的提交值进行设置) )。由于您的bean是请求作用域,它将返回默认值,而不是先前请求的提交值。
基本上有两种方法可以解决这个问题。
将bean放在更广泛的范围内。 JSF正是为了这个目的而提供@ViewScoped
。这是当前的JSF 2.1版本,只与CDI不兼容。如果不能选择切换到JSF @ManagedBean
,那么您需要MyFaces CODI将JSF @ViewScoped
透明地连接到CDI,或者等待JSF 2.2获得CDI兼容{{} 1}}开箱即用。
检查请求参数而不是bean属性。
@ViewScoped
请注意,这一切与枚举完全无关。使用例如,你会遇到完全相同的问题。一个<h:selectOneMenu binding="#{type}" ...>
...
</h:selectOneMenu>
<h:panelGroup rendered="#{param[type.clientId] == 'Double'}">
。另请注意,我在代码示例中修正了拼写错误,枚举值String
绝对与Double
不一样。