JavaScript报错:document.getElementById(...) is null 问题求助
Django模板JS点击报错
document.getElementById(...) is null问题修复 问题描述
重构HTML页面后,点击“Ajouter l'adresse”触发form_add_address函数时,控制台报错:
Uncaught TypeError: document.getElementById(...) is null form_add_address http://0.0.0.0:9999/nb_database/05eafb35-74ca-53f1-b2e6-81c2ca97b0ee/:117 onclick http://0.0.0.0:9999/nb_database/05eafb35-74ca-53f1-b2e6-81c2ca97b0ee/:1
涉及的Django模板代码如下:
{% extends 'base.html' %} {% load static %} {% block content%} {% for post in dict_post %} <!-- PHOTO / ADRESSE / VENDEURS--> <div class="container"> <div class="d-flex align-items-center justify-content-center pav flex-wrap"> <div class="photo d-flex" onclick="location.href='{{ post.8 }}'"> </div> <div class="adresse d-flex" id="address"> <a class="adressetext" onclick="change_text()" >Obtenir l'adresse</a> <div id="form_address" style="display:none"> <form action="" method="post"> {% csrf_token %} {{ form }} </form> </div> </div> <div class="vendeurs d-flex flex-wrap"> </div> </div> </div> <script> function change_text(){ var address = "{{ post.6 }}"; if (address != "Inconnue pour le moment"){ address = address.split(' ').join("+") var google_address = "https://www.google.com/maps/search/?api=1&query=" + address console.log(google_address) document.getElementById("address").innerHTML = "<p class=\"addressfounded\"> {{ post.6 }} </p>" + "<a href=" + google_address + "> <p class=\" googlemapslink\"> Ouvrir sur Google maps </p> </a>" ; } else { document.getElementById("address").innerHTML = "<p class=\"unknowaddress\"> L'adresse est inconnue Voulez-vous la rajouter ? </p>" + "<a class=\"addaddress\" onclick=\"form_add_address()\" > Ajouter l'adresse </a>" ; } } function form_add_address(){ var displayed = document.getElementById("form_address").style.display; if(displayed == "none"){ document.getElementById("form_address").style.display = "block"; } } </script> {% endfor %} {% endblock%}
错误原因
- 重复ID冲突:在
{% for %}循环中,每个迭代都会生成id="address"和id="form_address",但HTML要求ID必须唯一,导致getElementById无法定位到正确的目标元素。 - innerHTML替换丢失元素:调用
change_text()时,通过innerHTML完全替换了address容器的内容,原容器内的form_address元素被删除,后续点击按钮时该元素已不存在。 - 函数重复定义:循环内每次都会重新定义
change_text()和form_add_address(),后面的函数会覆盖前面的,导致逻辑混乱。
修复方案
1. 生成唯一ID
利用循环的forloop.counter(或post的唯一字段如post.id)为每个元素生成唯一ID,避免冲突。
2. 避免完全替换容器内容
在change_text的else分支,将表单元素重新添加回容器,防止innerHTML替换导致元素丢失。
3. 函数移到循环外
将JS函数定义移到循环外部,仅定义一次,通过传递参数(如唯一ID)操作对应元素。
修复后完整代码
{% extends 'base.html' %} {% load static %} {% block content%} {% for post in dict_post %} <!-- PHOTO / ADRESSE / VENDEURS--> <div class="container"> <div class="d-flex align-items-center justify-content-center pav flex-wrap"> <div class="photo d-flex" onclick="location.href='{{ post.8 }}'"> </div> <div class="adresse d-flex" id="address-{{ forloop.counter }}"> <a class="adressetext" onclick="change_text({{ forloop.counter }}, '{{ post.6|escapejs }}')" >Obtenir l'adresse</a> <div id="form_address-{{ forloop.counter }}" style="display:none"> <form action="" method="post"> {% csrf_token %} {{ form }} </form> </div> </div> <div class="vendeurs d-flex flex-wrap"> </div> </div> </div> {% endfor %} <script> function change_text(counter, address){ const addressContainer = document.getElementById(`address-${counter}`); const formContainer = document.getElementById(`form_address-${counter}`); // 清空容器内容 addressContainer.innerHTML = ''; if (address !== "Inconnue pour le moment"){ const formattedAddress = address.split(' ').join("+"); const googleAddress = `https://www.google.com/maps/search/?api=1&query=${formattedAddress}`; addressContainer.innerHTML = ` <p class="addressfounded">${address}</p> <a href="${googleAddress}"> <p class="googlemapslink">Ouvrir sur Google maps</p> </a> `; } else { addressContainer.innerHTML = ` <p class="unknowaddress">L'adresse est inconnue Voulez-vous la rajouter ?</p> <a class="addaddress" onclick="form_add_address(${counter})">Ajouter l'adresse</a> `; // 将表单重新添加回容器 addressContainer.appendChild(formContainer); } } function form_add_address(counter){ const formContainer = document.getElementById(`form_address-${counter}`); if(formContainer.style.display === "none"){ formContainer.style.display = "block"; } } </script> {% endblock%}
关键修复点说明
- 使用
forloop.counter生成唯一ID,确保每个元素ID不重复。 - 函数接收
counter参数,精准定位当前循环的元素。 - 在else分支中,通过
appendChild把表单重新添加回容器,避免innerHTML替换导致元素丢失。 - 使用
escapejs过滤器处理post.6的内容,防止JavaScript字符串转义错误。 - 将script标签移到循环外部,避免函数重复定义覆盖。
内容的提问来源于stack exchange,提问作者L.S
相关产品推荐
相关产品推荐

