MarkUs Blog

MarkUs Developers Blog About Their Project

Replacing form_remote_tag in rails 3

without comments

form_remote_tag has been deprecated in rails 3, and thus shouldn’t be used anymore. But what do we replace it with?

The main idea is that we can use form_tag with :remote => true passed in as an argument for the same effect. eg:


<%= form_remote_tag :url => global_actions_assignment_groups_path(@assignment) do %>

becomes:

<%= form_tag url_for(global_actions_assignment_groups_path(@assignment)),
:remote => true do %>

Simple enough. But what if we want some Ajax callbacks attached to this? For instance, what if we originally had this:

<%= form_remote_tag :url => global_actions_assignment_groups_path(@assignment),
:loading => "thinking();",
:complete => "done_thinking();" do %>

Now things get a little but trickier. Let look at the html that this generates:

<form onsubmit="new Ajax.Request('/en/assignments/2/groups/global_actions', {asynchronous:true, evalScripts:true, onComplete:function(request){done_thinking();}, onLoading:function(request){thinking();}, parameters:Form.serialize(this)}); return false;" method="post" action="/en/assignments/2/groups/global_actions" accept-charset="UTF-8">

Notice that the javascript is appearing inline, making things annoying to read. In rails 3, we use UJS (Unobtrusive Javascript) to separate this out. First we need to take out the Ajax callbacks and put in the :remote => true tag:


<%= form_tag url_for(global_actions_assignment_groups_path(@assignment)),
:remote => true do %>

and the html this generates:

<form method="post" data-remote="true" action="/en/assignments/2/groups/global_actions" accept-charset="UTF-8">

This is way simpler, but how do we achieve the same end result? The magic is happening with the data-remote="true" line. Rails UJS binds to any forms with that attribute and submits them via AJAX instead of POST. Now we just need to write event listeners to the appropriate Ajax callbacks. First we should give our form an id:


<%= form_tag url_for(global_actions_assignment_groups_path(@assignment)),
:id => "global_action_form",
:remote => true do %>

and then we can write the listeners:


<script type='text/javascript'>
$("global_action_form").observe('ajax:after', function(evt, status, data, xhr) {
thinking();
});


$("global_action_form").observe('ajax:complete', function(evt, status, data, xhr) {
done_thinking();
});
</script>

Note that this code should appear after the form that it is hooking to. Note that a UJS Ajax call has 6 events that can be hooked to:

ajax:before – Before the Ajax call
ajax:loading – before ajax call, but after XmlHttpRequest object is created
ajax:after – after ajax call is sent (note: not after it returns)
ajax:success – successful ajax call
ajax:failure – failed ajax call
ajax:complete – completion of ajax call (after ajax:success and ajax:failure)

Thats it. We now have the same end result using UJS.

Written by Erik

November 23rd, 2011 at 10:27 am

Posted in Uncategorized

Leave a Reply