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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.07 17:15:08