What is "Nested form In Rails 3" and when do we use it?
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.Example :-
Suppose we have two models "Profile" and "Picture". We want to get all the information in the same form. In this case we got to use "Nested Form".
What are the steps to setup nested form gem in your app?
Add it to your Gemfile (by writing gem "nested_form" to you Gemfile) then run bundle to install it .
Asset Pipeline Setup
And then add it to the Asset Pipeline in the application.js file://= require jquery_nested_form
and don't forget to do $ bundle install
Non Asset Pipeline Setup
If you do not use 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" %>
How do we use this in our project?
Model Setup
class Profile < ActiveRecord::Base
has_many :pictures, :as => :imageable
accepts_nested_attributes_for :pictures, :allow_destroy => true, :reject_if => Proc.new { |c| c['image'].blank? }
Here we have Profile model which has many pictures. We want to accept attributes of Picture model in Profile model and we want to allow nested attributes to be destroyed (so :allow_destroy => true). We don't want entry in DB if no image is selected in the form(so :reject_if => Proc.new { |p| p['image'].blank? })
View Setup
<%= nested_form_for @profile, :url => admin_profile_path(@profile), :method => :post, :multipart => true, :html => { :class => "new-profile" } do |form|-%>
<%= form.text_field :name, :placeholder=>"Profile Name" %>
<%= form.fields_for :pictures, @product.pictures.new do |picture| %>
<%= picture.file_field :image %>
<%= picture.link_to_remove raw(" "), :class => "red button", :alt => "Remove" %>
<% end -%>
<%= form.link_to_add "Add New Picture", :pictures, :class => 'small blue button' %>
<%= form.submit 'Update', :class => 'button green' %>
Here we have a simple view to understand nested form view.
We have got a form object for profile. We want to take a name for profile so we have a form.text_field.
Now in the same form we want to take pictures related to this profile so we have use form.fields_for :pictures . This fields for help will generate fields for picture which user wants to upload for this profile.
Nested forms provides two very useful and nice helpers.
1. picture.link_to_remove :- This helper provides a link which will remove that particular row of picture fields in which it is present. This must be inside picture object scope (which is obvious :P ).
2. form.link_to_add :- This helper provides a link which will add new fields for picture. This must be outside of picture and inside of form object.
Using Partial
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.
<%= form.fields_for :pictures %>
In this case it will look for a partial called "picture_fields" and pass the form builder as an form variable to it.
JavaScript events
So here comes JS. This is very much useful when you are using nested form and you would need this for sure if you want to make you form smart and cool.
Now after adding/removing picture fields you want to some JS things so need call backs. After adding or removing the field a set of custom events is triggered on this field. Using form example from above, if you click on the "Add a picture" link, nested:fieldAdded and nested:fieldAdded:tasks will be triggered, while nested:fieldRemoved and nested:fieldRemoved:tasks will be triggered if you click "Remove this picture" then.
$(document).on('nested:fieldAdded', function(event){
// this field was just inserted into your form
var field = event.field;
// it's a jQuery object already! Now you can find date input
var dateField = field.find('.date');
// and activate datepicker on it
dateField.datepicker();
});
And here you go. This was a simple explanation about nested form (specially for beginners). I have shared my view on how to use nested form. Your comments are most welcome.
Spacial thanks to Nested form documentation on GitHub.
Comments
Post a Comment