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

如何动态使用Tom-select?克隆行组件失效问题排查与解决

问题描述

在模态框的表格中嵌入Tom-select输入组件,添加按钮用于新增该行,但点击按钮克隆包含Tom-select的行后,新行中的Tom-select无法正常工作,相关代码如下,如何实现Tom-select的动态初始化?

原代码

模态框渲染代码

// show modal : 
this.show = function(){
    var main = this;
    var items= main.items;
    var modalTitle = "modalTitle";
    var modalMsg = ' <div id="modal-id">';
    modalMsg    += '    <table id = "MyTable" class="table">';
    modalMsg    += '        <tbody>';
    modalMsg    += '            <tr>';
    modalMsg    += '                <th class="col-xs-3"> 25125211  : </th>';
    modalMsg    += '                <td class="col-xs-9"><label class="col-xs-3"><input type="radio" class="input-val" name="confirm_radio" id="approve" value="100" required>apporve</label>';
    modalMsg    += '                <label class="col-xs-3"><input name="confirm_radio" id="refer" type="radio" value="900" required>refer</label></td>';
    modalMsg    += '            </tr>';
    modalMsg    += '            <tr id = "tomselect-tr">';
    modalMsg    += '                <th class="col-xs-3"> chooseTomselectOption </th>';
    modalMsg    += '                <td>';
    modalMsg    += '                   <div class="input-group"><select id="TomSelect_1" placeholder="choose an item..."></select><span class="input-group-btn"><button id="cloneTr" type="button"  class="btn btn-tool"><i class="fa fa-plus"></i></button></span></div>';
    modalMsg    += '                </td>';
    modalMsg    += '            </tr>';       
    modalMsg    += '        </tbody>';
    modalMsg    += '    </table>';
    modalMsg    += ' </div>';
    var modalBtn1Text = "done";
    var modalBtn2Text = "cancel";
    var modalCallback;

    var updateCallback = function(){
        agreementInfo.saveInfo();
    };
    modalCallback = updateCallback;

    this.modal = new _modal.show(modalTitle
        ,modalMsg
        ,modalBtn1Text
        ,modalBtn2Text
        ,modalCallback
    );
}

克隆行函数

// cloneTr function :
function cloneTr(){
    trNum++;
    var $newTr= $("#tomselect-tr").clone();     
    $newTr.attr("id", "tomselect-tr"+trNum);
    $newTr.find("#TomSelect_1").attr("id","TomSelect_"+trNum);
    $("#MyTable").find("tbody").find("#tomselect-tr").after($newTr);
    var targetDiv = "TomSelect_"+trNum;
    addSelector(targetDiv);
}

Tom-select初始化函数

// addSelector function
function addSelector(_targetDiv){
    var selector = new TomSelect("#"+_targetDiv,{
        valueField: 'USR_NO',
        searchField: ['USR_NM', 'USR_ID', 'USR_EMAIL', 'GP_NM'],
        maxItems: 1,
        maxOptions: 100,
        options: items,
        render: {
            option: function(data, escape) {
                console.log(escape);
                return  '<div>' +
                    '   <span class="USR_NM">' + escape(data.USR_NM) + '</span>' +
                    '   <span class="GP_NM">' + escape(data.GP_NM) + '</span>' +
                    '   <span class="USR_ID">' + escape(data.USR_ID) + '</span>' +
                    '   <span class="USR_EMAIL">'  + escape(data.USR_EMAIL) + '</span>' +
                    '</div>';
            },
            item: function(data, escape) {
                return  '<div id="'+itemDivTxt+'" title="' + escape(data.USR_NO) + '" data-name="' + escape(data.USR_NM) + '">' +
                    '   <span class="tom-select-name">' + escape(data.USR_NM) + '</span>' +
                    '   <span class="tom-select-group">' + escape(data.GP_NM) + '</span>' +
                    '</div>';
            }
        }
    });
    selector.clearCache();
}

问题根源

克隆已初始化Tom-select的行时,原始<select>元素已经被Tom-select替换成了自定义的DOM结构(包含div、input等),克隆出来的不是真正的<select>,自然无法被Tom-select重新初始化。另外代码中itemDivTxt变量未定义,也会导致初始化报错。

解决方案

1. 保存原始select模板

在初始化第一个Tom-select前,保存原始<select>的HTML结构作为模板,避免克隆已被修改的DOM:

