public
Created

Jquery plugin for adding and removing nested records (Rails accepts nested attributes for)

  • Download Gist
example.erb.html
Liquid
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
<!-- 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>
jquery.nested-associations.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67
// 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);

Please sign in to comment on this gist.

Something went wrong with that request. Please try again.