Vaadin 8 Upload组件addSucceededListener时序问题:如何先弹确认再开文件选择窗
问题根源
你当前的逻辑顺序完全颠倒:addSucceededListener是Vaadin Upload组件的上传成功回调监听器,仅当用户选中文件、上传流程完全执行完成后才会触发,所以你写在这个监听器里的确认弹窗,必然会在选文件之后才弹出。
解决方案
你需要先拦截上传触发动作,完成确认后再唤起文件选择窗口,推荐用「自定义触发按钮+隐藏原生Upload」的方案实现,逻辑清晰且改动量小:
步骤1:修改前端模板
隐藏原生Upload组件,新增一个普通按钮作为上传触发入口:
<!-- 新增自定义触发按钮 --> <vaadin-button caption="Incarc INDICATORI" _id="customUploadBtn" :right></vaadin-button> <!-- 原生Upload加hidden隐藏,仅做文件接收能力 --> <vaadin-upload button-caption="Incarc INDICATORI " _id="cmdIncarcRaportInd" :right hidden></vaadin-upload>
步骤2:后端绑定自定义按钮的点击逻辑
把前置校验、确认弹窗逻辑移到自定义按钮的点击事件中,用户确认后用JS主动唤起隐藏的Upload的文件选择窗口:
// 给原生Upload设置固定ID,方便JS定位 getCmdIncarcRaportInd().setId("upload-indicatori"); // 自定义按钮点击逻辑 getCustomUploadBtn().addClickListener(event -> { int NR_Raport = 0; String WBL = getCheBL().getValue() ? "B" : "I"; if(raport != null) NR_Raport = Numeric.getValInt(raport.get("Nr. Raport")); // 前置校验报告编号 if (NR_Raport == 0) { Notification notif = new Notification("Atentie", "NR Raport incorect", Notification.Type.ERROR_MESSAGE); notif.setDelayMsec(-1); notif.show(Page.getCurrent()); return; } // 判断是否需要弹Base Line确认框 if(WBL.equals("B")) { ConfirmButton cd = new ConfirmButton("Confirmare"); cd.misWinTitle = "Atentie MIS"; cd.misWinText = "Incarcati valori Base Line ? Daca exista deja, cele vechi se vor rescrie cu valorile noi. CONFIRMATI BASE LINE (DA / NU) ?"; cd.misButOK = "DA"; cd.misButCancel = "NU"; cd.setOkAction(() -> { // 确认后主动触发文件选择窗口 Page.getCurrent().getJavaScript().execute("document.getElementById('upload-indicatori').querySelector('input[type=file]').click();"); }); cd.setCancelAction(() -> {}); cd.openInModalPopup(); } else { // 无需确认直接触发文件选择 Page.getCurrent().getJavaScript().execute("document.getElementById('upload-indicatori').querySelector('input[type=file]').click();"); } });
步骤3:简化原有SucceededListener逻辑
移除原来监听器里的前置校验、确认弹窗逻辑,仅保留上传完成后的业务处理代码即可:
getCmdIncarcRaportInd().addSucceededListener(event -> { String WBL = getCheBL().getValue() ? "B" : "I"; int NR_Raport = 0; if(raport != null) NR_Raport = Numeric.getValInt(raport.get("Nr. Raport")); int NR_RaportW = WBL.equals("B") ? 99 : NR_Raport; String raspuns = "ok"; // 校验文件名 if(!receiver.getFile().getName().split("_")[0].equals(proiect.get("Prj cod"))) { Notification notif = new Notification("Atentie", "Cod Proiect Incorect", Notification.Type.ERROR_MESSAGE); notif.setDelayMsec(-1); notif.show(Page.getCurrent()); return; } // 执行业务逻辑 try { if(WBL.equals("B")) { raspuns = Utility.getSomeData(receiver.getFile(), proiect, 99, themeDisplay); } else { raspuns = Utility.DoSomeStuff(receiver.getFile(), proiect, NR_RaportW, themeDisplay); } } catch (IOException | SQLException e) { raspuns = e.getMessage(); } // 结果通知+刷新表格 String notifyTitle = WBL.equals("B") ? "Atentie - Incarcare Base Line Indicatori" : "Atentie - Incarcare Rap Indicatori"; Notification notificare = new Notification(notifyTitle, raspuns, Notification.Type.ERROR_MESSAGE); notificare.setDelayMsec(-1); notificare.show(Page.getCurrent()); incarcGrdIndicatori(prj_cod); receiver.uploadFinished(event); });
内容的提问来源于stack exchange,提问作者Cristian Sfetcu
相关产品推荐
相关产品推荐

