调用ARES API的公司信息查询程序:动态加载模态框按钮点击无效问题求助(Uncaught TypeError: Cannot set property 'onclick' of null)
问题分析
你遇到的核心问题是动态生成的DOM元素无法直接绑定事件——页面初始加载时,tl_ares_vlozit按钮还不存在(是通过AJAX请求data.php后才插入到页面的),所以你尝试的document.getElementById("tl_ares_vlozit")会返回null,自然就抛出了Cannot set property 'onclick' of null的错误。另外,btn.onload的用法完全错误,btn是你的搜索按钮,它的onload事件不会监听动态内容的加载完成。
还有一个隐藏问题:你在data.php的循环中给每个按钮都设置了相同的id="tl_ares_vlozit",这违反了HTML中id必须唯一的规则,会导致后续选择元素时出现混乱,建议改成class来标识这些按钮。
解决方案:两种可行的实现方式
方式1:事件委托(推荐)
事件委托利用了事件冒泡的原理,将事件绑定到已经存在的父元素(比如模态框的内容容器#firma_pass,甚至document)上,当点击动态生成的按钮时,事件会冒泡到父元素,再判断点击的目标是否是我们需要的按钮。这种方式不需要关心元素何时被创建,适合动态内容场景。
修改步骤:
- 先修改
data.php中的按钮,把id改成class:
<button type="button" class="tl_ares_vlozit" name="tl_ares_vlozit">Vložit do formuláře</button>
- 然后修改
handler.js,删除原来的btn.onload代码块,替换成事件委托的代码:
// 事件委托:绑定到模态框内容容器,监听按钮点击 document.getElementById('firma_pass').addEventListener('click', function(e) { // 判断点击的元素是否是目标按钮 if (e.target.classList.contains('tl_ares_vlozit')) { // 找到当前按钮所在的父容器(.obal_radku_ares),避免多个公司数据冲突 const parentRow = e.target.closest('.obal_radku_ares'); // 从当前行中获取公司信息 const hodnota_firma = parentRow.querySelector('.div_fakturacni_firma').textContent; const hodnota_ico = parentRow.querySelector('.div_fakturacni_ico').textContent; // 填充到表单(注意jQuery选择器要加.,因为prvek_fakturacni_firma是class) $(".prvek_fakturacni_firma").val(hodnota_firma); // 若有地址信息,可对应填充到地址输入框,这里示例用ICO代替,你可按需调整 $("#firma-adresa").val(hodnota_ico); // 关闭模态框 modal.style.display = "none"; console.log("按钮已点击,信息已填充"); } });
方式2:AJAX回调完成后绑定事件
另一种方式是在AJAX请求成功、动态内容插入到页面后,立即给新生成的按钮绑定点击事件。这种方式适合内容较少、不需要频繁更新的场景。
修改handler.js中的ajaxStranka函数:
function ajaxStranka(something) { var xmlhttp = new XMLHttpRequest(); console.log( "sending " + something ); xmlhttp.open('GET', "data.php?id=" + something, true); xmlhttp.send(); xmlhttp.onreadystatechange = function() { if (this.readyState == 4 && this.status == 200) { dataResponse = this.responseText; console.log( "given back " + dataResponse ); $("#firma_pass").html(dataResponse); // 动态内容插入完成后,给按钮绑定事件 // 需先修改data.php的按钮为class="tl_ares_vlozit" document.querySelectorAll('.tl_ares_vlozit').forEach(btn => { btn.onclick = function() { const parentRow = this.closest('.obal_radku_ares'); const hodnota_firma = parentRow.querySelector('.div_fakturacni_firma').textContent; const hodnota_ico = parentRow.querySelector('.div_fakturacni_ico').textContent; $(".prvek_fakturacni_firma").val(hodnota_firma); $("#firma-adresa").val(hodnota_ico); modal.style.display = "none"; } }); } }; }
额外的小问题修复
- 你的jQuery选择器
$("prvek_fakturacni_firma")缺少了.(因为它是class选择器),应该改成$(".prvek_fakturacni_firma")。 - 如果每个公司条目都有对应的地址信息,记得在
data.php中输出地址字段,并在填充表单时对应到#firma-adresa输入框。
内容的提问来源于stack exchange,提问作者DatZiggyZig
相关产品推荐
相关产品推荐

