我在一个后台bean为Request Scoped的页面上有两个下拉列表。第一次呈现页面时,第二个下拉菜单始终处于禁用状态。但是,如果用户将第一个下拉菜单切换到与默认值不同的值,则会启用第二个下拉菜单。当用户提交表单时,我希望我的RequestScoped托管bean看到第二个下拉列表的值。然而,很明显,由于第二个下拉列表最初被禁用,因此它的值不会与表单一起提交,即使在提交表单时,下拉列表也已启用。
我解决这个问题的方法是将第二个下拉列表的禁用"状态"存储在ViewScoped bean中。这样,当用户将第一个下拉列表更改为默认值以外的值时,actionListener可以触发,它将更新与第二个下拉列表关联的ViewScoped bean的值(将其状态更改为未禁用)。
这是处理这种情况的最佳方法吗?或者有更好的方法吗?
这确实是最明智的方法。
如果真的需要将您的bean放在请求范围内,那么另一种选择是根据您可以在请求参数映射中找到的第一个下拉列表的提交值,在bean的(post)构造函数中重新确定第二个下拉菜单的disabled
状态(或者让JSF通过@ManagedProperty
设置它)。您只需要在必要时手动重复JSF转换/验证。
假设当第一个下拉列表的提交值等于字符串值foo
并且第一个下拉菜单的客户端ID为form:dropdown1
:时,第二个下拉列表不应再被禁用
public Bean() {
this.dropdown2disabled = !"foo".equals(FacesContext.getCurrentInstance()
.getExternalContext().getRequestParameterMap().get("form:dropdown1"));
}
但正如您所发现的,视图范围的bean更容易。
作为另一种选择,您可以使用Tomahawk的<t:saveState>
将单个属性直接存储在视图状态中。将此添加到视图的某个位置,然后:
<t:saveState value="#{bean.dropdown2disabled}" />
这将导致视图状态的大小比使用视图范围的bean时更小。
我也遇到了类似的问题。我最终用一个"假的"残疾人解决了这个问题。
<div style="position:relative">
<p:inputText styleClass="ui-state-disabled">
<!-- fake-disable input field -->
<div style="position:absolute; top:0; left:0; width:100%; height:100%;"/>
</div>
在输入上方使用不可见的div,用户无法与之交互。此外,我为输入字段设置了样式,使其看起来被禁用。