栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 面试经验 > 面试问答

带有jQuery的Rails中的动态表单字段

面试问答 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

带有jQuery的Rails中的动态表单字段

由于没有人对此提供答案,即使是悬赏,我终于设法自己解决了这个问题。这不应该是一个树桩!希望这将在Rails 3.0中更容易实现。

Andy的示例是直接删除记录的好方法,而无需向服务器提交表单。在这种情况下,我真正想要的是一种在对嵌套表单进行更新之前动态添加/删除字段的方法。这是一种稍微不同的情况,因为随着字段的删除,在提交表单之前,它们实际上并未删除。我可能最终会根据情况同时使用两者。

我已经基于Tim Riley在github上的complex-forms-
examples
分支实现了我的实现。

首先设置模型,并确保它们支持嵌套属性:

class Person < ActiveRecord::base  has_many :phone_numbers, :dependent => :destroy  accepts_nested_attributes_for :phone_numbers, :reject_if => lambda { |p| p.values.all?(&:blank?) }, :allow_destroy => trueendclass PhoneNumber < ActiveRecord::base  belongs_to :personend

为PhoneNumber的表单字段创建局部视图:

<div >  <%= f.text_field :description %>  <%= f.text_field :number %></div>

接下来为Person模型编写一个基本的编辑视图:

<% form_for @person, :builder => LabeledFormBuilder do |f| -%>  <%= f.text_field :name %>  <%= f.text_field :email %>  <% f.fields_for :phone_numbers do |ph| -%>    <%= render :partial => 'phone_number', :locals => { :f => ph } %>  <% end -%>  <%= f.submit "Save" %><% end -%>

这将通过为PhoneNumber模型创建一组模板字段来实现,我们可以使用javascript复制这些模板字段。我们将

app/helpers/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_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  endenddef add_child_link(name, association)  link_to(name, "javascript:void(0)", :class => "add_child", :"data-association" => association)enddef remove_child_link(name, f)  f.hidden_field(:_destroy) + link_to(name, "javascript:void(0)", :class => "remove_child")end

现在,将这些帮助程序方法添加到edit部分:

<% form_for @person, :builder => LabeledFormBuilder do |f| -%>  <%= f.text_field :name %>  <%= f.text_field :email %>  <% f.fields_for :phone_numbers do |ph| -%>    <%= render :partial => 'phone_number', :locals => { :f => ph } %>  <% end -%>  <p><%= add_child_link "New Phone Number", :phone_numbers %></p>  <%= new_child_fields_template f, :phone_numbers %>  <%= f.submit "Save" %><% end -%>

您现在已经完成了js模板。它将为每个关联提交一个空白模板,但是

:reject_if
模型中的子句将丢弃它们,仅保留用户创建的字段。 更新:
我已经重新考虑了这种设计,请参见下文。

这并不是真正的AJAX,因为除了页面加载和表单提交之外,没有任何通信可以进行到服务器,但是老实说,我实在找不到一种方法。

实际上,这可以提供比AJAX更好的用户体验,因为您无需等待服务器对每个其他字段的响应就可以完成。

最后,我们需要使用javascript将其连接起来。将以下内容添加到您的“ public / javascripts /
application.js”文件中:

$(function() {  $('form 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;  });  $('form a.remove_child').live('click', function() {    var hidden_field = $(this).prev('input[type=hidden]')[0];    if(hidden_field) {      hidden_field.value = '1';    }    $(this).parents('.fields').hide();    return false;  });});

到此时,您应该拥有准系统的动态表单!这里的javascript非常简单,可以很容易地用其他框架完成。例如,您可以轻松地

application.js
用原型+
lowpro
替换我的代码。其基本思想是,您无需将巨大的javascript函数嵌入到标记中,也不必
phone_numbers=()
在模型中编写繁琐的函数。一切正常。万岁!


经过一些进一步的测试,我得出结论,需要将模板移出

<form>
字段。将它们保留在此处意味着它们将与表单的其余部分一起发送回服务器,这只会在以后造成麻烦。

我将其添加到布局的底部:

<div id="jstemplates">  <%= yield :jstemplates %></div

并修改了

new_child_fields_template
助手:

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  endend

现在,您可以

:reject_if
从模型中删除这些子句,而不必担心模板被发回。



转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/409945.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号