Primefaces <p:ajax event="blur">引发表单首次提交失效问题
问题根因
光标停留在输入框内直接点击提交按钮时,浏览器的事件触发顺序为:首先将焦点从输入框移走触发blur事件、其次触发按钮的click事件。由于PrimeFaces的Ajax默认采用串行队列执行机制,blur事件触发的异步请求会在队列中优先执行,执行过程中会打断尚未完成的按钮点击事件逻辑,导致第一次点击的提交动作被丢弃;等blur请求响应完成、输入框组件重新渲染后,第二次点击的提交动作才能正常触发。
可落地解决方案
- 方案1:利用
<p:ajax>内置的delay参数,延迟blur事件的请求发送时机
给输入框的blur Ajax配置增加delay="200"属性,意思是blur事件触发后等待200ms再发送Ajax请求。用户点击按钮引发blur事件后,blur的请求会先进入等待状态,这段时间内按钮的click事件可以优先完成提交逻辑,不会被未发出的blur请求抢占执行权,示例代码:<p:inputText value="#{bean.userInput}"> <p:ajax event="blur" update="@this" delay="200" /> </p:inputText> - 方案2:调整Ajax队列的冲突处理策略,优先保障提交类请求
编写拦截逻辑,当检测到blur事件的Ajax是因用户点击提交按钮引发时,自动取消blur请求,避免两类请求的执行冲突,示例脚本:// 页面内嵌入的脚本逻辑 faces.ajax.addOnEvent(function(data) { if(data.status !== 'begin') return; // 识别blur事件触发的输入框类Ajax请求 const sourceEl = document.getElementById(data.source.id); if(sourceEl.tagName === 'INPUT' && event.target.tagName === 'BUTTON' && event.target.type === 'submit') { // 终止未发出的blur请求,优先执行提交流程 faces.ajax.abort(data); } }); - 方案3:调整blur事件的触发逻辑,避免和按钮点击事件重叠
若业务场景允许,可将输入框原本绑定在blur上的校验、值更新逻辑,从blur事件触发调整为提交按钮的处理流程统一执行,移除独立的blur Ajax绑定,从根源上消除两个事件的执行冲突:<!-- 移除输入框上的blur ajax绑定 --> <p:inputText id="inputField" value="#{bean.userInput}"> <!-- 原<p:ajax event="blur" update="@this" /> 配置移除 --> </p:inputText> <p:commandButton value="提交" action="#{bean.submit}" process="@form" update="@form" /> - 方案4:开启blur请求的异步执行模式
PrimeFaces 10.0及以上版本支持<p:ajax>的async="true"配置,开启后blur的Ajax请求会异步执行,不阻塞主事件循环里的按钮点击逻辑,从执行机制上避免请求抢占:<p:inputText value="#{bean.userInput}"> <p:ajax event="blur" update="@this" async="true" /> </p:inputText>
内容的提问来源于stack exchange,提问作者Alessandro
相关产品推荐
相关产品推荐

