如果您在对话框中输入了文件,取消文件选择会以某种方式关闭对话框。为什么会发生这种情况,如何预防?
<dialog open>
<input type="file">
</dialog>
编辑:
该对话框在 Firefox 中保持打开状态(如预期)。该对话框在 Chrome 中关闭(意外)。
我实际上也遇到了完全相同的问题。我怀疑这是由于当用户取消文件选择时输入触发
cancel
事件引起的。这个 cancel
事件冒泡到对话框中,它错误地认为它是针对自己的,因此过早关闭。这个问题似乎只出现在 Chromium 浏览器中,因为正如您提到的,这种行为在 Firefox 中不会发生。
发生这种情况时,会触发对话框的
cancel
事件,但该事件具有输入目标。这对于检测对话框是否即将提前关闭非常有用,并以布尔变量的形式引发标志。
const dialog = document.getElementById("dialog");
let prematurelyClosed = false;
dialog.addEventListener("cancel", (e) => {
if(e.target !== dialog)
prematurelyClosed = true;
// or simply prematurelyClosed = e.target !== dialog
})
这样,当对话框的
close
事件被调用时,我们可以检查标志是否被提升。如果是,我们就知道该对话框是在不应该关闭的情况下关闭的,并阻止它。然而,似乎“防止”它的唯一方法是来自 @underflow 的答案,我们需要立即重新打开模式。除此之外我还没有找到任何其他方法。至少使用此方法,我们只需要在这种特定情况下重新打开它,并在其他所有情况下正确关闭它,例如用户按下 Esc 或者按钮调用 dialog.close()
。
dialog.addEventListener("close", (e) => {
if(prematurelyClosed){
dialog.showModal();
prematurelyClosed = false;
}
})
所以最后,我最终解决了我的问题,希望可以帮助你。
const dialog = document.getElementById("dialog");
let prematurelyClosed = false;
dialog.addEventListener("cancel", (e) => {
if(e.target !== dialog)
prematurelyClosed = true;
// or simply prematurelyClosed = e.target !== dialog
})
dialog.addEventListener("close", (e) => {
if(prematurelyClosed){
dialog.show();
prematurelyClosed = false;
}
})
<dialog open id="dialog">
<input type="file">
<button onclick="dialog.close()">Close</button>
</dialog>
找到了一种在单击取消或Esc
后保持对话框/模式打开的好方法const dialog = document.getElementById("dialog");
dialog.addEventListener('close', (e) => {
dialog.showModal();
});
const closeButton = document.querySelector(".close");
closeButton.addEventListener("click", () => {
dialog.style.display = "none";
});
<dialog id="dialog" open>
<input type="file" />
<button class="close">Close</button>
</dialog>
在这种特定情况下,手动关闭模式的最佳方法是通过 CSS。
我在开发的 Angular 应用程序中也遇到了同样的问题。本质上,来自输入的取消事件正在冒泡到调用组件。我通过在输入组件上使用主机侦听器来侦听并停止将事件传播到我的其他组件来解决这个问题。
@HostListener('cancel', ['$event'])
onCancel(event: Event){
console.log('Cancel host listener.');
event.stopImmediatePropagation();
};