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

如何让克隆表单中的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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.26 17:18:09