Summernote 编辑器不支持嵌套表单

Summernote editor not working with nested forms

我正在尝试在我的 ruby-on-rails 应用
这是我的模型:

class Dog < ApplicationRecord
    has_many :pictures, as: :imageable, dependent: :destroy
    accepts_nested_attributes_for :pictures, reject_if: :all_blank, allow_destroy: true
end

乍一看新建或编辑页面似乎还不错。第一个 summary 字段使用 summernote 正确渲染。如果我已经将几张照片保存到我的 dog 模型中,它们在编辑页面上看起来都非常好。 但是,当我单击 "add picture" 时,它会创建新的图片字段,其中 summary 字段无法使用 summernote 正确呈现。在 html 页面中,它看起来像这样:

<div class="field">
    <label class="string optional" for="dog_pictures_attributes_1544609860934_summary">Summary</label>
    <textarea data-provider="summernote" name="dog[pictures_attributes][1544609860934][summary]" id="dog_pictures_attributes_1544609860934_summary"></textarea>
</div>

而不是这个:

<div class="field">
    <label class="string optional" for="dog_pictures_attributes_1_summary">Summary</label>
    <textarea data-provider="summernote" name="dog[pictures_attributes][1][summary]" id="dog_pictures_attributes_1_summary" style="display: none;"></textarea>
    <div class="note-editor note-frame">...</div>
</div>

这是我的 _form.erb:(如果相关)

<%= simple_form_for @dog, defaults: { required: false } do |f| %>
  <div class="field">
    <%= f.label 'Note' %>
    <%= f.text_area :note, 'data-provider': :summernote %>
  </div>
  <h2> Add pictures </h2>
  <%= f.fields_for :pictures do |picture| %>
    <%= render 'picture_fields', :f => picture %>
  <% end %>
  <div class='links'>
    <%= link_to_add_association 'add picture', f, :pictures %>
  </div>
  <div class="actions">
    <%= f.submit %>
  </div>
<% end %>

这是我的_picture_fields.erb:

<div class='nested-fields'>
  <div class="field">
    <%= f.file_field :image %>
  </div>
  <div class="field">
    <%= f.label :author %>
    <%= f.text_field :author %>
  </div>
  <div class="field">
    <%= f.label :summary %>
    <%= f.text_area :summary, 'data-provider': :summernote %>
  </div>
    <%= link_to_remove_association "remove picture", f %>
</div>

我还尝试使用 drifting ruby 从头开始​​构建嵌套表单。但它会导致同样的问题

在页面中动态插入项目时,您还必须在这些项目上初始化 summernote 编辑器。 Cocoon 具有允许您执行此操作的回调。

加载页面时,要初始化 summernote,您可以执行类似

的操作
$('[data-provider="summernote"]').each ->
    $(this).summernote

(从summernote-rails gem文档中复制)

但这只适用于页面上已有的 "summernote",它不能初始化 还不存在的注释。

因此,在插入嵌套项目后,我们必须使用相同的代码来初始化插入的注释。这样的事情应该有效:

$('form').on('cocoon:after-insert', function(e, insertedItem) {
    insertedItem.find('[data-provider="summernote"]').each(function() {
      $(this).summernote();  
    })  
});

这将在新嵌套项目中查找 summernote 项目并初始化它们。

[编辑:改进 javascript 以从视图中提取它]

Javascript 文件通常分组在 app/assets/javascripts 中,如果您正在编辑 Dogs 让我们添加一个新文件 dogs.js 并输入以下代码:

$(document).on('cocoon:after-insert', 'form', function(e, insertedItem) {
    insertedItem.find('[data-provider="summernote"]').each(function() {
      $(this).summernote();  
    })  
});

然后使用 require dogs 将此文件添加到您的 application.js

此代码在文档上注册了一个事件处理程序,它将侦听在 form 上触发的任何 cocoon:after-insert 事件。如果您有多个使用 cocoon 的表单,您可能需要一个 better/more 精确的 css 选择器(例如,向表单添加一个 class 并将其也添加)。