5

我在OmniFaces Showcase 应用程序中检查此模板的代码时,遇到了在 a 中使用的以下条件:p:selectOneMenu

disabled="#{facesContext.postback and not facesContext.renderResponse}"

从使用应用程序来看, selectOneMenu似乎从未被禁用,那么这段代码究竟做了什么?

我知道页面facesContext.postback是由 JSF 组件( commandButton/commandLink等)true生成的 POST 请求产生的,但是在视图中评估时通常的预期状态是什么?facesContext.renderResponse

更新:哎呀,刚才我看到了评论:它们在渲染响应之外的其他阶段被禁用,因为否则他们会抱怨即使没有 form 也无法设置模型值

所以,我猜这个条件在 Faces 生命周期中被评估了几次,并且组件被禁用,直到达到最后一个状态(renderResponse),当facesContext.renderResponse评估为时true,整个表达式评估false为然后启用组件。这对吗?

4

2 回答 2

5

这些<p:selectOneMenu>组件实际上被滥用以拥有一个<div><ul><li>带有最少代码的漂亮下拉菜单;)它们的值表示当前菜单组和页面,它们在设计上是只读的(它们没有 setter 方法)。window.location导航由在更改事件期间处理的 JavaScript进行。他们不属于任何形式,也不参与任何形式的提交。

disabled属性理论上不是强制性的,但是当同步提交同一页面中其他地方的非 ajax JSF 表单时,即使它根本没有包含在任何表单中,PrimeFacesSelectOneMenuRenderer仍会完整地尝试它。decode()当要更新模型值时,最终会导致以下异常,因为该值没有设置器:

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属性true发期间进行评估时,SelectOneMenuRenderer将跳过decode()应用请求值期间的阶段,从而也跳过模型值的更新。但是,如果它true渲染响应阶段也进行了评估,那么它将变得不可选择(因此无法使用)。因此,它不应该在渲染响应阶段评估为真。表达方式

disabled="#{facesContext.postback and not facesContext.renderResponse}"

正是做到了这一点。总而言之,它基本上是一种解决奇怪行为的方法SelectOneMenuRenderer(我还没有真正调查过根本原因)。

要自己测试,请拉取项目,删除disabled属性并在例如<o:onloadScript>展示页面中调用同步提交。

于 2012-12-28T12:30:39.167 回答
0

这将评估getter 状态以读取是否已调用renderResponse() 。此方法用于指示JSF 生命周期跳过后续阶段并直接发出响应(例如,在验证失败的情况下)。

于 2012-12-28T11:53:27.930 回答