Rails UJS搭配form_with远程表单 如何中止提交后再正常提交避免循环
问题根源
死循环是因为调用Rails.fire(form, 'submit')触发表单提交时,Rails UJS会再次派发ajax:beforeSend事件,导致你的监听器逻辑被重复执行,不断触发确认弹窗。
可行解决方案
方案1:添加确认状态标记(最简单常用)
给表单添加一个自定义属性作为确认标记,用户确认后标记为已确认,再次触发ajax:beforeSend时直接放行,不阻止提交:
const form = document.getElementById('assign_sessions_to_employees') form.addEventListener( 'ajax:beforeSend', (event) => { // 已经确认过就直接放行,不阻止提交 if (form.dataset.confirmed) return // 未确认就阻止默认提交,弹出确认框 event.preventDefault() swal.fire({ title: 'Are you sure ?', text: `You are about to spend ${expectedExpenditure()} credits.`, showCancelButton: true, }).then((result) => { if (result.isConfirmed) { // 标记为已确认 form.dataset.confirmed = 'true' // 重新触发提交,此时下次触发ajax:beforeSend会直接放行 Rails.fire(form, 'submit') } }) } )
这个方案不需要修改原有事件绑定逻辑,改动最小,也不会影响表单其他提交相关的逻辑。
小提示:如果表单提交失败需要支持重新提交,可以额外绑定
ajax:error事件重置标记:form.addEventListener('ajax:error', () => { delete form.dataset.confirmed })如果表单提交后页面会刷新或者表单会被重置,也可以在对应逻辑里补充重置标记的代码,避免用户下次提交时不会触发确认。
方案2:使用一次性事件监听器
绑定事件的时候使用{ once: true }参数,让监听器只执行一次,用户确认后触发提交时不会再执行监听逻辑:
const form = document.getElementById('assign_sessions_to_employees') const confirmBeforeSubmit = (event) => { event.preventDefault() swal.fire({ title: 'Are you sure ?', text: `You are about to spend ${expectedExpenditure()} credits.`, showCancelButton: true, }).then((result) => { if (result.isConfirmed) { Rails.fire(form, 'submit') } else { // 用户取消的话,重新绑定监听器,方便下次提交时还能触发确认 form.addEventListener('ajax:beforeSend', confirmBeforeSubmit, { once: true }) } }) } // 首次绑定一次性监听器 form.addEventListener('ajax:beforeSend', confirmBeforeSubmit, { once: true })
内容的提问来源于stack exchange,提问作者David Geismar
相关产品推荐
相关产品推荐

