【问题标题】:What does the condition #{facesContext.postback and not facesContext.renderResponse} mean?条件 #{facesContext.postback 而不是 facesContext.renderResponse} 是什么意思?
【发布时间】:2012-12-13 16:22:32
【问题描述】:

当我遇到p:selectOneMenu 中使用的以下条件时,我正在从OmniFaces Showcase app 中检查this template 的代码:

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

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

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

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

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

【问题讨论】:

    标签: jsf-2 el


    【解决方案1】:

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

    disabled 属性理论上不是强制性的,但是当同步提交同一页面中其他地方的非 ajax JSF 表单时,PrimeFaces SelectOneMenuRenderer 仍然会尝试完整地 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 属性在postback 期间评估true 时,SelectOneMenuRenderer 将在应用请求值阶段跳过decode(),从而也跳过模型值的更新。但是,如果它在render response phase 期间也评估true,那么它变得不可选择(因此无法使用)。因此,它不应该在渲染响应阶段评估为真。表达式

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

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

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

    【讨论】:

    • 谢谢,伙计!很酷的把戏!嗯……所以诀窍是组件只在渲染响应阶段解码,对吧?
    • 不,decode() 我基本上是指处理表单提交。渲染响应阶段不解码(应用请求值),它编码(生成 HTML 输出)。这样它在表单提交期间根本不会被处理(因为它被禁用),但它在 HTML 输出中显示为正常/启用状态。
    • 对,我说的是“解码”,但我正在考虑生成 HTML。谢谢,伙计,我想我现在明白了……做得很好!
    【解决方案2】:

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

    【讨论】:

    • 嘿,伙计!我认为renderResponse() 在生命周期结束时的每个请求中都会被调用,而不仅仅是在跳过阶段时。但我更怀疑facesContext.renderResponse 在视图中使用时的价值,我认为它在生命周期中会被多次评估......
    • 我错了,我检查了 Mojarra 代码中的用法,现在我认为 FacesContext.renderResponse() 是个例外,真的。那么,facesContext.getRenderResponse() 只有在跳过某个阶段时才会评估为真?
    • 它不调用FacesContext#renderResponse(),它调用FacesContext#getRenderResponse()
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-04-01
    • 1970-01-01
    • 2015-12-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-01-27
    相关资源
    最近更新 更多