如何阻止Material Web组件mdc-dialog的[确定]按钮自动关闭弹窗?
阻止MDC Dialog确定按钮自动关闭的解决方案
问题背景
我使用HTML、JavaScript及Webpack构建了基于Material Design Components的Web应用,页面中使用mdc-dialog组件作为数据输入弹窗。弹窗的mdc-dialog__actions区域包含「取消」和「确定」按钮,我为「确定」按钮添加了自定义CSS类,用于在保存前自定义验证数据:若输入数据未通过验证,将弹出错误提示弹窗,同时主输入弹窗保持显示。但实际运行时,点击「确定」按钮后主输入弹窗会自动关闭。
相关代码
HTML代码
<div class="dialog-add-userpass mdc-dialog mdc-dialog--fullscreen"> <div class="mdc-dialog__container"> <div class="mdc-dialog__surface" role="dialog" aria-modal="true" aria-labelledby="my-dialog-title" aria-describedby="my-dialog-content"> <div class="mdc-dialog__header"> <h2 class="mdc-dialog__title" id="my-dialog-title">Add new User-Pass</h2> <button class="mdc-icon-button material-icons mdc-dialog__close" data-mdc-dialog-action="close">close</button> </div> <div class="mdc-dialog__content" id="my-dialog-content"> <label class="txt-new-pass-no mdc-text-field mdc-text-field--outlined w-100p"> <span class="mdc-notched-outline"> <span class="mdc-notched-outline__leading"></span> <span class="mdc-notched-outline__notch"> <span class="mdc-floating-label" id="lbl-pass-no">Pass No.</span> </span> <span class="mdc-notched-outline__trailing"></span> </span> <input type="text" class="mdc-text-field__input" aria-labelledby="lbl-pass-no" aria-controls="pass-no-help" aria-describedby="pass-no-help" id="inputPassNo" required minlength="4"> </label> <!-- 省略其他表单内容 --> <div class="mdc-dialog__actions"> <button type="button" class="mdc-button mdc-dialog__button" data-mdc-dialog-action="cancel"> <div class="mdc-button__ripple"></div> <span class="mdc-button__label">Cancel</span> </button> <button type="button" class="btn-add-save mdc-button mdc-dialog__button" data-mdc-dialog-action="ok"> <div class="mdc-button__ripple"></div> <span class="mdc-button__label">Add new</span> </button> </div> </div> </div> </div> <div class="mdc-dialog__scrim"></div> </div>
JavaScript代码
import { MDCDialog } from '@material/dialog'; const dialogAddUserPass = new MDCDialog(document.querySelector('.dialog-add-userpass')); dialogAddUserPass.scrimClickAction = ""; dialogAddUserPass.escapeKeyAction = ""; // 省略其他初始化代码 const btnAddSave = document.querySelector(".btn-add-save"); btnAddSave.addEventListener('click', async (e) => { e.preventDefault(); txtPassNo.value = txtPassNo.value.trim(); txtPassCode.value = txtPassCode.value.trim(); txtEmail.value = txtEmail.value.trim(); txtFullName.value = txtFullName.value.trim(); // 省略验证逻辑 } else { displayDialogMessage(validAddNew.message); dialogAddUserPass.open(); } });
解决方案
方案一:移除自动关闭触发属性
MDC Dialog会自动为带有data-mdc-dialog-action属性的按钮绑定关闭逻辑,直接移除「确定」按钮的该属性,即可阻止自动关闭,之后在验证通过时手动调用关闭方法。
- 修改HTML中的确定按钮:
<button type="button" class="btn-add-save mdc-button mdc-dialog__button"> <div class="mdc-button__ripple"></div> <span class="mdc-button__label">Add new</span> </button>
- 修改JavaScript点击事件,验证通过后手动关闭弹窗:
const btnAddSave = document.querySelector(".btn-add-save"); btnAddSave.addEventListener('click', async (e) => { e.preventDefault(); txtPassNo.value = txtPassNo.value.trim(); txtPassCode.value = txtPassCode.value.trim(); txtEmail.value = txtEmail.value.trim(); txtFullName.value = txtFullName.value.trim(); // 执行自定义验证 if (validAddNew.isValid) { // 这里添加保存数据的逻辑 await saveUserPassData(); // 验证通过,手动关闭弹窗 dialogAddUserPass.close(); } else { displayDialogMessage(validAddNew.message); // 弹窗不会自动关闭,无需再次调用open() } });
方案二:监听关闭事件并拦截
如果需要保留data-mdc-dialog-action属性,可以通过监听MDCDialog:closing事件,在验证不通过时阻止默认关闭行为。
修改JavaScript代码,添加事件监听:
import { MDCDialog } from '@material/dialog'; const dialogAddUserPass = new MDCDialog(document.querySelector('.dialog-add-userpass')); dialogAddUserPass.scrimClickAction = ""; dialogAddUserPass.escapeKeyAction = ""; // 监听弹窗关闭前的事件 dialogAddUserPass.listen('MDCDialog:closing', (event) => { // 判断是否是点击了确定按钮,且验证不通过 if (event.detail.action === 'ok' && !validAddNew.isValid) { // 阻止弹窗关闭 event.preventDefault(); // 显示错误提示 displayDialogMessage(validAddNew.message); } }); // 原有点击事件可以保留,专注于数据处理 const btnAddSave = document.querySelector(".btn-add-save"); btnAddSave.addEventListener('click', async (e) => { e.preventDefault(); txtPassNo.value = txtPassNo.value.trim(); txtPassCode.value = txtPassCode.value.trim(); txtEmail.value = txtEmail.value.trim(); txtFullName.value = txtFullName.value.trim(); // 执行自定义验证逻辑,更新validAddNew状态 validAddNew = validateUserPassData(); });
内容的提问来源于stack exchange,提问作者Jatu Tung
相关产品推荐
相关产品推荐

