Нажатие 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 предназначен, например. загружать данные из БД, и нет причин запускать их для исходного значения, а затем снова для нового значения.

Если я использую стандартный 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-битная версия)
  • ПраймФейс 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