Google Sheets模态框提交表单后HTML清空问题求助
问题排查与修复方案
需求目标
- 点击Google表格模态框表单的提交按钮后,显示加载动画,延迟1.5秒后通过
google.script.host.close()关闭弹窗 - 保留表单原生验证功能
当前问题
点击提交按钮后,模态框内容立即清空,仅留下空HTML结构:
<html> <head> <meta http-equiv="X-UA-Compatible" content="IE=edge"> </head> <body></body> </html>
弹窗需手动关闭,提交事件处理函数未触发(console.log无输出),预期代码未执行。
过往尝试与已做操作
- 曾用普通按钮
onclick实现功能,但无法触发表单验证 - 已尝试在提交事件中添加
event.preventDefault(),问题仍未解决
代码片段
JavaScript
var x; let ID = t => document.getElementById(t); var loader = ID('loader'); document.addEventListener("DOMContentLoaded", () => { loader.style.visibility = 'visible'; google.script.run.withSuccessHandler(res => { x = res.arr[1]; google.script.run.callLibraryFunction('CharacterSheetCode.clearClassEdit'); switch (res.arr[0]) { case 'edit': ID('class').value = res.arr[2].class; ID('subclass').value = res.arr[2].subclass; ID('level').value = res.arr[2].level; ID('hitdie').value = res.arr[2].hitdie; ID('spellcasting').value = res.arr[2].spells; makeEditable(); break; case 'add': makeEditable(); break; } function makeEditable() { ID('class').readOnly = false; ID('subclass').readOnly = false; ID('level').readOnly = false; ID('level').max = (20 - res.lvl) + (res.arr[2] ? Number(res.arr[2].level) : 0); ID('hitdie').readOnly = false; ID('spellcasting').readOnly = false; ID('addedit').disabled = false; ID('remove').disabled = false; loader.style.visibility = 'hidden'; } }) .callLibraryFunction("CharacterSheetCode.getClassInfo"); }); ID("form").addEventListener("submit", e => { e.preventDefault(); loader.style.visibility = 'visible'; var className = ID('class').value, subclass = ID('subclass').value, level = ID('level').value, hitdie = ID('hitdie').value, spells = ID('spellcasting').value; if (hitdie % 2 == 0 && hitdie >= 6 && hitdie <= 12) { setTimeout(() => google.script.host.close(), 1500); google.script.run.callLibraryFunction("CharacterSheetCode.addEditInfo", [className.trim(), subclass.trim(), level, hitdie, spells, x]); } else { alert(`Error: You must use a d6, d8, d10, or d12 as a hit die. A d${hitdie} will not be accepted.`); loader.style.visibility = 'hidden'; } } function removeClass() { loader.style.visibility = 'visible'; setTimeout(() => google.script.host.close(), 1500); google.script.run.callLibraryFunction("CharacterSheetCode.addEditInfo", ['', '', '', '', '', x]); }
CSS
.container { background-color: white; padding: 15px; height: 200px; width: 300px; font-family: Georgia; color: black; font-size: 15px; position: absolute; top: 50%; left: 50%; -ms-transform: translate(-50%, -50%); transform: translate(-50%, -50%); text-align: center; } input { border-radius: 1em; text-align: center; font-family: Georgia; font-size: 15px; } select { border-radius: 1em; font-family: Georgia; font-size: 15px; } button { border-radius: 1em; font-family: Georgia; font-size: 15px; } button:active { filter: brightness(80%); } .loader { border: 5px solid #f3f3f3; border-radius: 50%; border-top: 5px solid #3498db; border-bottom: 5px solid #3498db; position: absolute; top: calc(50% - 30px); left: calc(50% - 30px); width: 50px; height: 50px; z-index: 10; animation: spin 2s linear infinite; } @keyframes spin { 0% { transform: rotate(0deg); } 100% { transform: rotate(360deg); } }
HTML
<div id="loader" class="loader" style="visibility: hidden;"></div> <div id="container" class="container"> <form id="form"> <label for="class">Class</label> <input type="text" id="class" required readonly="readonly"><br> <label for="subclass">Subclass</label> <input type="text" id="subclass" readonly="readonly"><br> <label for="level">Level</label> <input type="number" id="level" style="width: 50px;" min="1" max="20" required readonly="readonly" onkeypress="return event.charCode >= 48 && event.charCode <= 57"> <label for="hitdie">Hit Die: d</label> <input type="number" id="hitdie" style="width: 50px" min="6" max="12" step="2" required readonly="readonly" onkeypress="return event.charCode >= 48 && event.charCode <= 57"><br> <label for="spellcasting">Spellcasting:</label> <select id="spellcasting" readonly="readonly"> <option>None</option> <option>Full</option> <option>Half</option> <option>Third</option> <option>Pact</option> </select><br> <button id="addedit" type="submit" disabled>Add/Edit</button><br> <button id="remove" onclick="removeClass()" disabled>Remove Class</button> <div>Note: The process of updating the sheet can sometimes take up to 20-40 seconds.</div> </form> </div>
问题原因分析
- JavaScript语法错误:提交事件监听函数末尾缺少闭合括号
),导致JS解析失败,整个脚本中断执行。浏览器遇到语法错误时会停止执行后续代码,包括event.preventDefault(),表单会默认提交,导致模态框内容被清空。 - 元素获取时机问题:
var loader = ID('loader');在DOMContentLoaded事件前执行,此时DOM可能尚未完全加载,loader可能为null,后续操作会报错。
修复方案
1. 修复语法错误
在提交事件监听函数末尾添加闭合括号:
ID("form").addEventListener("submit", e => { e.preventDefault(); loader.style.visibility = 'visible'; var className = ID('class').value, subclass = ID('subclass').value, level = ID('level').value, hitdie = ID('hitdie').value, spells = ID('spellcasting').value; if (hitdie % 2 == 0 && hitdie >= 6 && hitdie <= 12) { setTimeout(() => google.script.host.close(), 1500); google.script.run.callLibraryFunction("CharacterSheetCode.addEditInfo", [className.trim(), subclass.trim(), level, hitdie, spells, x]); } else { alert(`Error: You must use a d6, d8, d10, or d12 as a hit die. A d${hitdie} will not be accepted.`); loader.style.visibility = 'hidden'; } }); // 添加闭合括号
2. 调整元素获取时机
将loader的获取逻辑移到DOMContentLoaded事件内部,确保DOM加载完成后再获取元素:
document.addEventListener("DOMContentLoaded", () => { var loader = ID('loader'); // 移到事件内部 loader.style.visibility = 'visible'; // 后续代码保持不变 });
3. 优化表单提交逻辑(可选)
为避免google.script.run异步操作未完成就关闭弹窗,建议在addEditInfo执行成功后再触发关闭:
if (hitdie % 2 == 0 && hitdie >= 6 && hitdie <= 12) { loader.style.visibility = 'visible'; google.script.run .withSuccessHandler(() => { setTimeout(() => google.script.host.close(), 1500); }) .callLibraryFunction("CharacterSheetCode.addEditInfo", [className.trim(), subclass.trim(), level, hitdie, spells, x]); }
4. 修复removeClass函数的潜在问题
在函数内部获取loader元素,确保DOM已加载:
function removeClass() { var loader = ID('loader'); loader.style.visibility = 'visible'; google.script.run .withSuccessHandler(() => { setTimeout(() => google.script.host.close(), 1500); }) .callLibraryFunction("CharacterSheetCode.addEditInfo", ['', '', '', '', '', x]); }
内容的提问来源于stack exchange,提问作者Ben Craven
相关产品推荐
相关产品推荐

