JSF:如何在commandLink的action与监听器执行后再显示dialog
问题
在PrimeFaces的dataTable中,通过commandLink结合ajax调用dialog时,点击行内的commandLink后,dialog会先显示,但f:setPropertyActionListener和commandLink的action方法要等到dialog显示后才执行,导致弹窗展示的是上一次点击的旧数据。需要实现dialog仅在这两个操作执行完成后再显示,且不通过Java代码调用dialog,也不直接将行数据传入dialog,必须先完成两个操作后再展示最新数据的弹窗。
原代码
<h:form id="form"> <p:outputPanel id="OPPanel"> <p:panel header="Panel Display"> <p:dataTable value="#{myBean.myDataList}" var="emp"> <p:column headerText="myData1"> <h:outputText value="#{emp.myData1}"/> </p:column> <p:column headerText="myData2"> <p:commandLink action="#{myActionClass.customizeData}" immediate="true"> <f:setPropertyActionListener value="#{emp.myData1}" target="#{myBean.myData1Str}" /> <p:ajax event="click" update=":form:OPDialog" oncomplete="PF('opDialogVar').show()"/> <h:outputText value="#{emp.myData2}"/> </p:commandLink> </p:column> </p:dataTable> </p:panel> </p:outputPanel> <p:dialog header="Custom Dialog Display" widgetVar="opDialogVar" modal="true" showEffect="fade" hideEffect="fade" resizable="false"> <p:outputPanel id="OPDialog" style="text-align:center;"> <p:panelGrid columns="2" columnClasses="label,value"> <h:outputText value="Customized Data:"/> <h:outputText value="#{myBean.myData1Str}"/> </p:panelGrid> </p:outputPanel> </p:dialog> </h:form>
补充说明
- 已知可在Java代码中调用dialog,但希望采用当前前端触发的方式
- 尝试过给
p:ajax添加process="@this"、global="false",无效果 - 不想直接将点击行的值传入dialog,需先完成
f:setPropertyActionListener赋值和customizeData方法执行,再显示含最新数据的dialog
解决方案
问题根源在于你在p:commandLink内部嵌套了p:ajax,这会导致两次独立请求:一次是commandLink本身的提交,一次是ajax请求,oncomplete绑定在ajax上,但commandLink的action和setPropertyActionListener是在commandLink的提交流程中执行,两者不同步。
修改步骤
- 移除
p:commandLink内部的p:ajax标签 - 直接在
p:commandLink上添加update、oncomplete属性,保留原有的action和f:setPropertyActionListener - 移除
immediate="true"(无特殊验证跳过需求时,该属性会打乱JSF生命周期,引发数据处理异常)
修改后的代码
<h:form id="form"> <p:outputPanel id="OPPanel"> <p:panel header="Panel Display"> <p:dataTable value="#{myBean.myDataList}" var="emp"> <p:column headerText="myData1"> <h:outputText value="#{emp.myData1}"/> </p:column> <p:column headerText="myData2"> <p:commandLink action="#{myActionClass.customizeData}" update=":form:OPDialog" oncomplete="PF('opDialogVar').show()"> <f:setPropertyActionListener value="#{emp.myData1}" target="#{myBean.myData1Str}" /> <h:outputText value="#{emp.myData2}"/> </p:commandLink> </p:column> </p:dataTable> </p:panel> </p:outputPanel> <p:dialog header="Custom Dialog Display" widgetVar="opDialogVar" modal="true" showEffect="fade" hideEffect="fade" resizable="false"> <p:outputPanel id="OPDialog" style="text-align:center;"> <p:panelGrid columns="2" columnClasses="label,value"> <h:outputText value="Customized Data:"/> <h:outputText value="#{myBean.myData1Str}"/> </p:panelGrid> </p:outputPanel> </p:dialog> </h:form>
原理说明
p:commandLink本身自带ajax提交能力,无需额外嵌套p:ajax- 将
update和oncomplete直接绑定在p:commandLink上,会严格遵循JSF生命周期:先执行f:setPropertyActionListener赋值,再执行customizeData方法完成后端数据处理,接着更新dialog的内容,最后在请求完全完成时触发oncomplete显示dialog,确保流程同步 - 若确实需要
immediate="true",请确认业务场景必须跳过验证阶段,否则建议移除,避免数据处理逻辑异常
内容的提问来源于stack exchange,提问作者satya prakash Panigrahi
相关产品推荐
相关产品推荐

