Щракването върху p:commandButton кара стойността на p:selectOneMenu да бъде зададена два пъти

Сблъсках се с проблем с 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. Потвърдете избора си, като щракнете върху бутона "проверка".

Ако обаче се опитам да щракна върху бутона „Нулиране на годината“, методът 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 ли е или съм направил нещо нередно? Има ли начин да настроя CommandButton на PF да се държи както е описано по-горе, т.е. да не задейства метода setYear със стар параметър, предаден или трябва да се придържам към "стандартния" CommandButton?

Експериментирах със задаване на immediate="true" на CommandButton и наистина първо пропусна първоначалната настройка на стойността, но SelectOneMenu не взе под внимание новата стойност, без значение какво поставих в атрибута update на бутона - все още показваше първоначалната стойност .

Примерът беше изпълнен с помощта на следното:

  • Java 1.8 (jdk1.8.0_51 - 64 бита)
  • PrimeFaces 5.2
  • WildFly 8.2.0 (тестван също с JBoss 7.1)

Всяка идея е повече от добре дошла.


person Sva.Mu    schedule 30.08.2015    source източник
comment
Свързани: stackoverflow.com/ въпроси/25339056/   -  person BalusC    schedule 31.08.2015


Отговори (1)


След още няколко часа разбрах какъв е проблемът - поведението по подразбиране на 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" />

Надявам се да спестя времето на някой друг, като публикувам това решение тук :-)

person Sva.Mu    schedule 30.08.2015