Порядок выполнения событий при нажатии PrimeFaces p: commandButton

Я пытаюсь выполнить метод JSF2 bean и показать диалоговое окно после завершения метода при щелчке PrimeFaces <p:commandButton>.

<p:commandButton id="viewButton" value="View"
    actionlistener="#{userBean.setResultsForSelectedRow}" ajax="false"
    update=":selectedRowValues"
    oncomplete="PF('selectedRowValuesDlg').show()">
</p:commandButton>
<p:dialog id="selectedRowValues" widgetVar="selectedRowValuesDlg" dynamic="true">
    <h:outputText value="#{userBean.selectedGroupName}" />
</p:dialog>

Когда я нажимаю на кнопку команды, метод прослушивания bean setResultsForSelectedRow выполняется правильно, но при завершении метода он не отображает диалоговое окно. Если я удалю actionlistener, появится диалоговое окно. Я не знаю, что происходит.

Каков порядок выполнения событий? Можно ли одновременно выполнять actionlistener и oncomplete?

Ответ 1

Не удалось, потому что вы использовали ajax="false". Это вызывает полный синхронный запрос, который, в свою очередь, вызывает полную перезагрузку страницы, в результате чего oncomplete никогда не запускается (обратите внимание, что все другие атрибуты, связанные с ajax, такие как process, onstart, onsuccess, onerror и update также не запускаются).

То, что это сработало, когда вы удалили actionListener, также невозможно. Он должен был потерпеть неудачу так же. Возможно, вы также удалили ajax="false" вдоль него, не понимая, что вы делаете. Удаление ajax="false" должно действительно достичь желаемого требования.


Также возможно одновременное выполнение actionlistener и oncomplete?

Нет. script может быть запущен только до или после прослушивателя действий. Вы можете использовать onclick для запуска script в момент щелчка. Вы можете использовать onstart для запуска script в момент отправки запроса ajax. Но они никогда не будут точно одновременно уволены. Последовательность выглядит следующим образом:

  • Пользователь нажимает кнопку на клиенте
  • onclick Выполняется код JavaScript
  • JavaScript готовит запрос ajax на основе process и текущего дерева HTML DOM
  • onstart Выполняется JavaScript-код
  • JavaScript отправляет запрос ajax от клиента к серверу
  • JSF получает запрос ajax
  • JSF обрабатывает жизненный цикл запроса в дереве компонентов JSF на основе process
  • actionListener Выполняется метод поддержки JSF bean
  • action Выполняется метод поддержки JSF bean
  • JSF готовит ответ ajax на основе update и текущего дерева компонентов JSF
  • JSF отправляет ответ ajax от сервера к клиенту
  • JavaScript возвращает ответ ajax
    • если статус ответа HTTP равен 200, onsuccess выполняется код JavaScript
    • else, если статус ответа HTTP равен 500, onerror выполняется код JavaScript
  • JavaScript выполняет update на основе ответа ajax и текущего дерева HTML DOM
  • oncomplete Выполняется код JavaScript

Обратите внимание, что update выполняется после actionListener, поэтому, если вы использовали onclick или onstart, чтобы показать это диалоговое окно, он может по-прежнему отображать старый контент вместо обновленного контента, что плохо для пользователя опыт. Тогда вам лучше использовать oncomplete, чтобы отобразить диалог. Также обратите внимание, что вам лучше использовать action вместо actionListener, когда вы намереваетесь выполнить бизнес-действие.

См. также:

Ответ 2

Мне просто нравится получать информацию, такую ​​как BalusC, здесь, и он достаточно любезен, чтобы помочь ТАК много людей с такой хорошей информацией, что я считаю его слова как евангелие, но я не мог использовать этот порядок событий для решения этого же вид сроков в моем проекте. Поскольку BalusC поставил большую общую ссылку здесь, что я даже добавил в закладки, я думал, что пожертвую свое решение для некоторых продвинутых вопросов времени в том же самом месте, так как оно также решит исходные вопросы по расписанию. Я надеюсь, что этот код поможет кому-то:

        <p:pickList id="formPickList" 
                    value="#{mediaDetail.availableMedia}" 
                    converter="MediaPicklistConverter" 
                    widgetVar="formsPicklistWidget" 
                    var="mediaFiles" 
                    itemLabel="#{mediaFiles.mediaTitle}" 
                    itemValue="#{mediaFiles}" >
            <f:facet name="sourceCaption">Available Media</f:facet>
            <f:facet name="targetCaption">Chosen Media</f:facet>
        </p:pickList>

        <p:commandButton id="viewStream_btn" 
                         value="Stream chosen media" 
                         icon="fa fa-download"
                         ajax="true"
                         action="#{mediaDetail.prepareStreams}"                                              
                         update=":streamDialogPanel"
                         oncomplete="PF('streamingDialog').show()"
                         styleClass="ui-priority-primary"
                         style="margin-top:5px" >
            <p:ajax process="formPickList"  />
        </p:commandButton>

Диалог находится в верхней части XHTML вне этой формы, и он имеет форму встроенного в диалоговом окне вместе с datatable, который содержит дополнительные команды для потоковой передачи мультимедиа, которые все должны быть загрунтованы и готовы к работе, когда диалог представлен. Вы можете использовать эту же методику, чтобы делать такие вещи, как загружать настроенные документы, которые необходимо подготовить, прежде чем они будут переданы на пользовательский компьютер с помощью кнопок fileDownload в диалоговом окне.

Как я уже сказал, это более сложный пример, но он поражает все точки вашей проблемы и мои. Когда нажата кнопка командной строки, результат сначала гарантирует, что резервная копия bean будет обновлена ​​с результатами pickList, а затем сообщите резервной копии bean для подготовки потоков для пользователя на основе их выбора в списке выбора, затем обновите элементы управления в динамическом диалоге с обновлением, затем отобразите диалоговое окно, готовое для того, чтобы пользователь начал передавать потоковое содержимое.

Уловкой для этого было использование порядка событий BalusC для основного CommandButton, а затем добавить бит <p:ajax process="formPickList" />, чтобы убедиться, что он был выполнен первым - потому что ничего не происходит правильно, если pickList не обновил поддержку bean сначала (что-то это не произошло для меня, прежде чем я добавил). Итак, да, этот commandButton сказывается, потому что вы можете воздействовать на предыдущие, ожидающие и текущие компоненты, а также на поддержку beans, но время, необходимое для их взаимосвязи, не всегда легко обрабатывать.

Счастливое кодирование!