diff --git a/README.md b/README.md index ee293bc5..465658c5 100644 --- a/README.md +++ b/README.md @@ -79,10 +79,15 @@ It is often desirable to move the nested fields into a partial to keep things or In this case it will look for a partial called "task_fields" and pass the form builder as an `f` variable to it. -## Specifying a Target for Nested Fields +## Options for the Wrapper By default, `link_to_add` appends fields immediately before the link when -clicked. This is not desirable when using a list or table, for example. In +clicked. The contents of `fields_for` are wrapped inside a `div` with +`class="fields"`. + +### Specifying a Target for Nested Fields + +This behaviour is not desirable when using a list or table, for example. In these situations, the "data-target" attribute can be used to specify where new fields should be inserted. @@ -98,14 +103,37 @@ fields should be inserted.
<%= f.link_to_add "Add a task", :tasks, :data => { :target => "#tasks" } %>
``` +### Specifying a custom Wrapper Selector + +By default, nested_form assumes that the wrapper has a `class="fields"` +attribute. In case this class conflicts with your existing css, you may +provide a custom wrapper css selector attribute along with the `:wrapper +=> false` option. + +```erb +<%= task_form.text_field :name %> | +<%= task_form.link_to_remove "Remove this task" %> | +
<%= f.link_to_add "Add a task", :tasks, :data => { :target => "#tasks", :selector => ".task-wrapper" } %>
+``` + +### Data Attribute Syntax + Note that the `:data` option above only works in Rails 3.1+. For Rails 3.0 and below, the following syntax must be used. ```erb -<%= f.link_to_add "Add a task", :tasks, "data-target" => "#tasks" %>
+<%= f.link_to_add "Add a task", :tasks, "data-target" => "#tasks", "data-selector" => ".task-wrapper" %>
``` + + ## JavaScript events Sometimes you want to do some additional work after element was added or removed, but only diff --git a/spec/dummy/app/controllers/tasks_controller.rb b/spec/dummy/app/controllers/tasks_controller.rb new file mode 100644 index 00000000..5423a9d9 --- /dev/null +++ b/spec/dummy/app/controllers/tasks_controller.rb @@ -0,0 +1,5 @@ +class TasksController < ApplicationController + def new + @task = Task.new + end +end diff --git a/spec/dummy/app/views/tasks/new.html.erb b/spec/dummy/app/views/tasks/new.html.erb new file mode 100644 index 00000000..415e7c5c --- /dev/null +++ b/spec/dummy/app/views/tasks/new.html.erb @@ -0,0 +1,12 @@ +<%= nested_form_for @task do |f| -%> + <%= f.text_field :name %> +<%= milestone_form.text_field :name %> | +<%= milestone_form.link_to_remove "Remove" %> | +
<%= f.link_to_add "Add new milestone", :milestones, "data-target" => "#tasks", "data-selector" => ".milestones-wrapper" %>
+<% end %> diff --git a/spec/dummy/config/routes.rb b/spec/dummy/config/routes.rb index 6f29827f..52c74b70 100644 --- a/spec/dummy/config/routes.rb +++ b/spec/dummy/config/routes.rb @@ -1,6 +1,7 @@ Dummy::Application.routes.draw do resources :companies, :only => %w(new create) resources :projects, :only => %w(new create) + resources :tasks, :only => %w(new create) get '/:controller/:action' # The priority is based upon order of creation: diff --git a/spec/form_spec.rb b/spec/form_spec.rb index 2701051b..aad3b5f2 100644 --- a/spec/form_spec.rb +++ b/spec/form_spec.rb @@ -21,6 +21,25 @@ def check_form fields.reject { |field| field.visible? }.count.should == 1 end + def check_form_with_custom_wrapper + page.should have_no_css('form .milestones-wrapper input[id$=name]') + click_link 'Add new milestone' + page.should have_css('form .milestones-wrapper[data-nested-wrapper] input[id$=name]', :count => 1) + find('form .milestones-wrapper[data-nested-wrapper] input[id$=name]').should be_visible + find('form .milestones-wrapper[data-nested-wrapper] input[id$=_destroy]').value.should == 'false' + + click_link 'Remove' + find('form .milestones-wrapper[data-nested-wrapper] input[id$=_destroy]').value.should == '1' + find('form .milestones-wrapper[data-nested-wrapper] input[id$=name]').should_not be_visible + + click_link 'Add new milestone' + click_link 'Add new milestone' + fields = all('form .milestones-wrapper[data-nested-wrapper]') + fields.select { |field| field.visible? }.count.should == 2 + fields.reject { |field| field.visible? }.count.should == 1 + end + + it 'should work with jQuery', :js => true do visit '/projects/new' check_form @@ -63,4 +82,19 @@ def check_form name.should match(/\Acompany\[project_attributes\]\[tasks_attributes\]\[\d+\]\[milestones_attributes\]\[\d+\]\[name\]\z/) end + context "form with custom wrapper" do + + it 'should work with jQuery', :js => true do + visit '/tasks/new' + check_form_with_custom_wrapper + end + + it 'should work with Prototype', :js => true do + visit '/tasks/new?type=prototype' + check_form_with_custom_wrapper + end + + end + + end diff --git a/vendor/assets/javascripts/jquery_nested_form.js b/vendor/assets/javascripts/jquery_nested_form.js index b9225b14..56bff81d 100644 --- a/vendor/assets/javascripts/jquery_nested_form.js +++ b/vendor/assets/javascripts/jquery_nested_form.js @@ -11,10 +11,11 @@ var assoc = $(link).data('association'); // Name of child var blueprint = $('#' + $(link).data('blueprint-id')); var content = blueprint.data('blueprint'); // Fields template + var wrapperSelector = $(link).data('selector') || ".fields"; // Make the context correct by replacing