动态添加&任意次数地删除表单中相同的新字段

Dynamically add & remove new but the same fields of a form any amount times

本文关键字:新字段 字段 任意次 添加 表单 删除 动态      更新时间:2023-09-26

我有一个没有嵌套模型的表单。

class UserProductsController
  def new
    @user_product = current_user.user_products.build
  end
end

与jquery/javascript我想添加和删除新的@user_product字段在同一形式。正常情况下是这样的:

<%= form_for(@user_product) do |f| %>
    <%= f.error_messages %>
      <%= f.text_field :product %>
      <%= f.text_field :address %>
      <%= f.text_field :price %>
    <%= f.submit %>
<% end %>

And I'm trying to achieve:

<%= form_for(@user_product) do |f| %>
      <%= f.error_messages %>
      <%= f.text_field :product_name %>
      <%= f.text_field :address %>
      <%= f.text_field :price %>
      ---New ID(New generated ID, could be any new number in the database)
      <%= f.text_field :product_name %>
      <%= f.text_field :address %>
      <%= f.text_field :price %>
      <%= Remove this Product %> # ajax style, this link removes this product entirely
      ----ID 3----
      <%= f.text_field :product_name %>
      <%= f.text_field :address %>
      <%= f.text_field :price %>
      <%= Remove this Product %>
     -----Add link------
      <%= Add Another Field %> # ajax style adding
   <%= f.submit %>
<% end %>

请注意,新id没有预先设置,还有一个提交按钮,这样用户就可以一次创建多个Product。我如何实现上述目标?

谢谢。


答:

使用用户。你可以照詹姆斯说的去做。这是我的表格。

<%= form_for(current_user, :url => user_products_path) do |f| %>
  <%= f.error_messages %>
    <%= f.fields_for :user_products do |builder| %>
     <%= render "user_product_fields", :f => builder %>
    <% end %>
     <%= link_to_add_fields "Add a UserProduct", f, :user_products %>
    <%= f.submit "Create" %>
<% end %>

_user_product_fields.html.erb

<div class="fields">
        <%= f.label :product, "Product" %>
        <%= f.text_field :product %>
        <%= f.label :address, "Address" %>
        <%= f.text_field :address %>
        <%= f.label :price %>
        <%= f.text_field :price %>
        <%= link_to_remove_fields "remove", f %>
</div>

就像其他人建议的那样(有些没用),使用嵌套的表单。

您需要表单基于current_user对象,并为:user_products声明fields_for。你需要使用url_for将表单的url设置为发送回user_product控制器,而不是用户控制器。你还需要调整user_product控制器的更新和创建操作,以使用params[:user]而不是params[:user_product]

如果你有你的accepts_nested_attributes配置正确,所有应该是好的。

顺便说一句,如果你遵循这些railcast,你会发现添加新的javascript将无法在Rails 3.x中工作

你应该在你的视图帮助器

中使用这样的东西
module ApplicationHelper
  def link_to_remove_fields(name, f)
    f.hidden_field(:_destroy) + link_to_function(name, "remove_fields(this)")
  end
  def link_to_add_fields(name, f, association)
    new_object = f.object.class.reflect_on_association(association).klass.new
    fields = f.fields_for(association, new_object, :child_index => "new_#{association}") do |builder|
      render(association.to_s.singularize + "_fields", :f => builder)
    end
    link_to_function(name, "add_fields(this, '#{association}', '#{escape_javascript(fields)}')")
  end
end

之类的东西在application。js文件

// Place your application-specific JavaScript functions and classes here
// This file is automatically included by javascript_include_tag :defaults
function remove_fields(link) {
  $(link).previous("input[type=hidden]").value = "1";
  $(link).up(".fields").hide();
}
function add_fields(link, association, content) {
  var new_id = new Date().getTime();
  var regexp = new RegExp("new_" + association, "g")
  $(link).up().insert({
    after: content.replace(regexp, new_id)
  });
}

显然你的form_for需要被重构成这样的东西

<%= form_for(current_user, :url => user_product_path) do |f| %>
<!-- add your f.fields_for :user_products here, probably in a rendered partial -->
<%end%>

这应该足以让您使用rails强制转换

Checkout this:

http://railscasts.com/episodes/196-nested-model-form-part-1

http://railscasts.com/episodes/197-nested-model-form-part-2

可以使用cocoon