【问题标题】:<h:commandButton> does not invoke action<h:commandButton> 不调用操作
【发布时间】:2012-07-06 09:11:00
【问题描述】:

在使用 JSF 2(Glassfish 3.1.1 上的 mojarra)进行的一些测试中,我遇到了我无法解释的奇怪行为。

这是我的托管 bean:

@ManagedBean
@RequestScoped
public class TestBean {
    private int id;

    public void hideButton() {
        id = 0;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }
}

这是我的 xhtml 页面

   <h:form>
       <h:inputHidden value="#{testBean.id}"/>

       <h:outputText value="#{testBean.id}"/>

       <h:commandButton value="set 1"
                    actionListener="#{testBean.setId(1)}">
       </h:commandButton>

       <h:commandButton value="hide button"
                    action="#{testBean.hideButton}" rendered="#{testBean.id > 0}">
       </h:commandButton>            
   </h:form>

我预计,“隐藏按钮”按钮在页面初始加载时不可见,这确实是事实。单击“set 1”按钮后,会出现“隐藏按钮”按钮,这也是意料之中的。 对我来说真的无法理解的是,随后单击“隐藏按钮”按钮并没有调用方法 testBean.hideButton 并将 id 设置为 0。 我在这里阅读了 BalusC 的非常有用的答案(非常感谢)

commandButton/commandLink/ajax action/listener method not invoked or input value not updated

并认识到,问题与“rendered”属性有关,如果我将其删除,则会调用该操作。 但据我所知,必须在 UPDATE MODEL VALUES 阶段初始化类成员,并且在 INVOKE APPLICATION 阶段应将呈现的属性中提到的条件评估为 true 并调用操作。

如果我将 bean 的范围更改为 View/Session,则该示例有效。 但如果我从“隐藏按钮”中删除渲染属性,它也可以正常工作

有人会解释这种行为吗?

换句话说,在什么阶段渲染属性的表达式被评估以决定不调用动作?

【问题讨论】:

  • 在问题的初始版本中,我错误地引用了 BalusC 的答案,对不起
  • 之前的旧答案不知何故被删除了,不是故意的。

标签: jsf-2 glassfish-3 mojarra


【解决方案1】:

rendered 属性也在应用请求值阶段进行评估,此时 JSF 需要确定需要调用哪个操作。如果它评估false,则无法识别该操作,因此也不会调用该操作。

问题是由托管 bean 范围太窄引起的。由于您的托管 bean 是请求范围的,因此它会在响应结束时被丢弃,并在任何后续请求中重新创建(所有属性都设置为默认值)。 rendered 属性所依赖的模型值只会在更新模型值阶段更新,这为时已晚。您应该将托管 bean 放在视图范围内。

除了将bean作用域改为视图作用域外,另一种方法是在rendered属性中检查请求参数映射值。

<h:form id="form">
    <h:inputHidden id="id" ... />

    <h:commandButton ... rendered="#{param['form:id'] gt 0}" />
</h:form>

(顺便说一下,您使用 &gt; 而不是 gt 表明您使用的是已弃用的 JSP 视图技术而不是 Facelets,我强烈建议您迁移到 Facelets)

另见:

【讨论】:

    【解决方案2】:

    我找到了问题的原因。

    方法 UIComponentBase.processDecodes(在应用请求值阶段)调用 isRendered,它返回 false,因为它在更新模型值之前。跳过组件的解码。

    有一些可能的解决方法,恕我直言,它们都不是很酷,但它仍然有效

    可以通过请求参数在(后)构造函数中手动设置托管 bean 中的必要值。 或者使用

    【讨论】:

      猜你喜欢
      • 2013-06-26
      • 2016-03-08
      • 1970-01-01
      • 2013-07-18
      • 2013-12-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多