Skip to content

Instantly share code, notes, and snippets.

@naderhen
Created August 19, 2010 01:08
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save naderhen/536704 to your computer and use it in GitHub Desktop.
Save naderhen/536704 to your computer and use it in GitHub Desktop.
/**
* Application_helper.rb
*/
# Methods added to this helper will be available to all templates in the application.
module ApplicationHelper
def remove_child_link(name, f)
f.hidden_field(:_destroy) + link_to(name, "javascript:void(0)", :class => "remove_child")
end
def add_child_link(name, association)
link_to(name, "javascript:void(0)", :class => "add_child", :"data-association" => association)
end
def new_child_fields_template(form_builder, association, options = {})
content_for "#{association}_fields_template" do
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
end
end unless content_given?("#{association}_fields_template")
end
def content_given?(name)
content = instance_variable_get("@content_for_#{name}")
! content.nil?
end
end
/**
* _form.html.erb
*/
<%= form_for @board do |f| %>
<p>
<%= f.label :board_date %><br />
<%= f.text_field :board_date, :class=>"datepicker" %>
</p>
<fieldset>
<legend>Warehouses</legend>
</fieldset>
<%= f.fields_for :warehouses do |warehouse_form| %>
<%= render :partial => 'warehouse', :locals => { :f => warehouse_form } %>
<% end %>
<p><%= add_child_link "New Warehouse", :warehouses %></p>
<%= new_child_fields_template(f, :warehouses)%>
<p><%= f.submit "Submit" %></p>
<% end %>
<%= yield :warehouses_fields_template %>
<%= yield :ratgrades_fields_template %>
/**
* _warehouse.html.erb
*/
<div class="fields">
<%= f.label :name, "Warehouse" %>
<%= f.text_field :name, :class=>"half title"%>
<%= remove_child_link "remove", f %>
<div class="children_fields">
<%= f.fields_for :ratgrades do |ratgrade_form| %>
<%= render :partial => 'ratgrade', :locals => { :f => ratgrade_form } %>
<% end %>
<p><%= add_child_link "New Grade", :ratgrades %></p>
<%= new_child_fields_template(f, :ratgrades)%>
</div>
</div>
/**
* _ratgrade.html.erb
*/
<div class="fields">
<%= f.text_field :name, :size=>"10" %>
<%= f.text_field :total, :size=>"10" %>
<%= f.text_field :availdate, :class=>"rat_date" %>
<%= remove_child_link "remove", f %>
</div>
/**
* application.js
*/
$(function() {
$('form a.add_child').live('click', function() {
// Setup
var assoc = $(this).attr('data-association'); // Name of child
var content = $('#' + assoc + '_fields_template').html(); // Fields template
// Make the context correct by replacing new_<parents> with the generated ID
// of each of the parent objects
var context = ($(this).parents('.fields').children('input:first').attr('name') || '').replace(new RegExp('\[[a-z]+\]$'), '');
// context will be something like this for a brand new form:
// project[tasks_attributes][1255929127459][assignments_attributes][1255929128105]
// or for an edit form:
// project[tasks_attributes][0][assignments_attributes][1]
if(context) {
var parent_names = context.match(/[a-z]+_attributes/g) || []
var parent_ids = context.match(/[0-9]+/g)
for(i = 0; i < parent_names.length; i++) {
if(parent_ids[i]) {
content = content.replace(
new RegExp('(\\[' + parent_names[i] + '\\])\\[.+?\\]', 'g'),
'$1[' + parent_ids[i] + ']'
)
}
}
}
// Make a unique ID for the new child
var regexp = new RegExp('new_' + assoc, 'g');
var new_id = new Date().getTime();
content = content.replace(regexp, new_id)
$(this).parent().before(content);
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).parent('.fields').hide();
return false;
});
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment