首页 > 解决方案 > Rails + Javascript:同时创建一个父模型和多个子模型

问题描述

我有一个父模型(纸)和一个嵌套的子模型(磁带),并且想在不使用任何宝石的情况下同时创建多个子模型。磁带的输入字段应通过单击“+”来动态添加。

如果我在控制器中写“3.times { @paper.tapes.build }”,我可以同时创建 1 个纸和 3 个磁带。但是如果输入字段应该添加多少次取决于用户(如果用户点击“+”10次,一次保存1个父模型和10个子模型),我应该如何修改代码?

这是我的代码。纸模型

has_many :tapes
accepts_nested_attributes_for :tapes, allow_destroy: true

磁带模型

belongs_to :paper, optional: true

控制器

def new
    @paper = Paper.new
    3.times { @paper.tapes.build }
end

def create
  @paper = Paper.new(paper_params)
  @paper.user_id = current_user.id
  if @paper.save
    redirect_to action_list_paper_path(@paper.id)
  else
    render 'new'
  end
end

查看器

<%= nested_form_for(@paper) do |f| %>
 <div class="container">
<%= stylesheet_link_tag 'papers', media: 'all', 'data-turbolinks-track': 'reload' %>
  <div class= "paper_form">
    <div class="col-md-6">
      <%= f.label(:content, "Name") %>
      <%= f.text_area :content %>
    </div>
   </div>
 </div>

 <div class="tape_form">
   <%= f.fields_for :tapes do |tape| %>
    <div id="input_pluralBox">
      <div id="input_plural">
        <div class="col-md-4">
         <%= tape.label :label %>
         <%= tape.text_field :label %>
        </div>
      </div>
      <input type="button" value="+&quot; class="add pluralBtn">
      <input type="button" value="-&quot; class="del pluralBtn">
    </div>
  </div>
 <% end %>
 </div>
</div>
<% end %>

Javascript(输入栏“标签”将通过javascript添加“+”)。

<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script type="text/javascript">
$(document).on("click", ".add", function() {
    $(this).parent().clone(true).insertAfter($(this).parent());
});
$(document).on("click", ".del", function() {
    var target = $(this).parent();
    if (target.parent().children().length > 1) {
        target.remove();
    }
});
</script>

标签: javascriptruby-on-railsrubyaccepts-nested-attributes

解决方案


如何在表单中添加嵌套记录的示例:

    <%= form.fields_for :headers, get_headers(client) do |builder| %>
      <div>
        <div class="header-fields form-row">
          <%= builder.hidden_field :id %>
          <div class="form-group col col-md-4">
            <%= builder.label :key %>
            <%= builder.text_field :key, class: 'form-control' %>
          </div>
          <div class="form-group col col-md-6">
            <%= builder.label :value %>
            <%= builder.text_field :value, class: 'form-control', value: builder.object.value %>
          </div>
          
          <% if action_name == "edit" %>
          <div class="form-group col col-md-2">
            <div class="form-check">
              <%= builder.check_box :_destroy, class: 'form-check-input' %>
              <%= builder.label :_destroy, "Destroy?", class: 'form-check-label' %>
            </div>
          </div>
          <% end %>
        </div>
      </div>
    <% end %>

辅助函数

def get_headers(client)
  return client.headers if client.headers.any?
  [Header.new]
end

控制器参数

def client_params
  params.require(:client).permit(headers_attributes: [:id, :key, :value, :_destroy])
end

模型:

class Client < ApplicationRecord
  has_many :headers, dependent: :destroy
  accepts_nested_attributes_for :headers, allow_destroy: true
end

然后 JS 根据需要添加/删除行。


推荐阅读