3.4. Ajax FormsTo Ajaxify this form, all we need to do is replace the form_tag helper with its form_remote_tag alternative and add a place for the response to be inserted: <%= form_remote_tag :update => "reversed", :url => { :action => 'reverse' } %> <p>Text to reverse: <%= text_field_tag 'text_to_reverse' %></p> <p ></p> <p><%= submit_tag 'Reverse!' %></p> <%= end_form_tag %> The options here should look familiar, because they're exactly the same as the options for link_to_remote. The :update option specifies which HTML element will be updated with the Ajax response, and :url provides the URL for the Ajax request. Try out the new form, and you'll get something like Figure 3-5. As you can see, that won't do. Figure 3-5. Oops, that's not rightThe layout is being rendered twice, heading and all. The problem is that every action (such as our reverse) will render within layouts/application.rhtml unless told otherwise. To specify a layout (or turn them off), the action needs an explicit render statement: def reverse @reversed_text = params[:text_to_reverse].reverse render :layout => false end With that line added, try the Ajax form again, and everything should work as expected, as seen in Figure 3-6. Figure 3-6. Rendered without layoutThe rendered result of the form_remote_tag uses Prototype's Ajax.Updater, just like link_to_remote did: <form action="/chapter3/reverse" method="post" onsubmit="new Ajax.Updater('reversed','/chapter3/reverse', {asynchronous:true, evalScripts:true, parameters:Form.serialize(this)}); return false;"> Just as the onclick attribute hijacks a link, onsubmit hijacks the behavior of forms. The Ajax counterpart to form_for (the helper for creating forms to work with model objects) is remote_form_for. Using it works exactly like form_for, except that the options hash may also contain the usual Ajax options, such as :update and :complete. |