Commit a941d776791c41ab9ebf7b04f32326e60dbcb4d5
1 parent
2ab6a694
Exists in
master
and in
1 other branch
Add JS to allow adding/destroying nested attributes
Showing
3 changed files
with
57 additions
and
3 deletions
Show diff stats
app/models/project.rb
| ... | ... | @@ -15,7 +15,7 @@ class Project |
| 15 | 15 | validates_presence_of :name, :api_key |
| 16 | 16 | validates_uniqueness_of :name, :api_key, :allow_blank => true |
| 17 | 17 | |
| 18 | - accepts_nested_attributes_for :watchers, | |
| 18 | + accepts_nested_attributes_for :watchers, :allow_destroy => true, | |
| 19 | 19 | :reject_if => proc { |attrs| attrs.all? { |k, v| v.blank? } } |
| 20 | 20 | |
| 21 | 21 | def self.find_by_api_key!(key) | ... | ... |
app/views/projects/_fields.html.haml
public/javascripts/application.js
| ... | ... | @@ -0,0 +1,54 @@ |
| 1 | +$(function(){ | |
| 2 | + activateNestedForms(); | |
| 3 | +}); | |
| 4 | + | |
| 5 | +function activateNestedForms() { | |
| 6 | + $('.nested-wrapper').each(function(){ | |
| 7 | + var wrapper = $(this); | |
| 8 | + | |
| 9 | + makeNestedItemsDestroyable(wrapper); | |
| 10 | + | |
| 11 | + var addLink = $('<a/>').text('add another').addClass('add-nested'); | |
| 12 | + addLink.click(appendNestedItem); | |
| 13 | + wrapper.append(addLink); | |
| 14 | + }); | |
| 15 | + $('.nested a.remove-nested').live('click',removeNestedItem); | |
| 16 | +} | |
| 17 | + | |
| 18 | +function makeNestedItemsDestroyable(wrapper) { | |
| 19 | + wrapper.find('.nested').each(function(){ | |
| 20 | + var nestedItem = $(this); | |
| 21 | + var destroyLink = $('<a/>').text('remove').addClass('remove-nested'); | |
| 22 | + destroyLink.css('float','right'); | |
| 23 | + nestedItem.find('label').first().prepend(destroyLink); | |
| 24 | + }) | |
| 25 | +} | |
| 26 | + | |
| 27 | +function appendNestedItem() { | |
| 28 | + var addLink = $(this); | |
| 29 | + var nestedItem = addLink.parent().find('.nested').first().clone(); | |
| 30 | + nestedItem.find('input, select').each(function(){ | |
| 31 | + var input = $(this); | |
| 32 | + var timestamp = new Date(); | |
| 33 | + timestamp = timestamp.valueOf(); | |
| 34 | + input.attr('id', input.attr('id').replace(/([_\[])\d+([\]_])/,'$1'+timestamp+'$2')); | |
| 35 | + input.attr('name', input.attr('name').replace(/([_\[])\d+([\]_])/,'$1'+timestamp+'$2')); | |
| 36 | + input.val(''); | |
| 37 | + }); | |
| 38 | + addLink.before(nestedItem); | |
| 39 | +} | |
| 40 | + | |
| 41 | +function removeNestedItem() { | |
| 42 | + var destroyLink = $(this); | |
| 43 | + var nestedItem = destroyLink.closest('.nested'); | |
| 44 | + var inputNameExample = nestedItem.find('input').first().attr('name'); | |
| 45 | + var idFieldName = inputNameExample.replace(/\[[^\]]*\]$/,'[id]'); | |
| 46 | + if($("input[name='"+idFieldName+"']").length) { | |
| 47 | + var destroyFlagName = inputNameExample.replace(/\[[^\]]*\]$/,'[_destroy]') | |
| 48 | + var destroyFlag = $('<input/>').attr('name',destroyFlagName).attr('type','hidden').val('true'); | |
| 49 | + $("input[name='"+idFieldName+"']").after(destroyFlag); | |
| 50 | + nestedItem.hide(); | |
| 51 | + } else { | |
| 52 | + nestedItem.remove(); | |
| 53 | + } | |
| 54 | +} | |
| 0 | 55 | \ No newline at end of file | ... | ... |