Rails now provides(as of 0.11.0) a number of useful tools to simplify working with “Ajax”.
The API documentation is available: http://rails.rubyonrails.com/classes/ActionView/Helpers/JavaScriptHelper.html
The example given here is to delete records, but you could easily modify it to change status, add records, or even render a partial and dump it into a div.
You must include the javascript code in your view for the Ajax functions to be available in that view. The best place for this is in the <head> tag like so:
define_javascript_functions (the ok method)
<html>
<head>
..
<%= define_javascript_functions %>
..
</head>
<body>
define_javascript_functions and javascript_include_tag ?define_javascript_functions pastes all of the required Javascript code right into your view. All 21kb of it. javascript_include_tag on the other hand simply creates a <script> tag that links to the javascript files like prototype.js, controls.js, etc rather than printing it all out in the HTML <head>.
javascript_include_tag (the best method)
<html>
<head>
..
<%= javascript_include_tag :defaults %>
</head>
...
produces
<html>
<head>
..
<script type="text/javascript" src="/javascripts/prototype.js"></script>
...
<script type="text/javascript" src="/javascripts/controls.js"></script>
</head>
...
Using javascript_include_tag allows for quicker downloads since the script can be cached by the browsers instead of adding an extra ~20kb to every page.
There are two options here. Either you can return a snippet of HTML and fill a container (like a div or table cell) with it; and/or, you can run a javascript function.
Javascript Functions
You’ll want to create the javascript functions if you want the code to do anything. Following on from the other Ajax howto HowToUseAjaxToRemoveARecordWithoutReloadingThePage, here’s similar functionality but with the helpers.
First, let’s say we have some divs with items in them, and a “remove” link on each div.
<div id="animal<%= animals.id%>">
<%= animals.name %>
<a href='#'>(remove)</a>
</div>
The javascript function should add the words, “Removing..” to the div, remove the database item, then hide the div once it’s done. This gives the appearance of being “deleted”, and stops the user refreshing the page (which will cancel the http request).
To hide the div, we’ll just empty its contents.
Now for the javascript to change the text of the div so we have some status goin’ on. This function allows you to pass a node, or a string containing the id of a node.
function status(node)
{
if (!node) return false;
if (typeof node == 'string')
node = document.getElementById(node);
if (node) node.innerHTML = 'Removing ..' + node.innerHTML
}
Note: Using the function name ‘status’ throws an error in Safari.
Calling the request
Now for the Rails happiness!
Replace the link in the div with this simple code: (don’t worry, we’ll explain it more below)
<%= link_to_remote "Remove",
:url=>{
:controller=>"animals",
:action=>"destroy",
:id=>animal.id},
:update=>"animal#{animal.id}",
:loading=>"status('animal#{animal.id}')"
%>
Wtf?
The link_to_remote arguments are as follows:
The last 5 relate to the status of the HTTP request; however, not all of these are compatible across all browsers, and all you can really rely on are :loading, and :complete (status 1, and 4, respectively).
<div id=" #{animal#id}">, so the view for animals will be an empty file.url_for or link_to.There are more functions (such as link_to_function) as well as a form serializer in this wonderful helper library..
Returns a form tag that will submit using XmlHTTPRequest in the background instead of the regular reloading POST arrangement. This is useful when using <input> buttons instead of just text links with link_to_remote.
Just start your form with:
<%= form_remote_tag :update => 'id_of_element_where_you_like_the_response_to_go',
:url => { :action => 'your_action' } %>
There is also an option :position (before, after, top, bottom) which places the response html to those positions relative to the element you specify with :update. These positions indicate where in the DOM the returned html is to be inserted, whether inside the named element or outside.
This will automagically make the form work with Ajax remoting. No special changes need to be made to your submit button. All variables will be available in @params.
You’ll need to modify the action so that it returns the correct response. You may even need a new action.
If you are deleting a record, you’ll just return an empty string so that the DIV is effectively removed.
render_text ""
If you are updating or inserting a record, you’ll want to return a full record, so, a good way to do this, is to have the DIV contents rendered as a partial ( <%= render_partial "mydiv", @animal %> ) and render the exact same partial from your action. Less programming!
Rails now provides(as of 0.11.0) a number of useful tools to simplify working with “Ajax”.
The API documentation is available: http://rails.rubyonrails.com/classes/ActionView/Helpers/JavaScriptHelper.html
The example given here is to delete records, but you could easily modify it to change status, add records, or even render a partial and dump it into a div.
You must include the javascript code in your view for the Ajax functions to be available in that view. The best place for this is in the <head> tag like so:
define_javascript_functions (the ok method)
<html>
<head>
..
<%= define_javascript_functions %>
..
</head>
<body>
define_javascript_functions and javascript_include_tag ?define_javascript_functions pastes all of the required Javascript code right into your view. All 21kb of it. javascript_include_tag on the other hand simply creates a <script> tag that links to the javascript files like prototype.js, controls.js, etc rather than printing it all out in the HTML <head>.
javascript_include_tag (the best method)
<html>
<head>
..
<%= javascript_include_tag :defaults %>
</head>
...
produces
<html>
<head>
..
<script type="text/javascript" src="/javascripts/prototype.js"></script>
...
<script type="text/javascript" src="/javascripts/controls.js"></script>
</head>
...
Using javascript_include_tag allows for quicker downloads since the script can be cached by the browsers instead of adding an extra ~20kb to every page.
There are two options here. Either you can return a snippet of HTML and fill a container (like a div or table cell) with it; and/or, you can run a javascript function.
Javascript Functions
You’ll want to create the javascript functions if you want the code to do anything. Following on from the other Ajax howto HowToUseAjaxToRemoveARecordWithoutReloadingThePage, here’s similar functionality but with the helpers.
First, let’s say we have some divs with items in them, and a “remove” link on each div.
<div id="animal<%= animals.id%>">
<%= animals.name %>
<a href='#'>(remove)</a>
</div>
The javascript function should add the words, “Removing..” to the div, remove the database item, then hide the div once it’s done. This gives the appearance of being “deleted”, and stops the user refreshing the page (which will cancel the http request).
To hide the div, we’ll just empty its contents.
Now for the javascript to change the text of the div so we have some status goin’ on. This function allows you to pass a node, or a string containing the id of a node.
function status(node)
{
if (!node) return false;
if (typeof node == 'string')
node = document.getElementById(node);
if (node) node.innerHTML = 'Removing ..' + node.innerHTML
}
Note: Using the function name ‘status’ throws an error in Safari.
Calling the request
Now for the Rails happiness!
Replace the link in the div with this simple code: (don’t worry, we’ll explain it more below)
<%= link_to_remote "Remove",
:url=>{
:controller=>"animals",
:action=>"destroy",
:id=>animal.id},
:update=>"animal#{animal.id}",
:loading=>"status('animal#{animal.id}')"
%>
Wtf?
The link_to_remote arguments are as follows:
The last 5 relate to the status of the HTTP request; however, not all of these are compatible across all browsers, and all you can really rely on are :loading, and :complete (status 1, and 4, respectively).
<div id=" #{animal#id}">, so the view for animals will be an empty file.url_for or link_to.There are more functions (such as link_to_function) as well as a form serializer in this wonderful helper library..
Returns a form tag that will submit using XmlHTTPRequest in the background instead of the regular reloading POST arrangement. This is useful when using <input> buttons instead of just text links with link_to_remote.
Just start your form with:
<%= form_remote_tag :update => 'id_of_element_where_you_like_the_response_to_go',
:url => { :action => 'your_action' } %>
There is also an option :position (before, after, top, bottom) which places the response html to those positions relative to the element you specify with :update. These positions indicate where in the DOM the returned html is to be inserted, whether inside the named element or outside.
This will automagically make the form work with Ajax remoting. No special changes need to be made to your submit button. All variables will be available in @params.
You’ll need to modify the action so that it returns the correct response. You may even need a new action.
If you are deleting a record, you’ll just return an empty string so that the DIV is effectively removed.
render_text ""
If you are updating or inserting a record, you’ll want to return a full record, so, a good way to do this, is to have the DIV contents rendered as a partial ( <%= render_partial "mydiv", @animal %> ) and render the exact same partial from your action. Less programming!