我制作了一个表单,用户可以通过单击文本或 URL 按钮动态添加嵌套表单字段。提交表单后,内容将显示在 View 模板中。但是,当我去编辑(并希望随后更新)/posts/id/edit
中的帖子时,帖子内容不会出现在编辑 View 模板中 - 它在浏览器中是一个空白页面。
非常感谢您的帮助!谢谢!
发布模型
class Post < ActiveRecord::Base
has_many :things, dependent: :destroy
accepts_nested_attributes_for :things
end
事物模型
class Thing < ActiveRecord::Base
belongs_to :post
end
架构
create_table "posts", force: :cascade do |t|
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
create_table "things", force: :cascade do |t|
t.text "text"
t.string "url"
t.integer "post_id"
end
帖子 Controller
class PostsController < ApplicationController
def edit
@post = Post.find(params[:id])
end
def update
end
new.html.erb
<button id='addtext'>text</button>
<button id='addurl'>url</button>
<%= form_for @post, url: posts_path, html: { multipart: true } do |f| %>
<%= f.fields_for :thing do |ff| %>
<% end %>
<%= f.submit %>
<% end %>
posts.coffee
current_index = 0
addText = ->
html = """
<div>
<textarea placeholder="Write something..." name="post[things_attributes][#{current_index}][text]" id="post_things_attributes_#{current_index}_text"></textarea>
<input type="hidden" name="post[things_attributes][#{current_index}] [order]" id="post_things_attributes_#{current_index}_order" value="#{current_index}" />
</div>
"""
$("#new_post input[type='submit']").before(html)
current_index += 1
$ ->
$('#addtext').on('click', addText)
current_index = 0
最佳答案
您的结构存在几个问题:
- 您的
form_for
中没有任何字段 - 您正在手动为
fields_for
定义字段(大不不)。
form_for
当您创建form_for
时,Rails 使用 form object
从您的 model
获取数据,并将其输出为 HTML 表单。
此输出是在渲染时完成的,无论您使用 javascript 进行多少手动提升,都不会改变:
<%= form_for @post do |f| %>
# you need fields in here
<%= f.submit %>
<% end %>
调试此问题的方法是检查 source
您的页面 ( Right-Click > View Source
)。如果<form>
元素存在,这意味着 form_for
方法有效:
另外,请记住 form_for
是一个辅助方法。它接受参数并输出 HTML 供您使用。这不是魔法。如果它“没有出现”,那么一定有一个合乎逻辑的原因。
fields_for
第二步是你的fields_for
如果没有任何对象来填充它,则不会显示。
当您手动添加新的 fields_for
时,您还会遇到一个大问题。字段,这基本上是一个 antipattern .
您需要执行以下操作:
#app/controllers/posts_controller.rb
class PostsController < ApplicationController
def edit
@post = Post.includes(:things).find(params[:id])
@post.things.build unless @post.things.any?
end
end
#app/views/posts/edit.html.erb
<%= form_for @post, url: posts_path, html: { multipart: true } do |f| %>
<%= f.fields_for :things do |ff| %> #-> association name (plural)
<%= ff.text_area :text, placeholder: "Write Something" %>
<% end %>
<%= f.submit %>
<% end %>
fields_for
使用您传递给 form_for
的父级的关联对象进行填充。因此,如果您尚未构建任何关联对象,则需要确保至少构建了一个关联对象,以便相应地填充字段。
嵌套
最后,您需要了解如何动态附加 fields
到fields_for
堵塞。
虽然您的代码没有错误,但它非常不切实际。有大量资源可以为您指明正确的方向:
- RailsCasts Nested Forms
Cocoon
Gem (HIGHLY recommended)- NoMethodError within nested model form (my own post)
简而言之,您需要使用 Ruby/Rails 来构建 fields_for
您需要的方法,使用 ajax 将它们附加到您的表单中:
#app/controllers/posts_controller.rb
class PostsController < ApplicationController
def edit
@post = Post.includes(:things).find params[:id]
@post.things.build unless @post.things.any?
respond_to do |format|
format.js
format.html
end
end
end
#app/views/posts/edit.html.erb
<%= form_for @post, authenticity_token: !request.xhr? do |f| %>
<%= render partial: "things_fields", locals: { f: f } %>
<% if !request.xhr? %>
<%= button_to "Add Thing", edit_posts_path(@post), method: :get, remote: true %>
<%= f.submit %>
<% end %>
<% end %>
#app/views/posts/_things_fields.html.erb
<%= f.fields_for :things, child_index: Time.now.to_i do |ff| %>
<%= ff.text_area :text, placeholder: "Write Something" %>
<% end %>
这将允许您附加 fields
通过JS
调用:
#app/views/posts/edit.js.erb
$("<%=j render "edit" %>").data().appendTo("form#post);
此方法的技巧是使用 child_index: Time.now.to_i
(为每个新附加的字段提供唯一的id
)。
--
长篇文章;如果您希望我专门与您一起检查一下,您已经收到了我的电子邮件。
关于javascript - Rails 嵌套表单 - 编辑操作和 edit.html.erb 不会显示表单或相关帖子内容,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35512471/