按下PrimeFaces p:commandButton时事件的执行顺序

39

我正在尝试执行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,它就可以显示对话框了。我不知道出了什么问题。

事件的执行顺序是什么?是否可能同时执行actionlisteneroncomplete


2
你在commandButton上明确设置了ajax=false,并尝试使用ajax update。这样是行不通的。尝试移除ajax=false,并在<p:commandButton/>上添加process=@this,同时你不能同时执行actionListeneroncomplete - SRy
感谢Chris的快速回复。我尝试使用process=@this,但它没有起作用。而且我无法同时执行actionListener和oncomplete,那么有其他方法可以使用吗? - Abhay
2个回答

152

由于您使用了ajax="false",导致操作失败。这将触发完整的同步请求,进而导致完整的页面重新加载,从而使oncomplete无法被触发(请注意,所有其他与ajax相关的属性,如processonstartonsuccessonerrorupdate也都不会被触发)。

如果您删除了actionListener后它仍然可以工作,这也是不可能的。它应该以相同的方式失败。也许您同时删除了ajax="false",而实际上并没有理解自己在做什么。确实,删除ajax="false"应该可以实现所需的要求。


同时执行actionlistener和oncomplete是否可能?

不可能。脚本只能在动作监听器之前或之后执行。您可以使用onclick在单击时触发脚本。您可以使用onstart在ajax请求即将发送时触发脚本。但是它们永远不会完全同时被触发。顺序如下:

  • 用户在客户端点击按钮
  • 执行onclick JavaScript代码
  • JavaScript根据process和当前HTML DOM树准备ajax请求
  • 执行onstart JavaScript代码
  • JavaScript从客户端向服务器发送ajax请求
  • JSF检索ajax请求
  • 根据process在JSF组件树上处理请求生命周期
  • 执行actionListener JSF后台bean方法
  • 执行action JSF后台bean方法
  • 基于update和当前JSF组件树,JSF准备ajax响应
  • 从服务器向客户端发送ajax响应
  • JavaScript检索ajax响应
如果HTTP响应状态为200,则执行onsuccess JavaScript代码,否则如果HTTP响应状态为500,则执行onerror JavaScript代码。JavaScript根据ajax响应和当前HTML DOM树执行update,然后执行oncomplete JavaScript代码。请注意,updateactionListener之后执行,因此如果您使用onclickonstart来显示对话框,则可能仍会显示旧内容而不是更新的内容,这会影响用户体验。在这种情况下,最好改用oncomplete来显示对话框。还要注意,当您打算执行业务操作时,最好使用action而不是actionListener。参见:了解PrimeFaces process/update和JSF f:ajax execute/render属性action和actionListener之间的区别

BalusC。是的,我已经删除了 ajax="false" 以及 actionListener,我忘记提到它了。是的,在 ajax 响应返回后,它会显示对话框。谢谢。 - Abhay
@ BalusC 因为 actionListener 在执行 action 前被执行,所以我想知道是否有可能打破这个顺序?让我解释一下,点击一个按钮会打开一个对话框 oncomplete="PF('dg').show()",但在打开此对话框之前,我想进行一个检查,如果失败了,我就不想打开这个对话框(不调用 oncomplete)。 - Rapster
这正是我们使用 RequestContext 所做的。我在想是否还有其他方法可以这样做。谢谢 @BalusC ;) - Rapster

10

我非常喜欢像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的顶部,不在此表单内,并且它具有自己的表单,其中嵌入了一个包含用于流式传输媒体的附加命令的数据表,这些命令在呈现对话框时都需要准备就绪。您可以使用相同的技术来下载需要预处理的定制文档,然后通过对话框中的fileDownload按钮将其流式传输到用户计算机上。
正如我所说,这是一个更复杂的例子,但它涵盖了您和我的所有要点。当单击命令按钮时,结果首先是确保支持bean已更新为pickList的结果,然后告诉支持bean根据用户在pickList中的选择准备流,然后使用更新更新动态对话框中的控件,然后显示对话框框已准备好供用户开始流式传输其内容。
其中的技巧是使用BalusC的主命令按钮事件顺序,然后添加<p:ajax process="formPickList" />以确保它首先执行-因为除非pickList首先更新支持bean(在我之前没有发生),否则没有任何事情会正确发生。所以,是的,该命令按钮非常出色,因为您可以影响先前、未决和当前组件以及后台bean-但有时很难掌握它们之间的时间关系。祝您编码愉快!

考虑到BalusC的回答让人无话可说,以及您的回答对我有所帮助,这里送上五个网络积分给您。 - Mindwin Remember Monica

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接