select2绑定DataTable操作列下拉框加载完成后失效问题
问题根因
- 回调名拼写错误:DataTable 表格重绘完成的回调参数是
drawCallback,你写的drawCollection不存在,所以重绘后重新初始化的逻辑根本没有触发 - 初始化时机错误:服务端模式下DataTable每次加载、排序、翻页、搜索都会销毁旧DOM重新渲染新节点,只在
fnInitComplete初始化一次select2,会在后续重绘时被新生成的原生select节点覆盖 - 重复初始化冲突:直接全局选择
.a_location元素初始化,会选中DataTable缓存中已移除的无效节点,且没有销毁已存在的select2实例,会导致渲染异常
修复方案
- 修正回调名称,将错误的
drawCollection替换为官方标准的drawCallback - 抽离select2初始化逻辑,每次重绘后只选中当前表格容器内的有效select节点做初始化
- 初始化前先销毁已存在的select2实例,避免重复初始化冲突
- 统一在DOM渲染稳定的时机执行初始化,避免加载过程中绑定的组件被新节点覆盖
修正后完整代码
t.tblHelpers = { actions: function () { return function (d) { return '<select name="approverName" value="' + d.id + '" id="location_' + d.id + '" class="a_location"></select>'; }; } }; t.dTbl = t.locationApproverTable.DataTable({ autoWidth: false, aoColumnDefs: [{ targets: 1, bSortable: true, render: t.tblHelpers.actions() }], order: [[0, 'asc']], processing: true, serverSide: true, ajax: { url: t.config.url.get_locations, type: "get", data: function(d) { d._token = t.getToken(); } }, columns: [ {data: 'a.text'}, {data: 'a.'} // 注意:此处字段未补全,需对应接口返回的实际字段名,否则会报渲染错误 ], fnInitComplete: function(oSettings, json) { var api = this.api(); var searchBox = '<div class="input-group table-search-btns">' +'<input type="text" class="form-control searchbox plain-search" placeholder="Press enter with search text" />' +'<span class="input-group-addon btn-searchbox" data-toggle="tooltip" data-placement="left" data-original-title="Search"><i class="ps-icon plain-search-icon"></i></span>' +'<span class="input-group-addon btn-reload-list" data-toggle="tooltip" data-placement="left" data-original-title="Refresh List"><i class="ps-icon fa fa-refresh"></i></span>' +'</div>'; // 首次加载完成初始化select2 initTableSelect2(api.table().container()); }, // 修正回调名,拼写错误是核心失效原因 drawCallback: function() { // 每次重绘完成后重新绑定,限定查找范围为当前表格容器,避免选中无效DOM initTableSelect2(this.api().table().container()); } }); /** * 初始化表格内的select2组件 * @param {HTMLElement} container 表格容器节点 */ function initTableSelect2(container) { $(container).find('select.a_location').each(function() { // 已初始化过的实例先销毁,避免重复初始化冲突 if ($(this).hasClass('select2-hidden-accessible')) { $(this).select2('destroy'); } // 初始化select2,可在此处扩展下拉数据源、占位符等配置 $(this).select2({ width: '100%' }); }); }
额外注意事项
- 不要在DataTable的
processing加载阶段初始化select2,此时DOM还在替换中,初始化后的组件会被新节点覆盖 - 如果需要加载可选用户列表,直接在select2的配置项中添加
data静态数据源或者ajax远程加载配置即可,无需提前全局填充 - 若后续需要给select绑定change事件,建议用事件委托的方式绑定到表格容器上,避免重绘后事件失效,写法参考:
$(t.locationApproverTable).on('change', 'select.a_location', function() { /* 业务逻辑 */ })
内容的提问来源于stack exchange,提问作者santosh
相关产品推荐
相关产品推荐

