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
相关产品推荐
相关产品推荐

