当我遇到p:selectOneMenu
中使用的以下条件时,我正在从this template中检查OmniFaces Showcase app的代码:
disabled="#{facesContext.postback and not facesContext.renderResponse}"
通过使用该应用程序,似乎从未禁用过selectOneMenu,那么这段代码实际上是做什么的?
我知道,只要页面是由JSF组件(commandButton/commandLink等)生成的POST请求生成的,
facesContext.postback
就是true
,但是在View中求值时facesContext.renderResponse
的通常预期状态是什么?更新:哎呀,刚才我看到了注释:除了渲染响应外,它们在其他阶段被禁用,因为他们否则提示即使没有表单也无法设置模型值。
因此,我猜想在Faces生命周期中会多次评估条件,并且禁用组件直到达到最后一个状态(renderResponse),当
facesContext.renderResponse
评估为true
时,整个表达式评估为false
然后启用该组件。那是对的吗? 最佳答案
那些<p:selectOneMenu>
组件实际上被滥用为带有最少代码的漂亮<div><ul><li>
下拉菜单;)它们的值表示当前菜单组和页面,这些菜单组和页面在设计上是只读的(它们没有setter方法)。导航通过在更改事件期间处理的JavaScript window.location
进行。它们不属于任何形式,也不参与任何形式的提交。disabled
属性从理论上讲不是强制性的,但是当同步提交同一页面中其他位置的非ajax JSF表单时,即使根本没有将它封装在任何形式中,PrimeFaces SelectOneMenuRenderer
仍将尝试对它进行完整的decode()
编码。当要更新模型值时,最终会导致以下异常,因为该值没有 setter :
javax.el.PropertyNotWritableException: /WEB-INF/templates/showcase.xhtml @28,80 value="#{parent.children[0].viewId}": The class 'org.omnifaces.showcase.Page' does not have a writable property 'viewId'.
at com.sun.faces.facelets.el.TagValueExpression.setValue(TagValueExpression.java:136)
at javax.faces.component.UIInput.updateModel(UIInput.java:818)
at javax.faces.component.UIInput.processUpdates(UIInput.java:735)
at javax.faces.component.UIComponentBase.processUpdates(UIComponentBase.java:1242)
at org.primefaces.component.panel.Panel.processUpdates(Panel.java:304)
at javax.faces.component.UIComponentBase.processUpdates(UIComponentBase.java:1242)
at javax.faces.component.UIComponentBase.processUpdates(UIComponentBase.java:1242)
at javax.faces.component.UIViewRoot.processUpdates(UIViewRoot.java:1231)
at com.sun.faces.lifecycle.UpdateModelValuesPhase.execute(UpdateModelValuesPhase.java:78)
at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:101)
at com.sun.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:118)
at javax.faces.webapp.FacesServlet.service(FacesServlet.java:593)
当
disabled
属性在postback期间评估true
时,那么SelectOneMenuRenderer
将在应用请求值阶段跳过decode()
,因此也跳过模型值的更新。但是,如果在render response phase期间也对true
求值,那么它将变为不可选择(因此不可使用)。因此,它不应在渲染响应阶段评估为true。表达方式disabled="#{facesContext.postback and not facesContext.renderResponse}"
做到这一点。总而言之,这基本上是
SelectOneMenuRenderer
异常行为的一种解决方法(对此我尚未真正调查其根本原因)。要自己进行测试,请拉出项目,删除
disabled
属性,然后在<o:onloadScript>
展示页面中调用同步提交。关于jsf-2 - #{facesContext.postback而不是facesContext.renderResponse}条件是什么意思?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/14068891/