/nested_form

Rails plugin to conveniently handle multiple models in a single form.

Primary LanguageRubyMIT LicenseMIT

Nested Form

This is a Rails gem for conveniently manage multiple nested models in a single form. It does so in an unobtrusive way through jQuery or Prototype.

This gem only works with Rails 3. See the rails2 branch for a plugin to work in Rails 2.

An example project showing how this works is available in the complex-nested-forms/nested_form branch.

Setup

Add it to your Gemfile then run bundle to install it.

gem "nested_form"

And then add it to the Asset Pipeline in the appication.js file:

//= require jquery_nested_form

Non Asset Pipeline Setup

If you do not us the asset pipeline, run this generator to create the JavaScript file.

rails g nested_form:install

You can then include the generated JavaScript in your layout.

<%= javascript_include_tag :defaults, "nested_form" %>

Usage

Imagine you have a Project model that has_many :tasks. To be able to use this gem, you’ll need to add accepts_nested_attributes_for :tasks to your Project model. If you don’t have the accepts_nested_attributes_for :tasks you’ll get a Missing Block Error.

This will create a tasks_attributes= method, so you may need to add it to the attr_accessible array. (attr_accessible :tasks_attributes)

Then use the nested_form_for helper method to enable the nesting.

<%= nested_form_for @project do |f| %>

You will then be able to use link_to_add and link_to_remove helper methods on the form builder in combination with fields_for to dynamically add/remove nested records.

<%= f.fields_for :tasks do |task_form| %>
  <%= task_form.text_field :name %>
  <%= task_form.link_to_remove "Remove this task" %>
<% end %>
<p><%= f.link_to_add "Add a task", :tasks %></p>

SimpleForm and Formtastic Support

Use simple_nested_form_for or semantic_nested_form_for for SimpleForm and Formtastic support respectively. This is feature is not yet in a Gem release but is in the Git repo.

Partials

It is often desirable to move the nested fields into a partial to keep things organized. If you don’t supply a block to fields_for it will look for a partial and use that.

<%= f.fields_for :tasks %>

In this case it will look for a partial called “task_fields” and pass the form builder as an f variable to it.

Events

If you are using jQuery, nested:fieldAdded and nested:fieldRemoved events are triggered on the form element after adding and removing fields.

Enhanced jQuery JavaScript template

You can override default behavior of inserting new subforms into your form. For example:

window.nestedFormEvents.insertFields = function(content, assoc, link) {
  return $(link).closest('form').find(assoc + '_fields').append($(content));
}

Project Status

Unfortunately I have not had time to actively work on this project recently. If you find a critical issue where it does not work as documented please ping me on Twitter and I’ll take a look.

Special Thanks

This gem was originally based on the solution by Tim Riley in his complex-form-examples fork.

Thank you Andrew Manshin for the Rails 3 transition, Andrea Singh for converting to a gem and Peter Giacomo Lombardo for Prototype support.

Andrea also wrote a great blog post on the internal workings of this gem.

Thanks Pavel Forkert for the SimpleForm and Formtastic support.