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

时间:2013-11-22 13:57:44

标签: jsf jsf-2 primefaces action 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,则会显示对话框。我不知道出了什么问题。

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

2 个答案:

答案 0 :(得分:120)

失败是因为您使用了ajax="false"。这会触发一个完整的同步请求,从而导致整页重新加载,导致oncomplete永远不会被触发(请注意所有其他与ajax相关的属性,如processonstart,{{ 1}},onsuccessonerror也永远不会被解雇。)

当您删除update时,它的工作原理也是不可能的。它应该以同样的方式失败。也许您还沿着它删除了actionListener而没有真正了解您在做什么。删除ajax="false"确实应该达到预期的要求。


  

还可以同时执行actionlistener和oncomplete吗?

没有。该脚本只能在之前或在动作侦听器之后触发。您可以使用ajax="false"在点击时触发脚本。您可以使用onclick在即将发送ajax请求时触发脚本。但他们永远不会同时被解雇。顺序如下:

  • 用户点击客户端中的按钮
  • onstart执行JavaScript代码
  • JavaScript根据onclick和当前的HTML DOM树
  • 准备ajax请求
  • process执行JavaScript代码
  • JavaScript从客户端向服务器发送ajax请求
  • JSF检索ajax请求
  • JSF基于onstart
  • 处理JSF组件树上的请求生命周期
  • process执行JSF支持bean方法
  • actionListener执行JSF支持bean方法
  • JSF根据action和当前的JSF组件树
  • 准备ajax响应
  • JSF从服务器向客户端发送ajax响应
  • JavaScript检索ajax响应
    • 如果HTTP响应状态为200,则执行update JavaScript代码
    • 如果HTTP响应状态为500,则执行onsuccess JavaScript代码
  • JavaScript根据ajax响应和当前的HTML DOM树执行onerror
  • update执行JavaScript代码

请注意oncomplete update后执行,因此如果您使用actionListeneronclick来显示对话框,那么可能仍然显示旧内容而不是更新内容,这对用户体验来说很差。然后,您最好使用onstart来显示对话框。另请注意,当您打算执行业务操作时,最好使用oncomplete而不是action

另见:

答案 1 :(得分:8)

我只是喜欢获得像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按钮将这些文档传输到用户的计算机。

正如我所说,这是一个更复杂的例子,但它会触及你的问题和我的所有高点。单击命令按钮时,结果是首先确保使用pickList的结果更新辅助bean,然后告诉辅助bean根据用户在选择列表中的选择为用户准备流,然后更新控件带有更新的动态对话框,然后显示准备好用户开始流式传输其内容的对话框。

它的诀窍是对主命令按钮使用BalusC的事件顺序,然后添加<p:ajax process="formPickList" />位以确保它首先被执行 - 因为除非pickList更新了支持,否则没有任何正确的事情发生bean first(在添加之前我没有发生过的事情)。所以,是的,那个命令按钮因为你可以影响以前的,待定的和当前的组件以及支持bean而摇滚 - 但是有时候相互关联所有这些组件的时机并不容易处理。

快乐的编码!