【问题标题】:Dynamically generating three levels deep nested forms in Rails在 Rails 中动态生成三层深层嵌套表单
【发布时间】:2017-03-06 05:45:29
【问题描述】:

我正在尝试使用示例 laid out in this question. 创建一个具有动态生成内容的深度嵌套表单但是,当我尝试将其进行超过一层时,我遇到了问题,因为内容生成在第一个生成的表单,当我尝试从第二级生成的内容添加字段时,什么也没有发生。

简化模型布局,

Task
  has_one VendorUpload
    has_many VendorShippingLogs
      has_many VendorShippingLogProducts

供应商运输日志产品是我卡住的地方,因为该表单试图在其自身动态生成的供应商运输日志内容中生成其内容,并且我不确定如何将其编码到它自己的帮助程序中。附上代码,

模型 -->

class Task < ApplicationRecord
  has_one :vendor_upload, :dependent => :destroy
  has_many :vendor_shipping_logs, :through => :vendor_upload
  has_many :vendor_shipping_log_products, :through => :vendor_shipping_logs

  accepts_nested_attributes_for :vendor_upload, :reject_if => :upload_type_blank, :allow_destroy => true

end

class VendorUpload < ApplicationRecord

  belongs_to :task
  has_many :vendor_shipping_logs, inverse_of: :vendor_upload, :dependent => :destroy
  has_many :vendor_shipping_log_products, :through => :vendor_shipping_logs

  accepts_nested_attributes_for :vendor_shipping_logs

end

class VendorShippingLog < ApplicationRecord

  belongs_to :vendor_upload
  has_many :vendor_shipping_log_products, inverse_of: :vendor_shipping_log, :dependent => :destroy

  accepts_nested_attributes_for :vendor_shipping_log_products

end

class VendorShippingLogProduct < ApplicationRecord

  belongs_to :vendor_shipping_log

end

tasks_controller.rb

def new
  @task = Task.new
  @task.build_vendor_upload.vendor_shipping_logs.build.vendor_shipping_log_products.build

end
private
  def task_params
    params.require(:task).permit!
  end

application_helper.rb -->

  def new_child_fields_template(form_builder, association, options = {})
    options[:object] ||= form_builder.object.class.reflect_on_association(association).klass.new
    options[:partial] ||= association.to_s.singularize
    options[:form_builder_local] ||= :f

    content_for :jstemplates do
      content_tag(:div, :id => "#{association}_fields_template", :style => "display: none") do
        form_builder.fields_for(association, options[:object], :child_index => "new_#{association}") do |f|
          render(:partial => options[:partial], :locals => { options[:form_builder_local] => f })
        end
      end
    end
  end

  def add_child_link(name, association)
    link_to(name, "javascript:void(0)", :class => "add_child btn btn-success btn-sm fa fa-plus-circle", :style => "margin-left: 15px;margin-top: 15px;", :"data-association" => association)
  end

  def remove_child_link(name, f)
    f.hidden_field(:_destroy) + link_to(name, "javascript:void(0)", :style => "height: 30px; margin-left: 5px;", :class => "remove_child btn btn-danger fa fa-close")
  end

new.html.erb -->

<%= form_for @task, url: tasks_path, method: :post, :html => {:multipart => true } do |f| %>
  <%= f.fields_for :vendor_upload do |ff| %>
    <%= ff.fields_for :vendor_shipping_logs do |fff| %>
      <%= render "vendor_shipping_log", :f => fff %>
    <% end %>
    <p><%= add_child_link " Add Customer", :vendor_shipping_logs %></p>
    <%= new_child_fields_template f, :vendor_shipping_logs %>
  <% end %>
<% end %>
<div id="jstemplates">
  <%= yield :jstemplates %>
</div>

_vendor_shipping_log.html.erb -->

<%= f.fields_for :vendor_shipping_log_products do |ff| %>
  <%= render "vendor_shipping_log_product", :f => ff %>
<% end %>
<%= new_child_fields_template f, :vendor_shipping_log_products %>
<p><%= add_child_link " Add Product", :vendor_shipping_log_products %></p>

<%= remove_child_link "", f %>

_vendor_shipping_log_product.html.erb -->

<div class="fields">
  <div class="form-group form-group-sm">
    <%= f.label :item_id, "Item ID:", class: 'col-sm-3 control-label' %>
    <div class="col-sm-9">
      <div style="display: inline-flex;">
        <%= f.text_field :item_id, class: "form-control" %>
      </div>
    </div>
  </div>
  <%= remove_child_link "", f %>
</div>

application.js -->

$(function() {
  $('a.add_child').click(function() {
    var association = $(this).attr('data-association');
    var template = $('#' + association + '_fields_template').html();
    var regexp = new RegExp('new_' + association, 'g');
    var new_id = new Date().getTime();
    $(this).parent().before(template.replace(regexp, new_id));
    $()
    return false;
  });
});
$(function(){
  $(document).on("click", 'a.remove_child', function() {
    var hidden_field = $(this).prev('input[type=hidden]')[0];
    if(hidden_field) {
      hidden_field.value = '1';
    }
    $(this).parents('.fields').hide();
    return false;
  });
});

这里的代码基本上模仿了示例中的所有内容,并且对于一级深层嵌套属性可以正常工作,但除此之外的任何内容都无法正常工作。尝试单击上面代码中的“添加产品”按钮时,我没有收到任何反馈。

我希望我在这里将所有内容都清楚地列出,因为作为新手很难解释。将不胜感激任何点在正确的方向!

【问题讨论】:

    标签: javascript ruby-on-rails


    【解决方案1】:

    这可能值得一试:

    $(function() {
      $(document).on('click', 'a.add_child', function() {
        var association, new_id, regexp, template;
        association = $(this).attr('data-association');
        template = $('#' + association + '_fields_template').html();
        regexp = new RegExp('new_' + association, 'g');
        new_id = (new Date).getTime();
        $(this).parent().before(template.replace(regexp, new_id));
        $();
        return false;
      });
    });
    

    jQuery 中的普通click 事件不会绑定到动态生成的内容。你应该使用on。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2010-11-16
      • 1970-01-01
      • 1970-01-01
      • 2011-08-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-01-12
      相关资源
      最近更新 更多