引入active_admin/select2后ActiveAdmin has_many表单重复问题求助
这事儿我之前在项目里碰到过!大概率是Select2重复初始化或者ActiveAdmin has_many组件与Select2的DOM处理逻辑冲突导致的,具体拆解JS层面的核心原因:
重复初始化引发DOM克隆异常
ActiveAdmin的has_many表单是靠动态克隆现有DOM元素来生成新行的。如果你在active_admin.js里引入active_admin/select2,再加上application.js里可能已经有Select2的初始化逻辑(或者ActiveAdmin本身内置了Select2的基础初始化),就会让同一个select控件被多次初始化Select2。当has_many克隆DOM时,已经被Select2改造过的元素会带着它生成的额外DOM结构(比如下拉框的容器、样式节点)一起被复制,最终就出现了重复的表单行或Select2控件。事件监听重复绑定
Select2初始化时会给目标DOM绑定一系列事件(比如点击、值变更),而ActiveAdmin的has_many组件也会监听添加/删除行的自定义事件。如果两次引入Select2相关代码,会导致这些事件监听被重复绑定。当触发添加新行操作时,重复的监听会多次执行克隆和初始化逻辑,直接造成表单行重复出现。版本/代码重复加载冲突
ActiveAdmin本身已经集成了适配它的Select2版本(在核心JS文件里),如果你手动在active_admin.js里再引入active_admin/select2,相当于把同一段初始化逻辑加载了两次。这会导致Select2的全局变量、初始化函数被重复定义,进而在处理has_many动态表单时,执行了两次初始化流程,生成重复的DOM节点。
- 先检查
javascript/application.js里有没有单独引入Select2,如果有就删掉,只用ActiveAdmin内置的版本即可 - 如果必须手动引入Select2,确保只在一个入口文件里加载
active_admin/select2,并且借助ActiveAdmin的自定义事件来初始化新行的Select2控件:$(document).on('has_many_add:after', function(e, fieldset) { // 只初始化当前新增行里的select控件 $(fieldset).find('select:not(.select2-initialized)').addClass('select2-initialized').select2(); }); - 或者给已初始化的Select2控件加标记,避免重复初始化:在初始化前判断控件是否有
select2-initialized类,没有才执行初始化逻辑
内容的提问来源于stack exchange,提问作者ViachMoz

