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

Django表单集中克隆表单的Choice下拉框无法正常工作

解决Django动态表单中Materialize下拉框失效问题

问题背景

参照Stack Overflow指导在Django中实现动态克隆空表单,JavaScript可成功追加新表单,但Choice组件的下拉框无法正常交互。浏览器检查显示选项存在,但组件无响应。

模板代码

<form method="post"> {% csrf_token %}
  <div id="form_set">
  {{ FightForms.management_form|materializecss }}
  {% for form in FightForms %}
  <div class="card white darken-1 col m12">
    <table class='no_error'>
      {{ form.non_field_errors }}
      <row>
          <div class="col m3">
              <div class="fieldWrapper">
                  {{ form.guild_member_id|materializecss }}
              </div>
          </div>
      </row>
      {% for hidden in form.hidden_fields %}
          {{ hidden }}
      {% endfor %}
    </table>
  </div>
  {% endfor %}
</div>

  <div class="col m12">
    <div>
        <input class="btn light-blue lighten-1" type="button" value="Add More" id="add_more">
    </div>
    <br>
    <button class="btn light-blue lighten-1" type="submit">Submit Guild Members</button>
  </div>

  <div id="empty_form" style="display:none">
    <div class="card white darken-1 col m12">
      <table class='no_error'>
        {{ FightForms.empty_form.non_field_errors }}
        <row>
            <div class="col m3">
                <div class="fieldWrapper">
                    {{ FightForms.empty_form.guild_member_id|materializecss }}
                </div>
            </div>
        </row>
        {% for hidden in form.hidden_fields %}
            {{ hidden|materializecss }}
        {% endfor %}
      </table>
    </div>
  </div>
</form>

头部导入代码

<html lang="en">
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1.0"/>
    <title>League Chronicler</title>
    <link rel="shortcut icon" type="image/png" href="{% static 'img/CScroll.png' %}"/>

    <!-- CSS  -->
    <link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
    <link rel="stylesheet" href="{% static 'css/chronicler.css' %}" type="text/css" media="screen,projection"/>
    <link rel="stylesheet" href="//code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">


    {% block css %}
      <link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
      <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0/css/materialize.min.css">
      <link rel="stylesheet" href="//code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
    {% endblock css %}

    <!-- javascript -->
    <script src="https://code.jquery.com/jquery-3.6.0.min.js" integrity="sha256-/xUj+3OJU5yExlq6GSYGSHk7tPXikynS7ogEvDej/m4=" crossorigin="anonymous"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0/js/materialize.min.js"></script>
    <script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>

</head>

问题分析(更新说明)

实际问题出在JavaScript克隆逻辑:.html()方法读取#empty_form内容时,Materialize已将下拉框所需的ul元素移出原DOM结构,导致克隆的新表单没有ul元素,反而每次点击都会把ul追加到#empty_form中。点击3次添加按钮后,#empty_form会包含4个ul,新表单却无下拉选项。

解决方案

1. 修复模板中的隐藏字段循环

empty_form部分的隐藏字段循环变量错误,将form改为FightForms.empty_form:

{% for hidden in FightForms.empty_form.hidden_fields %}
    {{ hidden|materializecss }}
{% endfor %}

2. 修改JavaScript克隆逻辑

  • 页面加载时保存原始空表单的HTML,避免Materialize动态生成的ul干扰
  • 每次添加新表单后,重新初始化Materialize下拉组件

修改后的JS代码:

$(document).ready(function() {
    // 页面加载时立即保存原始空表单HTML,此时还未被Materialize修改
    const originalEmptyForm = $('#empty_form').html();

    $('#add_more').click(function() {
        const formIdx = $('#id_form-TOTAL_FORMS').val();
        // 使用原始HTML替换前缀,生成新表单
        const newFormHtml = originalEmptyForm.replace(/__prefix__/g, formIdx);
        // 将新表单添加到form_set容器
        const $newForm = $(newFormHtml).appendTo('#form_set');
        
        // 初始化新表单中的下拉框
        $newForm.find('select').formSelect();
        
        // 更新表单总数
        $('#id_form-TOTAL_FORMS').val(parseInt(formIdx) + 1);
    });

    // 初始化页面上已有的下拉框
    $('select').formSelect();
});

关键说明

  • 提前保存原始空表单HTML:Materialize初始化下拉框时会重构DOM,把ul元素移到其他位置,后续读取#empty_form的html会包含这些动态生成的元素,导致克隆出错。
  • 重新初始化下拉框:动态添加的DOM元素不会自动被Materialize识别,必须手动调用formSelect()激活下拉功能。

内容的提问来源于stack exchange,提问作者krewsayder

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.19 09:59:52