Javascript 如何使用Haml和Formtastic动态添加和删除嵌套模型字段
我们都看到了Ryan Bates解释如何使用Javascript在父对象表单中动态添加或删除嵌套对象的精彩故事 有人知道这些方法需要如何修改才能与Haml Formtastic合作吗 为了增加一些背景,这里是我目前面临的问题的简化版本: #教师表单(具有嵌套主题表单)[来自我的申请]Javascript 如何使用Haml和Formtastic动态添加和删除嵌套模型字段,javascript,ruby-on-rails,nested-forms,formtastic,Javascript,Ruby On Rails,Nested Forms,Formtastic,我们都看到了Ryan Bates解释如何使用Javascript在父对象表单中动态添加或删除嵌套对象的精彩故事 有人知道这些方法需要如何修改才能与Haml Formtastic合作吗 为了增加一些背景,这里是我目前面临的问题的简化版本: #教师表单(具有嵌套主题表单)[来自我的申请] - semantic_form_for(@teacher) do |form| - form.inputs do = form.input :first_name = form.input :s
- semantic_form_for(@teacher) do |form|
- form.inputs do
= form.input :first_name
= form.input :surname
= form.input :city
= render 'subject_fields', :form => form
= link_to_add_fields "Add Subject", form, :subjects
- form.fields_for :subjects do |ff|
#subject_field
= ff.input :name
= ff.input :exam
= ff.input :level
= ff.hidden_field :_destroy
= link_to_remove_fields "Remove Subject", ff
#个人科目表部分[来自我的申请]
- semantic_form_for(@teacher) do |form|
- form.inputs do
= form.input :first_name
= form.input :surname
= form.input :city
= render 'subject_fields', :form => form
= link_to_add_fields "Add Subject", form, :subjects
- form.fields_for :subjects do |ff|
#subject_field
= ff.input :name
= ff.input :exam
= ff.input :level
= ff.hidden_field :_destroy
= link_to_remove_fields "Remove Subject", ff
#应用程序助手(直接来自Railscasts)
#Application.js(直接来自Railscasts)
实现的问题似乎在于javascript方法——Formtastic表单的DOM树与常规rails表单大不相同
我已经在网上看到过好几次这个问题,但还没有找到答案——现在你知道,不仅仅是我会感谢你的帮助
杰克你走对了方向: …Formtastic表单的DOM树 与常规轨道有很大不同 形式 为了将Ryan的示例改编为formtastic,需要提醒的是,用于helper的
semantic\u字段与用于
helper的semantic\u表单类似,后者以列表形式输出输入
要使内容尽可能接近Railscast代码,您需要:
- 将嵌套字段的集合封装在包装器中(我使用带有
subjects
CSS ID的div)
- 将嵌套字段封装在ul/ol包装器中(我应用了
嵌套字段
CSS类)
以下是您的文件的内容
教师表单(带嵌套主题字段):
主题字段部分(用于嵌套主题):
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, h("add_fields(this, \"#{association}\", \"#{escape_javascript(fields)}\")"))
end
Application.js:
function remove_fields(link) {
$(link).previous("input[type=hidden]").value = "1";
$(link).up(".nested-fields").hide();
}
function add_fields(link, association, content) {
var new_id = new Date().getTime();
var regexp = new RegExp("new_" + association, "g")
$(link).up().insert({
before: content.replace(regexp, new_id)
});
}
使用以下gems:
- formtastic(0.9.10)
- haml(3.0.2)
- 小黄瓜(1.0.26)
- 轨道(2.3.5)
jQuery的application.js:
function remove_fields(link) {
$(link).prev("input[type=hidden]").val("1");
$(link).parent(".nested-fields").hide();
}
function add_fields(link, association, content) {
var new_id = new Date().getTime();
var regexp = new RegExp("new_" + association, "g")
$(link).parent().before(content.replace(regexp, new_id));
}
在Rails 3中,不需要在助手中使用h()函数。只要省略就行了。多年来,我一直在断断续续地思考这个问题,今天我想出了一些我引以为豪的东西——优雅、不引人注目,而且你只能完成两三行(非常长的)代码
ParentFoo有许多嵌套条,带有适当的接受嵌套参数和所有这些好东西。将嵌套的_栏的一组字段呈现到链接上的“数据添加嵌套”属性中,使用:child_索引设置一个可以稍后替换的字符串。在第二个参数data add nested replace中传递该字符串
父\u foos/\u form.html.haml
- semantic_form_for @parent_foo do |f|
-# render existing records
- f.semantic_fields_for :nested_bars do |i|
= render 'nested_bar_fields', :f => i
# magic!
- reuse_fields = f.semantic_fields_for :nested_bars, @parent_foo.nested_bars.build, :child_index => 'new_nested_bar_fields' do |n| render('nested_bar_fields', :f => n) end
= link_to 'Add nested bar', '#', 'data-add-nested' => reuse_fields, 'data-add-nested-replace' => 'new_nested_bar_fields'
- f.inputs do
= f.input :name
= f.input :_delete, :as => :boolean
嵌套的部分字段没有什么特别之处
父\u foos/\u嵌套\u bar\u fields.html.haml
- semantic_form_for @parent_foo do |f|
-# render existing records
- f.semantic_fields_for :nested_bars do |i|
= render 'nested_bar_fields', :f => i
# magic!
- reuse_fields = f.semantic_fields_for :nested_bars, @parent_foo.nested_bars.build, :child_index => 'new_nested_bar_fields' do |n| render('nested_bar_fields', :f => n) end
= link_to 'Add nested bar', '#', 'data-add-nested' => reuse_fields, 'data-add-nested-replace' => 'new_nested_bar_fields'
- f.inputs do
= f.input :name
= f.input :_delete, :as => :boolean
在jQuery中,将元素的点击与数据添加嵌套字段绑定(我在这里使用了live(),这样ajax加载的表单就可以工作了)以将字段插入DOM,并用新ID替换字符串。这里我做的是在链接()之前插入新字段的简单操作,但是您也可以在链接上提供一个add-nested-replace-target属性,说明您希望新字段在DOM中的什么位置结束
application.js
$('a[data-add-nested]').live('click', function(){
var regexp = new RegExp($(this).data('add-nested-replace'), "g")
$($(this).data('add-nested').replace(regexp, (new Date).getTime())).insertBefore($(this))
})
当然,你可以把它放在助手里;我在这里直接在视图中介绍它,这样原则就很清楚了,而不必在元编程中乱搞。如果您担心名称冲突,可以在该助手中生成一个唯一的ID,并在嵌套替换中传递它
对删除行为的想象留给读者作为练习
(为Rails 2显示,因为这是我今天正在工作的站点-在Rails 3中几乎相同)您可以发布主题的字段的HTML输出吗?
?感谢您的解决方案--因此主题字段与按钮一样显示,但当我单击任一链接时,我将滚动到屏幕顶部,没有任何操作(我已经打开了js默认值,以防您怀疑)。我尝试了Steve的解决方案,删除链接起作用,但不幸的是添加按钮不起作用。可能我的标记有点不同——使用Rails 3和最新的Formtastic。有什么想法吗?我只使用上面列出的gems尝试了此设置。而且,听起来你并没有完全按照我的示例进行设置,所以你可能会这么做让您的表单结构不同。我建议您在继续删除字段之前,首先使用指向添加字段和添加字段帮助器的链接。谢谢--通过此操作,“删除”按钮可以正常工作,但“添加”按钮不能正常工作……使用Rails3和最新的Formtastic。注意:在Rails 3中,由于html转义,这可能没有那么容易:(使用escape\u once似乎有效,就像在这个半相关的示例中插入一个字段:-new\u field=escape\u once f.input(:related\u thing)=link_to‘Add other’、‘#’、‘data insert’=>new_field我进一步开发了这项技术,以便在没有模型的情况下使用-我遇到过一个客户希望指定要在报告中显示的字段集的情况。此版本使用块而不是单独的字段模板,并使用“通用模型”生成可替换的参数仪表。要点如下: