如何基于动态Bootstrap Tags Input实现标签组合与同步更新?
需求说明
页面包含一个静态Bootstrap Tags Input,同时支持新增多个动态Bootstrap Tags Input:
- 静态输入框添加标签(如「Black」),表格生成对应标签的行
- 任意动态输入框添加标签(如「26」),表格生成静态标签与所有动态标签的全组合行(如「Black 26」「Black M」等)
- 移除任意标签时,表格对应行同步删除
- 原代码仅支持2个输入框,需扩展为支持任意数量动态输入框
修改后的实现代码
HTML
<!-- 静态标签输入框 --> <input type="text" name="attr[0][tags]" class="form-control static-tag-input" data-role="tagsinput" /> <!-- 动态标签输入容器 --> <div class="dynamic-tags-container"> <!-- 初始动态输入框 --> <input type="text" name="attr[1][tags]" class="form-control dynamic-tag-input" data-role="tagsinput" /> </div> <!-- 新增动态输入框按钮 --> <button type="button" class="btn btn-primary add-dynamic-tag">新增标签输入框</button> <!-- 标签组合表格 --> <table class="table"> <tbody class="tbl-body"></tbody> </table>
jQuery
// 存储所有标签组:索引0是静态标签,后续是各动态输入框的标签 let tagGroups = [[]]; // 初始化现有输入框的标签监听 initTagListeners('.static-tag-input', 0); initTagListeners('.dynamic-tag-input', 1); // 新增动态输入框按钮事件 $('.add-dynamic-tag').on('click', function() { const index = tagGroups.length; const newInput = $(`<input type="text" name="attr[${index}][tags]" class="form-control dynamic-tag-input" data-role="tagsinput" />`); $('.dynamic-tags-container').append(newInput); // 初始化新输入框的tagsinput和监听 newInput.tagsinput(); initTagListeners(newInput, index); // 新增空标签组 tagGroups.push([]); }); // 初始化标签输入框的添加/移除监听 function initTagListeners(selector, groupIndex) { $(document).on('itemAdded', selector, function(e) { const tag = e.item.trim(); if (tag && !tagGroups[groupIndex].includes(tag)) { tagGroups[groupIndex].push(tag); refreshTable(); } }); $(document).on('itemRemoved', selector, function(e) { const tag = e.item.trim(); const tagIndex = tagGroups[groupIndex].indexOf(tag); if (tagIndex !== -1) { tagGroups[groupIndex].splice(tagIndex, 1); refreshTable(); } }); } // 生成所有标签的全组合 function generateAllCombinations(groups) { if (groups.length === 0) return []; // 从第一个组开始,逐步和后续组做笛卡尔积 let combinations = groups[0].map(tag => [tag]); for (let i = 1; i < groups.length; i++) { const currentGroup = groups[i]; if (currentGroup.length === 0) continue; // 临时存储新组合 const temp = []; // 现有组合和当前组标签逐一组合 combinations.forEach(comb => { currentGroup.forEach(tag => { temp.push([...comb, tag]); }); }); combinations = temp; } // 将数组形式的组合转为空格分隔的字符串 return combinations.map(comb => comb.join(' ')); } // 刷新表格内容 function refreshTable() { const combinations = generateAllCombinations(tagGroups); // 清空现有表格行 $('.tbl-body').empty(); // 生成新行 combinations.forEach(comb => { const row = `<tr><td>${comb}</td></tr>`; $('.tbl-body').append(row); }); }
关键实现点
- 标签组管理:用数组
tagGroups统一存储所有输入框的标签,索引0对应静态输入框,后续索引对应各动态输入框,方便扩展 - 动态输入框初始化:新增动态输入框时自动初始化
tagsinput并绑定事件,同时在tagGroups中新增对应空数组 - 全量刷新逻辑:不管是添加还是删除标签,都重新计算所有标签的笛卡尔积组合,清空表格后重新渲染,避免单独处理行删除的复杂逻辑,保证数据一致性
- 通用组合生成:通过循环嵌套实现任意数量标签组的笛卡尔积计算,支持无限扩展动态输入框数量
内容的提问来源于stack exchange,提问作者Sam S
相关产品推荐
相关产品推荐

