如何让克隆表单中的Select2字段正常工作?
解决Select2表单克隆后无法正常筛选的问题
核心问题在于直接克隆已初始化Select2的DOM时,会连带克隆Select2生成的额外节点,导致新的下拉框无法正常工作。以下是完整的修复方案:
1. 保存干净的表单模板
页面加载时先保存原始未被Select2修改的表单HTML,作为克隆的模板:
let cleanFormTemplate; $(document).ready(function () { // 保存原始表单的干净HTML cleanFormTemplate = $('#formContainer').html(); // 初始化原表单的Select2并调整name属性为数组格式 initOriginalForm(); // 绑定添加航班按钮事件 $('#addFlightBtn').click(function(e) { e.preventDefault(); const newForm = createFlightForm(); $('#newForm').append(newForm); }); });
2. 初始化原始表单
修改原初始化逻辑,将表单控件的name改为数组格式(方便后端接收多条数据):
function initOriginalForm() { // 处理Aircraft下拉框 $('#aircraft').attr('name', 'aircraft[]'); // 初始化机场搜索Select2 searchAirports(".adep", "adep-"); searchAirports(".ades", "ades-"); } function searchAirports(className, idName) { $(className).each(function (index) { const id = `${idName}${index + 1}`; // 设置唯一ID和数组格式的name $(this).attr("id", id).attr('name', `${className.replace('.', '')}[]`); $(`#${id}`).select2({ ajax: { url: "/flight/search_airports", dataType: "json", data: function (params) { return { search_value: params.term, }; }, processResults: function (data) { return { results: $.map(data, function (obj) { return { text: `${obj.code} ${obj.name}`, id: obj.code, }; }), }; }, cache: true, }, minimumInputLength: 3, placeholder: gettext("Search for a airport"), theme: "classic", tags: true, templateSelection: function (obj) { return obj.id; }, allowClear: true, }); }); }
3. 修改表单克隆逻辑
使用干净模板创建新表单,为新控件分配唯一ID并重新初始化Select2:
function createFlightForm() { // 基于干净模板创建新表单 const newForm = $(`<div>${cleanFormTemplate}</div>`)[0]; // 创建并绑定移除按钮 const removeBtn = document.createElement("button"); removeBtn.classList.add("btn", "btn-danger", "mt-3"); removeBtn.textContent = "Remove"; removeBtn.addEventListener("click", () => { // 移除前销毁当前表单的Select2实例,避免内存泄漏 $(newForm).find('.adep, .ades').select2('destroy'); newForm.remove(); }); newForm.appendChild(removeBtn); // 初始化新表单的Select2控件 initNewFormControls(newForm); return newForm; } function initNewFormControls(formElement) { // 计算当前表单总数,生成唯一ID后缀 const formCount = $('#formContainer').length + $('#newForm > div').length; // 处理出发机场 const adepSelect = $(formElement).find('.adep'); const adepId = `adep-${formCount}`; adepSelect.attr('id', adepId).attr('name', 'adep[]'); initAirportSelect(adepSelect); // 处理到达机场 const adesSelect = $(formElement).find('.ades'); const adesId = `ades-${formCount}`; adesSelect.attr('id', adesId).attr('name', 'ades[]'); initAirportSelect(adesSelect); // 处理飞机选择框 const aircraftSelect = $(formElement).find('select[name="aircraft"]'); const aircraftId = `aircraft-${formCount}`; aircraftSelect.attr('id', aircraftId).attr('name', 'aircraft[]'); } // 复用Select2初始化逻辑 function initAirportSelect($select) { $select.select2({ ajax: { url: "/flight/search_airports", dataType: "json", data: function (params) { return { search_value: params.term, }; }, processResults: function (data) { return { results: $.map(data, function (obj) { return { text: `${obj.code} ${obj.name}`, id: obj.code, }; }), }; }, cache: true, }, minimumInputLength: 3, placeholder: gettext("Search for a airport"), theme: "classic", tags: true, templateSelection: function (obj) { return obj.id; }, allowClear: true, }); }
关键修复点
- 使用干净模板克隆:避免克隆Select2生成的额外DOM节点,确保新表单的select是原始状态
- 唯一ID分配:为每个新生成的select控件分配唯一ID,避免Select2初始化冲突
- 数组格式name:将表单控件的name改为
xxx[],后端可直接接收多条数据 - 销毁Select2实例:移除表单前销毁对应Select2实例,防止内存泄漏
内容的提问来源于stack exchange,提问作者Giorgio Scarso
相关产品推荐
相关产品推荐

