Rails 7.1引擎中tinymce-rails动态嵌套字段编辑器加载问题
解决Rails 7.1引擎中TinyMCE动态嵌套字段加载问题
核心思路
动态添加的嵌套字段属于DOM新增元素,<%= tinymce :try %>这类静态初始化只会执行一次,因此需要在新字段插入DOM后手动初始化TinyMCE实例。
具体实现步骤
1. 重构字段部分模板(_page_section_fields.html.erb)
移除模板内的<%= tinymce :try %>,改用普通textarea并添加统一类名tinymce-nested-field:
<div class="nested-fields"> <%= form.text_area :content, class: "tinymce-nested-field form-control" %> <!-- 其他字段内容 --> <%= link_to_remove_association "移除区段", form %> </div>
2. 编写通用TinyMCE初始化函数
在JavaScript文件(如app/javascript/controllers/tinymce_controller.js)中定义初始化逻辑:
import tinymce from 'tinymce/tinymce' import 'tinymce/themes/silver' // 按需导入所需插件 import 'tinymce/plugins/link' import 'tinymce/plugins/image' export function initTinyMCE(elementSelector) { tinymce.init({ selector: elementSelector, // 复制tinymce.yml中的配置项,示例如下: height: 500, plugins: ['link', 'image'], toolbar: 'undo redo | bold italic | link image', // 其他自定义配置 }) }
3. 绑定动态字段的初始化事件
根据你的嵌套字段实现方式(Cocoon或自定义逻辑),在新字段插入后触发初始化:
若使用Cocoon
监听Cocoon的插入/移除事件:
import { initTinyMCE } from '../controllers/tinymce_controller' document.addEventListener('turbo:load', () => { // 初始化页面已存在的textarea document.querySelectorAll('.tinymce-nested-field').forEach(el => { initTinyMCE(`#${el.id}`) }) // 动态添加字段后初始化编辑器 document.addEventListener('cocoon:after-insert', (e) => { const newTextarea = e.detail.item.querySelector('.tinymce-nested-field') if (newTextarea) { initTinyMCE(`#${newTextarea.id}`) } }) // 移除字段时销毁对应编辑器,避免内存泄漏 document.addEventListener('cocoon:after-remove', (e) => { const removedTextareaId = e.detail.item.querySelector('.tinymce-nested-field')?.id if (removedTextareaId) { tinymce.remove(`#${removedTextareaId}`) } }) })
若使用自定义添加逻辑
在插入新字段的代码后直接调用初始化函数:
import { initTinyMCE } from '../controllers/tinymce_controller' document.querySelector('.add-section-btn').addEventListener('click', (e) => { e.preventDefault() // 示例:通过AJAX获取字段模板并插入DOM fetch('/path/to/section/template') .then(res => res.text()) .then(html => { const container = document.querySelector('#page-sections-container') container.insertAdjacentHTML('beforeend', html) // 初始化新添加的textarea const newTextarea = container.lastElementChild.querySelector('.tinymce-nested-field') initTinyMCE(`#${newTextarea.id}`) }) })
4. 清理旧代码
删除视图中所有<%= tinymce :try %>相关的静态初始化代码,避免冲突。
关键注意点
- 确保每个textarea拥有唯一
id:Rails表单助手生成的textarea默认会生成如page_sections_0_content的唯一ID,无需额外处理 - 移除字段时销毁对应编辑器:防止内存泄漏
- 若使用Turbo,需在
turbo:load或turbo:render事件中重新初始化已有编辑器,避免页面刷新后失效
内容的提问来源于stack exchange,提问作者jamesc
相关产品推荐
相关产品推荐

