Angular Material Dialog打开时如何禁用背景页面所有控件及快捷键操作
Angular Material v7 Dialog 弹窗打开时背景页快捷键冲突解决方案
问题表现
使用v7版本Angular Material Dialog时,若弹窗与底层背景页同时存在textarea、文本输入框等可编辑控件时,按下ctrl+z等快捷键会同时触发弹窗和背景页的撤销操作。
冲突的核心原因是浏览器的撤销操作栈绑定到当前获取焦点的可编辑元素,若背景页元素能获取焦点时,就会同步触发撤销操作,限制焦点后即可解决绝大多数这类问题。
解决方案
方案1:使用Dialog内置焦点捕获配置(优先推荐)
Angular Material Dialog v7已内置焦点限制能力,打开弹窗时添加以下配置即可让背景页控件无法获取焦点,从根源避免快捷键触发背景页操作:
import { MatDialog } from '@angular/material/dialog'; // 弹窗调用逻辑 constructor(private dialog: MatDialog) {} openDialog() { const dialogRef = this.dialog.open(你的弹窗组件名, { width: '300px', data: {/* 你的自定义传参 */}, // 核心配置项 autoFocus: true, // 弹窗打开后自动聚焦到弹窗内第一个可交互元素 trapFocus: true, // 强制锁定焦点仅能在弹窗内部移动,无法切换到背景页元素 }); }
方案2:手动禁用背景页可编辑控件(兜底方案)
如果内置配置不符合你的业务场景(比如需要保留背景页视觉可点击但不允许快捷键操作,可以在弹窗打开时统一禁用背景页可编辑控件,弹窗关闭后恢复:
// 全局变量存储原始控件状态 let originElementStates = []; const editableSelectors = 'textarea, input, [contenteditable="true"]'; openDialog() { // 先存储背景页可编辑控件的原始状态 originElementStates = Array.from(document.querySelectorAll(editableSelectors)).map(el => { return { element: el, disabled: el.disabled, contentEditable: el.getAttribute('contenteditable') } }); // 禁用所有背景页可编辑元素 document.querySelectorAll(editableSelectors).forEach(el => { el.disabled = true; el.setAttribute('contenteditable', 'false'); }); const dialogRef = this.dialog.open(你的弹窗组件名, { // 你的自定义弹窗配置 }); // 弹窗关闭后恢复所有控件原始状态 dialogRef.afterClosed().subscribe(() => { originElementStates.forEach(item => { item.element.disabled = item.disabled; item.element.setAttribute('contenteditable', item.contentEditable); }) }) }
内容的提问来源于stack exchange,提问作者Rams。
相关产品推荐
相关产品推荐

