如何实现点击Yes按钮后禁用Modal关闭直至Ajax完成?修改data属性无效

需求说明
- 首次弹出Modal时,可通过点击取消按钮、关闭标记按钮或点击Modal外部区域进行关闭;
- 点击Yes按钮后,在Ajax请求处理完成前,无法通过点击取消按钮、关闭标记按钮或点击Modal外部区域关闭Modal。
问题
我曾尝试在点击Yes按钮时通过JavaScript将data-backdrop改为static、data-keyboard改为false,但并未生效。请问该如何实现此功能?
实现方案
直接修改DOM的data-*属性不会生效,因为Modal初始化后,配置参数已存储在实例对象中,需要通过操作Modal实例来修改规则,同时禁用关闭按钮的交互。以下以Bootstrap 5为例给出实现代码:
1. 基础Modal结构
<div class="modal fade" id="confirmModal" tabindex="-1" aria-labelledby="confirmModalLabel" aria-hidden="true"> <div class="modal-dialog"> <div class="modal-content"> <div class="modal-header"> <h5 class="modal-title" id="confirmModalLabel">确认操作</h5> <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button> </div> <div class="modal-body"> 确定要执行此操作吗? </div> <div class="modal-footer"> <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">取消</button> <button type="button" class="btn btn-primary" id="yesBtn">Yes</button> </div> </div> </div> </div>
2. JavaScript逻辑
// 获取Modal实例及相关按钮 const confirmModal = new bootstrap.Modal(document.getElementById('confirmModal')); const yesBtn = document.getElementById('yesBtn'); const closeBtn = document.querySelector('.btn-close'); const cancelBtn = document.querySelector('.btn-secondary[data-bs-dismiss="modal"]'); yesBtn.addEventListener('click', function() { // 1. 禁用关闭按钮并移除关闭触发属性 closeBtn.disabled = true; cancelBtn.disabled = true; closeBtn.removeAttribute('data-bs-dismiss'); cancelBtn.removeAttribute('data-bs-dismiss'); // 2. 修改Modal配置,禁止外部点击和键盘关闭 confirmModal._config.backdrop = 'static'; confirmModal._config.keyboard = false; // 重新生成背景层使配置生效 if (confirmModal._backdrop) { confirmModal._backdrop.dispose(); confirmModal._backdrop = new bootstrap.Backdrop(confirmModal._element, { isVisible: true, isAnimated: confirmModal._config.animation }); } // 3. 执行Ajax请求 fetch('/your-api-endpoint', { method: 'POST', // 根据需求添加请求头、请求体等配置 }) .then(response => response.json()) .then(data => { // 请求成功后的业务处理,比如提示操作完成 console.log('操作执行成功'); }) .catch(error => { // 请求失败后的业务处理 console.error('操作执行失败:', error); }) .finally(() => { // 4. 请求完成后恢复所有设置 closeBtn.disabled = false; cancelBtn.disabled = false; closeBtn.setAttribute('data-bs-dismiss', 'modal'); cancelBtn.setAttribute('data-bs-dismiss', 'modal'); confirmModal._config.backdrop = true; confirmModal._config.keyboard = true; if (confirmModal._backdrop) { confirmModal._backdrop.dispose(); confirmModal._backdrop = new bootstrap.Backdrop(confirmModal._element, { isVisible: true, isAnimated: confirmModal._config.animation }); } // 可选:请求完成后关闭Modal confirmModal.hide(); }); });
关键说明
- Modal初始化后,
data-backdrop和data-keyboard仅作为初始配置,后续修改DOM属性不会触发实例更新,必须修改实例的_config并重新生成背景层。 - 移除关闭按钮的
data-bs-dismiss属性,避免用户通过键盘触发按钮的关闭逻辑。 - 在
finally块中恢复配置,确保无论请求成功或失败,Modal都能回到可正常关闭的状态。
如果使用jQuery版本的Bootstrap,逻辑类似,仅API调用方式不同:
$('#yesBtn').click(function() { const $modal = $('#confirmModal'); // 禁用关闭按钮 $('.btn-close, .btn-secondary[data-dismiss="modal"]').prop('disabled', true).removeAttr('data-dismiss'); // 更新Modal配置 $modal.modal({ backdrop: 'static', keyboard: false }); // 执行Ajax请求 $.ajax({ url: '/your-api-endpoint', method: 'POST' }) .done(function(data) { console.log('操作成功'); }) .fail(function(error) { console.error('操作失败'); }) .always(function() { // 恢复配置和按钮状态 $('.btn-close, .btn-secondary[data-dismiss="modal"]').prop('disabled', false).attr('data-dismiss', 'modal'); $modal.modal({ backdrop: true, keyboard: true }); $modal.modal('hide'); }); });
内容的提问来源于stack exchange,提问作者Donny Akhmad Septa Utama
相关产品推荐
相关产品推荐

