-
Notifications
You must be signed in to change notification settings - Fork 506
Handle AJAX form submissions
At some point you may want to use nested_form with an AJAX form. Maybe you have a really long form where you want to give users the option to save after a few different steps, but still want to keep them on the same page without reloading. This isn't initially clear on how to do this with nested_form, and without the proper setup in place you will run into errors (adding duplicate entries, running into errors when trying to delete items, ets.). When an item is added to your form via nested_form it is added with a randomly generated id, which will not match your database. This behavior is expected because it will keep items in your form unique. But when submitting via AJAX, if you do not re-render your form, you will run into the issues previously stated. In order to handle this elegantly, we simply want to re-render a form partial. So, to start, we want to make sure that our form is in a partial (if it isn't, move it into a partial). Then in the controller where you will handle the AJAX request, simply render that partial (passing in any locals that you need to, and making sure to set the layout to false so only our form is returned).
if @user.update_attributes(user_attributes)
if request.xhr?
render :partial => 'form', :layout => false, :locals => { :user => @user }
else
...
end
else
...
end
For the JavaScript, we will listen for the success event of the AJAX call and replace the form with our newly render form partial. In order for this to work correctly, we need to have a containing element for our for so that we can simply replace the content of that element with our new form.
$("#my_form").on("ajax:success", function(e, data, status, xhr) {
$('#my_form_container').html(data);
});
NOTE: This isn't the only way to handle an AJAX submit of a form, just the easiest (at least from my experience). The main reason to handle it this way is to handle the newly created / deleted items. When the form is replaced, the items that were deleted are now removed (not just hidden for deletion), and the items that were created now have a rails id associated with them instead of a randomly generated id.