Primefaces 6.2:带p:fileDownload的commandButton实现禁用与下载兼容
问题:PrimeFaces 下载按钮实现点击禁用、完成后启用
现有PrimeFaces按钮组件,可正常下载文件,但需要实现点击后禁用按钮,文件下载完成后重新启用,避免重复点击:
<p:commandButton style="width: 186px" title="#{msg['menu.export.tab.column.download']}" ajax="false" rendered="#{fileExist and not fileNull}" styleClass="button -primary download-file -md -margin-right-25 push-20 icon-file-pdf -width-max-content"> <p:fileDownload value="#{employeeExport.getExportDataXLS(export)}"/> </p:commandButton>
尝试添加onclick和oncomplete后,因ajax=false导致oncomplete无法触发;改为ajax=true后,事件可触发但无法下载文件。
解决方案
方法一:利用同步请求的JS阻塞特性
由于ajax=false时,浏览器会发起同步HTTP请求,JS线程会被阻塞直到用户处理完下载对话框(保存/取消)。我们可以利用这个特性,在onclick中先禁用按钮,再通过setTimeout将启用按钮的代码放到事件队列末尾,确保下载完成后执行:
修改按钮的onclick属性:
<p:commandButton style="width: 186px" title="#{msg['menu.export.tab.column.download']}" ajax="false" rendered="#{fileExist and not fileNull}" styleClass="button -primary download-file -md -margin-right-25 push-20 icon-file-pdf -width-max-content" onclick="var btn = $(this); btn.addClass('disabled').prop('disabled', true); setTimeout(() => { btn.removeClass('disabled').prop('disabled', false); }, 0);"> <p:fileDownload value="#{employeeExport.getExportDataXLS(export)}"/> </p:commandButton>
方法二:监听窗口焦点事件(更可靠)
给按钮添加唯一ID,通过JS监听窗口焦点事件,确保下载完成后恢复按钮状态:
- 给按钮添加ID:
<p:commandButton id="downloadBtn" style="width: 186px" title="#{msg['menu.export.tab.column.download']}" ajax="false" rendered="#{fileExist and not fileNull}" styleClass="button -primary download-file -md -margin-right-25 push-20 icon-file-pdf -width-max-content"> <p:fileDownload value="#{employeeExport.getExportDataXLS(export)}"/> </p:commandButton>
- 添加页面脚本:
var isDownloading = false; // 点击按钮时禁用并标记下载状态 $('#downloadBtn').on('click', function() { isDownloading = true; $(this).addClass('disabled').prop('disabled', true); }); // 窗口重新获得焦点时,恢复按钮状态(用户处理完下载对话框后触发) $(window).on('focus', function() { if (isDownloading) { $('#downloadBtn').removeClass('disabled').prop('disabled', false); isDownloading = false; } });
方法三:结合PrimeFaces后端回调(需页面局部刷新)
如果允许页面局部刷新,可以使用ajax="true"配合p:remoteCommand,先触发禁用按钮,再通过后端生成文件并触发下载,最后在回调中启用按钮:
- 添加远程命令和按钮:
<!-- 远程命令:处理禁用按钮并触发下载 --> <p:remoteCommand name="triggerDownload" process="@this" onstart="$('downloadBtn').addClass('disabled').prop('disabled', true);" action="#{employeeExport.prepareExportDataXLS(export)}" oncomplete="$('downloadBtn').removeClass('disabled').prop('disabled', false);"/> <!-- 下载按钮:触发远程命令 --> <p:commandButton id="downloadBtn" style="width: 186px" title="#{msg['menu.export.tab.column.download']}" rendered="#{fileExist and not fileNull}" styleClass="button -primary download-file -md -margin-right-25 push-20 icon-file-pdf -width-max-content" onclick="triggerDownload(); return false;"> <p:fileDownload value="#{employeeExport.downloadData}"/> </p:commandButton>
- 后端Bean添加对应方法:
private StreamedContent downloadData; public void prepareExportDataXLS(ExportModel export) { // 生成文件流并赋值给downloadData this.downloadData = getExportDataXLS(export); } // getter方法 public StreamedContent getDownloadData() { return downloadData; }
内容的提问来源于stack exchange,提问作者mtmx
相关产品推荐
相关产品推荐

