You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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%}

错误原因

  1. 重复ID冲突:在{% for %}循环中,每个迭代都会生成id="address"和id="form_address",但HTML要求ID必须唯一,导致getElementById无法定位到正确的目标元素。
  2. innerHTML替换丢失元素:调用change_text()时,通过innerHTML完全替换了address容器的内容,原容器内的form_address元素被删除,后续点击按钮时该元素已不存在。
  3. 函数重复定义:循环内每次都会重新定义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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.03 13:40:43