Skip to content

Instantly share code, notes, and snippets.

@maca
Created July 12, 2012 08:15
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 3 You must be signed in to fork a gist
  • Save maca/3096634 to your computer and use it in GitHub Desktop.
Save maca/3096634 to your computer and use it in GitHub Desktop.
Jquery plugin for adding and removing nested records (Rails accepts nested attributes for)
<!-- Sorry, this example is with formtastic but I think it would work the same with vanilla rails form helpers -->
<%= semantic_form_for @survey do |form| %>
<fieldset class="nested_models answers" data-association="answers">
<%- form.object.answers.build %>
<%= form.semantic_fields_for :answers do |answer| %>
<%- record = answer.object %>
<fieldset class="<%= record.new_record? ? :new : nil %>">
<ol>
<%= answer.input :text, required: false %>
<%= answer.input :_destroy, as: :boolean %>
</ol>
</fieldset>
<% end %>
<%= link_to t('.add_answer'), '#', :class => 'add_record', :style => 'display:none' %>
</fieldset>
<%= form.buttons do %>
<%= form.commit_button %>
<% end %>
<% end %>
<script>
$('fieldset[data-association]').nestedAssociations();
</script>
// macario ortega
// github.com/maca
// mit licence
(function($){
$.fn.nestedAssociationsChangeId = function(association, newId){
$(this).find('[id], [for], [name]').each(function(){
var tag = $(this);
$.each(['id', 'for', 'name'], function(index, attribute){
var value = tag.attr(attribute);
if (value && attribute == 'name') {
var matcher = new RegExp('\\[' + association + '_attributes\\]\\[\\d+\\]');
tag.attr(attribute, value.replace(matcher, '[' + association + '_attributes][' + newId + ']'));
} else if (value) {
var matcher = new RegExp(association + '_attributes_\\d+');
tag.attr(attribute, value.replace(matcher, association + '_attributes_' + newId));
};
});
});
};
$.fn.nestedAssociations = function(opts){
var self = $(this);
var associationFieldset = self;
var settings = {
add : $.noop,
remove : $.noop
}
if (opts) { $.extend(settings, opts); }
$(this).find('input[id$=_destroy]').closest('label').each(function(){
var destroyLink = $('<a href="#" class="remove-associated-record">').text($(this).text());
destroyLink.click(function(){
$(this).siblings('input').attr('value', '1');
settings.remove.apply($(this).closest('fieldset').slideUp());
return false;
});
$(this).hide().after(destroyLink);
});
return associationFieldset.each(function(){
var container = $(this);
var association = container.attr('data-association');
var template = container.children('fieldset.new').last().detach();
container.children('a.add_record').show().click(function(){
var cleanTemplate = template.clone(true);
$(this).before(cleanTemplate.hide());
$(this).parents('fieldset[data-association]').each(function(){
var association = $(this).attr('data-association');
$(this).children('fieldset.new').each(function(){
$(this).nestedAssociationsChangeId(association, new Date().getTime());
})
});
cleanTemplate.slideDown(function(){
settings.add.apply(this);
});
return false;
});
});
};
})(jQuery);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment