July 30, 2011

Ajax Partial Loading

In today's applications, it's common to use AJAX to load dynamic parts of a website without having to do a full page refresh. With Rails, it's easy to template these changes instead of using Javascript to update the DOM structure manually.

Imagine you have some portion of the page (say, a list of users that already has it's own partial) that you want to dynamically update with AJAX. You could: A) In your AJAX callback, construct the DOM elements manually and append them, like so:

var userList = $("#mylist");
$("<li>Amber Feng</li>").appendTo(userList);

This works perfectly fine in simple cases. But what if you later want to update the list elements to have a class named "user", and/or add a couple of spans inside of that list element to hold things like profile pictures, latest tweets, etc?

You'd have to change the partial to reflect that, for when the page is first loaded, and change your Javascript callback to reflect the changes for when you use an AJAX call to append things to the list as well.

This isn't DRY - and it's just plain messy to do manual DOM construction and appending. Instead, do this: B) Since you have a partial for the list of users anyway, just take advantage of this and have Rails generate the HTML for you to append. Stick a method in your controller for passing you back the html:

def render_partial
  render :json => {
    :html => render_to_string({
      :partial => "mypartial",
      :locals => {:v => v}

And just append the callback data to the container that your list is in.

  {params: params},
  function(data) {

Voila! Now, if you ever need to change the template for what the user's list is supposed to look like, you do it in one place (the Rail's partial, in case you haven't caught on yet), and that will automatically be used every time the page is loaded and every time your AJAX needs to update the list.

Caution: This does put somewhat of a heavier load on the server because you're hitting up the Rails application stack again every time you need to change something via AJAX on a page instead of adding it client side via Javascript.