this.show = function(){
    var main = this;
    var items= main.items;
    var modalTitle = "modalTitle";
    var modalMsg = ' <div id="modal-id">';
    modalMsg    += '    <table id = "MyTable" class="table">';
    modalMsg    += '        <tbody>';
    modalMsg    += '            <tr>';
    modalMsg    += '                <th class="col-xs-3"> 25125211  : </th>';
    modalMsg    += '                <td class="col-xs-9"><label class="col-xs-3"><input type="radio" class="input-val" name="confirm_radio" id="approve" value="100" required>apporve</label>';
    modalMsg    += '                <label class="col-xs-3"><input name="confirm_radio" id="refer" type="radio" value="900" required>refer</label></td>';
    modalMsg    += '            </tr>';
    modalMsg    += '            <tr id = "tomselect-tr">';
    modalMsg    += '                <th class="col-xs-3"> chooseTomselectOption </th>';
    modalMsg    += '                <td>';
    modalMsg    += '                   <div class="input-group"><select id="TomSelect_1" placeholder="choose an item..."></select><span class="input-group-btn"><button type="button" class="btn btn-tool clone-btn"><i class="fa fa-plus"></i></button></span></div>';
    modalMsg    += '                </td>';
    modalMsg    += '            </tr>';       
    modalMsg    += '        </tbody>';
    modalMsg    += '    </table>';
    modalMsg    += ' </div>';
    var modalBtn1Text = "done";
    var modalBtn2Text = "cancel";
    var modalCallback;

    var updateCallback = function(){
        agreementInfo.saveInfo();
    };
    modalCallback = updateCallback;

    this.modal = new _modal.show(modalTitle, modalMsg, modalBtn1Text, modalBtn2Text, modalCallback);

    // 保存原始select的HTML作为模板,并初始化第一个Tom-select
    const originalSelectHtml = $("#TomSelect_1").prop('outerHTML');
    window.tomSelectTemplate = originalSelectHtml;
    addSelector("TomSelect_1");

    // 绑定第一个克隆按钮的点击事件
    $(".clone-btn").on("click", cloneTr);
}

2. 修改克隆逻辑,基于模板创建新行

不再克隆已初始化的行,而是用模板生成新的<select>元素,确保每次初始化的都是原始的select:

// 初始化trNum为1,确保新行ID从2开始
let trNum = 1;

function cloneTr(){
    trNum++;
    // 克隆原始行结构
    const $newTr = $("#tomselect-tr").clone();
    $newTr.attr("id", `tomselect-tr${trNum}`);

    // 用模板生成新的select,替换行内的select容器内容
    const newSelectHtml = window.tomSelectTemplate.replace(/TomSelect_1/g, `TomSelect_${trNum}`);
    $newTr.find(".input-group").html(newSelectHtml + '<span class="input-group-btn"><button type="button" class="btn btn-tool clone-btn"><i class="fa fa-plus"></i></button></span>');

    // 添加新行到表格
    $("#MyTable tbody").append($newTr);

    // 初始化新的Tom-select
    addSelector(`TomSelect_${trNum}`);

    // 给新的克隆按钮绑定事件
    $newTr.find(".clone-btn").on("click", cloneTr);
}

3. 修复Tom-select初始化函数的报错

移除未定义的itemDivTxt变量,改用DOM元素直接初始化Tom-select(比选择器字符串更可靠):

function addSelector(_targetDiv){
    const $select = $("#" + _targetDiv);
    // 确保目标select存在
    if (!$select.length) return;

    var selector = new TomSelect($select[0], {
        valueField: 'USR_NO',
        searchField: ['USR_NM', 'USR_ID', 'USR_EMAIL', 'GP_NM'],
        maxItems: 1,
        maxOptions: 100,
        options: items,
        render: {
            option: function(data, escape) {
                return  '<div>' +
                    '   <span class="USR_NM">' + escape(data.USR_NM) + '</span>' +
                    '   <span class="GP_NM">' + escape(data.GP_NM) + '</span>' +
                    '   <span class="USR_ID">' + escape(data.USR_ID) + '</span>' +
                    '   <span class="USR_EMAIL">'  + escape(data.USR_EMAIL) + '</span>' +
                    '</div>';
            },
            item: function(data, escape) {
                // 移除未定义的itemDivTxt,保留必要的属性
                return  '<div title="' + escape(data.USR_NO) + '" data-name="' + escape(data.USR_NM) + '">' +
                    '   <span class="tom-select-name">' + escape(data.USR_NM) + '</span>' +
                    '   <span class="tom-select-group">' + escape(data.GP_NM) + '</span>' +
                    '</div>';
            }
        }
    });
    selector.clearCache();
}

内容的提问来源于stack exchange,提问作者강성빈

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.07 12:15:31