繁体   English   中英

Rails嵌套属性form_for for has_many,使用javascript无限制嵌套模型

[英]Rails Nested Attributes form_for for has_many with unlimited nested models using javascript

所以我有一个非常简单的模型,其中设置了嵌套属性:

class Property < ActiveRecord::Base
  has_many :trees
  accepts_nested_attributes for :trees
end

然后我在我的控制器中构建它们:

class PropertiesController < ApplicationController

  def new
    @property = Properties.new
    @trees = @property.trees.build
  end
end

然后在我看来(使用苗条):

= form_for @property |p|
  = p.text_field :name

  .tree
    = p.fields_for :trees do |t|
      = t.text_field :fruit
      = t.select :quantity, (1..1000).to_a

    = link_to 'Add Another Tree', new_properties_path, id: 'new-tree'

然后在我的js(coffeescript)文件中,绑定到'#new-tree'锚点的click事件:

event.preventDefault()
tree = $(event.target).parents('.tree')
tree.after tree.clone(true)

这可以按照您的预期工作,但是当我提交表单时,只提交最后一个树参数。 这是因为在form_for的生成的html中我得到这样的东西:

<input type="text" id="property_trees_attributes_0_fruit" name="property[trees_attributes][0][fruit]">
<select id="property_trees_attributes_0_quantity" name="property[trees_attributes][0][quantity]" class="valid">
  <option value="1">1</option>
  <option value="2">2</option>
  <option value="3">3</option>
  ...
</select>

当我克隆这个html时,我得到了名字和id,其中包含0 ,但我相信它应该是1来添加额外的树参数等。

我试图通过做这样的事来补偿js:

event.preventDefault()
tree = $(event.target).parents('.tree')
clone = tree.clone()
number = parseInt(clone.find('input[type=text]').attr('id').match /[0-9]/)
next = number + 1
clone = clone.html().replace /_(#{number})_|\[(#{number})\]/, next
section.after clone

正则表达式的要点是替换两个下划线或两个括号之间的任何数字,如_0_[0]

我的正则表达式似乎不起作用。 它只用1替换_0_ ,这个解决方案对我来说似乎很麻烦。 我会使正则表达式更简单,但是我不得不担心它会改变选择菜单选项的值。

有关清理的建议吗? 我错过了一些非常明显的东西吗

你遇到的问题是你只是复制了DOM元素 - 这是IMO的一个黑客攻击,因为你没有先构建你需要的对象(不会持久保存数据等)

我们之前使用Ajax实现了“向f.fields_for添加额外字段” - 这里有一个很棒的教程,这里有一个RailsCast


CHILD_INDEX

您的问题的答案是使用fields_for帮助程序中的child_index选项,并使用integer时间戳:

<% index = Time.now.to_i %>
<%= f.fields_for :trees, child_index: index do |fields| %>
    #your fields here
<% end %>

这就是我们的工作:

#app/views/properties/new.html.erb
<%= form_for @property do |f| %>
   <%= render partial: "trees_fields", locals: { f: f, child_index: Time.now.to_i } %>
   <%= link_to "New Field", new_field_property_path %>
<% end %>

#app/views/properties/_trees_fields.html.erb
<%= f.fields_for :trees, child_index: child_index do |trees| %>
   <%= trees.text_field :your_attr %>
<% end %>

#app/controllers/properties_controller.rb
def new_field
    @property = Property.new
    @property.trees.build
    render "add_tree", layout: false
end

#app/views/properties/add_tree.html.erb
<%= form_for @property do |f| %>
      <%= render partial: "trees_fields", locals: {f: f, child_index: Time.now.to_i} %>
<% end %>

 #app/assets/javascripts/application.js.coffee
$ ->
  $(document).on "click", "#add_tree", (e) ->
     e.preventDefault();
     $.ajax
       url: '/messages/add_subscriber'
       success: (data) ->
              el_to_add = $(data).html()
          $('#trees_form').append(el_to_add)
       error: (data) ->
          alert "Sorry, There Was An Error!"

你是对的,嵌套的.tree元素不应该有相同的id。 所以你不应该克隆它们。 而是使用帮助器构建新项目,例如,基于当前时间生成id,然后粘贴新的嵌套元素。 这是一个复杂的场景,所以我认为观看相关的railscast会更好:

  1. http://railscasts.com/episodes/196-nested-model-form-part-1
  2. http://railscasts.com/episodes/197-nested-model-form-part-2
  3. http://railscasts.com/episodes/196-nested-model-form-revised

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM