<h:commandbutton>不会调用操作</h:commandbutton>

时间:2012-07-05 22:09:27

标签: jsf-2 glassfish-3 mojarra

在使用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>

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

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

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

如果我将bean的范围更改为View / Session,则该示例有效。 但是如果我从“隐藏按钮”

中删除了渲染属性,它也可以正常工作

有人会解释这种行为吗?

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

2 个答案:

答案 0 :(得分:4)

在应用请求值阶段,当JSF需要识别需要调用哪个操作时,还会评估rendered属性。如果它评估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表示您使用的是不推荐使用的JSP视图技术而不是Facelets,我强烈建议您迁移到Facelets) / em>的

另见:

答案 1 :(得分:0)

我发现自己是问题的原因。

方法UIComponentBase.processDecodes(在Apply Request Values阶段)调用isRendered,它返回false,因为它位于Update Model Values之前。这会跳过组件的解码。

有一些可行的解决方法,所有这些都不是很酷,但它仍然有效

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