Rails中使用jQuery的不显眼的动态表单字段

前端之家收集整理的这篇文章主要介绍了Rails中使用jQuery的不显眼的动态表单字段前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我试图克服Rails中动态表单域的障碍 – 这似乎是框架不能非常优雅地处理的东西。我也在我的项目中使用jQuery。我安装了jRails,但我更愿意在可能的情况下写出AJAX代码

我的形式是相当复杂,两个或三个层次的嵌套是不寻常的。我遇到的问题是生成正确的表单id,因为它们依赖于表单构建器上下文。我需要能够动态添加新字段或删除has_many关系中的现有记录,我完全失去了。

到目前为止,我所见过的每一个例子都是以某种方式丑陋的。 Ryan Bates的tutorial需要RJS,这导致一些相当丑陋的令人不快的javascript的标记,似乎是在嵌套的属性之前写的。我看到了一个fork这个例子与不引人注意的jQuery,但我只是不明白它在做什么,并没有能够让它在我的项目中工作。

可以有人提供一个简单的例子,如何做到这一点?这是否甚至可能尊重控制器的RESTful约定?

Andy发布了一个删除现有记录的好例子,任何人都可以提供一个创建具有正确属性的新字段的示例?我还没有能够弄清楚如何使用嵌套表单。

@H_404_10@

解决方法

因为没有人提供答案,即使在赏金后,我终于设法让这个工作自己。这不应该是一个骗子!希望这将是更容易做Rails 3.0。

Andy的例子是直接删除记录的好方法,而不向服务器提交表单。在这种特殊情况下,我真正寻找的是在嵌套表单更新之前动态添加/删除字段的方法。这是一个稍有不同的情况,因为当字段被删除,它们实际上并没有删除,直到提交表单。我可能会最终使用两者取决于具体情况。

我基于我的实现在Tim Riley’s complex-forms-examples fork on github。

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

  1. class Person < ActiveRecord::Base
  2. has_many :phone_numbers,:dependent => :destroy
  3. accepts_nested_attributes_for :phone_numbers,:reject_if => lambda { |p| p.values.all?(&:blank?) },:allow_destroy => true
  4. end
  5.  
  6. class PhoneNumber < ActiveRecord::Base
  7. belongs_to :person
  8. end

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

  1. <div class="fields">
  2. <%= f.text_field :description %>
  3. <%= f.text_field :number %>
  4. </div>

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

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

这将工作通过为PhoneNumber模型创建一组模板字段,我们可以与javascript复制。我们将在app / helpers / application_helper.rb中为此创建帮助方法

  1. def new_child_fields_template(form_builder,association,options = {})
  2. options[:object] ||= form_builder.object.class.reflect_on_association(association).klass.new
  3. options[:partial] ||= association.to_s.singularize
  4. options[:form_builder_local] ||= :f
  5.  
  6. content_tag(:div,:id => "#{association}_fields_template",:style => "display: none") do
  7. form_builder.fields_for(association,options[:object],:child_index => "new_#{association}") do |f|
  8. render(:partial => options[:partial],:locals => { options[:form_builder_local] => f })
  9. end
  10. end
  11. end
  12.  
  13. def add_child_link(name,association)
  14. link_to(name,"javascript:void(0)",:class => "add_child",:"data-association" => association)
  15. end
  16.  
  17. def remove_child_link(name,f)
  18. f.hidden_field(:_destroy) + link_to(name,:class => "remove_child")
  19. end

现在添加这些帮助方法到编辑partial:

  1. <% form_for @person,:locals => { :f => ph } %>
  2. <% end -%>
  3. <p><%= add_child_link "New Phone Number",:phone_numbers %></p>
  4. <%= new_child_fields_template f,:phone_numbers %>
  5. <%= f.submit "Save" %>
  6. <% end -%>

现在你已经完成了js模板。它将为每个关联提交一个空白模板,但模型中的:reject_if子句将丢弃它们,只留下用户创建的字段。更新:我已经考虑这个设计,见下文。

这不是真正的AJAX,因为在页面加载和表单提交之外没有任何通信到服务器,但我真的找不到一个方法做事后。

事实上,这可能提供比AJAX更好的用户体验,因为你不必等待服务器响应每个附加字段,直到你完成。

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

  1. $(function() {
  2. $('form a.add_child').click(function() {
  3. var association = $(this).attr('data-association');
  4. var template = $('#' + association + '_fields_template').html();
  5. var regexp = new RegExp('new_' + association,'g');
  6. var new_id = new Date().getTime();
  7.  
  8. $(this).parent().before(template.replace(regexp,new_id));
  9. return false;
  10. });
  11.  
  12. $('form a.remove_child').live('click',function() {
  13. var hidden_field = $(this).prev('input[type=hidden]')[0];
  14. if(hidden_field) {
  15. hidden_field.value = '1';
  16. }
  17. $(this).parents('.fields').hide();
  18. return false;
  19. });
  20. });

到这个时候你应该有一个准系统的动态形式!这里的javascript非常简单,并且可以很容易地与其他框架完成。你可以很容易地替换我的application.js代码与原型lowpro例如。基本的想法是,你没有嵌入巨大的JavaScript函数到你的标记,你不必在模型中写繁琐的phone_numbers =()函数。一切都正常。 Hooray!

经过一些进一步的测试,我得出结论,模板需要移出< form>字段。将它们保存在那里意味着它们被发送回服务器与其余的形式,这只是创建头痛以后。

我把它添加到我的布局的底部

  1. <div id="jstemplates">
  2. <%= yield :jstemplates %>
  3. </div

修改了new_child_fields_template助手:

  1. def new_child_fields_template(form_builder,options = {})
  2. options[:object] ||= form_builder.object.class.reflect_on_association(association).klass.new
  3. options[:partial] ||= association.to_s.singularize
  4. options[:form_builder_local] ||= :f
  5.  
  6. content_for :jstemplates do
  7. content_tag(:div,:style => "display: none") do
  8. form_builder.fields_for(association,:child_index => "new_#{association}") do |f|
  9. render(:partial => options[:partial],:locals => { options[:form_builder_local] => f })
  10. end
  11. end
  12. end
  13. end

现在,您可以从模型中删除:reject_if子句,并停止担心正在发送的模板。

@H_404_10@ @H_404_10@

猜你在找的jQuery相关文章