Get updates

Scott Q&A: How Rails Returns JavaScript to Execute on Ajax Request?

On the road to a better to-do list application, I need to start with a solid base and advance one step at a time. That base includes simple ajax functionality so list items can be manipulated without a full page reload.

Question: When the user clicks an Ajax link to destroy a list item, how do I have Rails return JavaScript code to be executed which will hide that item?

As soon as I have the answer I’ll post it here…

Answer: It turns out my trusty rails book had the answer after all. There are three points to consider in order to make this work.

  1. In the destroy action the last statement should be render(:partial…) and the partial view need generate only the desired JavaScript code.
  2. Use :complete instead of :update in the link_to_remote statement.
  3. The :complete callback can execute the rendered JavaScript code by using eval(response.responseText)

So the controller’s destroy action could look something like this:
def destroy
  @dead_list_item_id = params[:id]
  render(:partial => 'delete_item', :object => @dead_list_item_id, :layout => false)

Note I’m sticking the list_item’s id in another variable to pass to the partial template (and this code doesn’t have any error checking), as the item is being deleted before it can be passed to the partial.

The _delete_item.rhtml partial could look something like this:
Element.remove('<%= @dead_list_item_id %>');

Of course, it’s customary (and useful) to give the user more obvious feedback, which is where the wonderful Scriptaculous effects come in. Just make _delete_item.rhtml something like this:
new Effect.Squish('<%= @dead_list_item_id %>');

Though it’s trivially unimportant, I have the urge to call Element.remove after the effect completes in order to remove the node completely instead of just hiding it. Calling them both back to back simply removes it right away while the effect is starting up, so it’s apparent a custom JavaScript function could be in order… maybe I’ll write that one another time.

Leave a Reply