单击p:commandButton会导致p:selectOneMenu的值被设置两次

时间:2015-08-30 10:58:38

标签: jsf primefaces selectonemenu commandbutton

我遇到了PrimeFaces的问题 - 考虑将SelectOneMenu置于Inplace内的表单。在Inplace旁边,我们有一个CommandButton,用于重置SelectOneMenu的值。

表格如下:

<h:form id="myform">
    <p:inplace id="inplace" editor="true">
        <p:ajax event="save" update="@(form)" />

        <f:facet name="output">
            <h:outputText value="#{testBean.year}" />
        </f:facet>

        <f:facet name="input">
            <p:selectOneMenu id="selYears" value="#{testBean.year}">
                <f:selectItem itemValue="2015" itemLabel="2015" />
                <f:selectItem itemValue="2014" itemLabel="2014" />
                <f:selectItem itemValue="2013" itemLabel="2013" />
            </p:selectOneMenu>
        </f:facet>
    </p:inplace>

    <p:commandButton id="btnResetYear" value="Reset year" rendered="#{testBean.year lt 2015}"
        action="#{testBean.resetYear()}" update="@(form)" />

</h:form>

这是TestBean:

import javax.annotation.PostConstruct;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;

@ManagedBean
@ViewScoped
public class TestBean {
    private int year;

    @PostConstruct
    private void init() {
        this.year = 2015;
    }

    public int getYear() {
        return year;
    }

    public void setYear(int year) {
        System.out.println("---> setYear: " + year);
        this.year = year;
        this.someMethod();
    }

    public void someMethod() {
        System.out.println("---> someMethod: " + this.year);
    }

    public void resetYear() {
        System.out.println("---> resetYear");
        this.setYear(2015);
    }
}

以下方案可以正常使用:

  1. 点击年份以显示实际的SelectOneMenu
  2. 选择不同年份(例如2013年)
  3. 点击“检查”按钮
  4. 确认选择

    但是,如果我尝试点击“重置年份”按钮,则会调用方法setYear,并在调用resetYear之前将原始年份作为参数。这是我在控制台中可以看到的:

    12:28:40,003 INFO  [stdout] (default task-15) ---> setYear: 2013
    12:28:40,003 INFO  [stdout] (default task-15) ---> someMethod: 2013
    12:28:40,004 INFO  [stdout] (default task-15) ---> resetYear
    12:28:40,004 INFO  [stdout] (default task-15) ---> setYear: 2015
    12:28:40,004 INFO  [stdout] (default task-15) ---> someMethod: 2015
    

    我不想要的是someMethod,例如从DB加载数据,没有理由为原始值运行它,然后再次为新值运行。

    如果我使用标准CommandButton而不是PrimeFaces提供的标准,它似乎正常工作:

    <h:commandButton id="btnResetYear" value="Reset year" rendered="#{testBean.year lt 2015}">
        <f:ajax listener="#{testBean.resetYear}" render="myform" />
    </h:commandButton>
    

    单击标准按钮将显示预期结果:

    12:42:11,506 INFO  [stdout] (default task-88) ---> resetYear
    12:42:11,506 INFO  [stdout] (default task-88) ---> setYear: 2015
    12:42:11,506 INFO  [stdout] (default task-88) ---> someMethod: 2015
    

    问题:

    这是PrimeFaces中的错误还是我做错了什么?有没有办法设置PF的CommandButton行为如上所述,即不传入传入旧参数的setYear方法或我是否必须坚持“标准”CommandButton

    我正在尝试将immediate="true"设置为CommandButton,但它确实跳过首先设置原始值,但SelectOneMenu没有考虑新值,无论是什么我输入了按钮的update属性 - 它仍显示原始值。

    该示例使用以下命令运行:

    • Java 1.8(jdk1.8.0_51 - 64bit)
    • PrimeFaces 5.2
    • WildFly 8.2.0(也使用JBoss 7.1测试)

    任何想法都非常受欢迎。

1 个答案:

答案 0 :(得分:2)

经过几个小时后,我发现了问题所在 - PF的CommandButton的默认行为是处理页面上的所有内容,这与我设置process="@all"

我通过检查CommandButton发送/接收的请求/响应的详细信息找到了这一点 - 请求标头中有以下参数:

javax.faces.partial.execute = @all

所以将process="@this"设置为CommandButton就可以了,我现在可以观察到正确的行为了:

18:45:51,874 INFO  [stdout] (default task-41) ---> resetYear
18:45:51,874 INFO  [stdout] (default task-41) ---> setYear: 2015
18:45:51,874 INFO  [stdout] (default task-41) ---> someMethod: 2015

这是我CommandButton的最终版本:

<p:commandButton id="btnResetYear" value="Reset year" rendered="#{testBean.year lt 2015}"
    action="#{testBean.resetYear()}" update="@(form)" process="@this" />

我希望通过在此处发布此解决方案来节省别人的时间: - )