Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Best practices for loading page content via AJAX request in Rails3?

Suppose you have a page with two columns of content. For whatever reason, you wish to retrieve the HTML content of one of those columns after the page has loaded, via an AJAX request. The user does not need to take an action to make the content load (no link clicking or form submissions), it just happens automatically.

I can easily do this by returning an empty placeholder div in the main response

<div id="pink-dancing-elephants"></div>

and then add a little jQuery to the page

$.ajax({
    url: "/elephants/dancing/pink",
    cache: false,
    success: function(html){
      $("#pink-dancing-elephants").append(html);
    }
});

and have the action that responses to /elephants/dancing/pink return the corresponding blob of HTML.

This all works fine, but I'm wondering if I'm missing some Rails3 feature that would make this easier. E.g. I'm searching for the ability to be able to just put something like the following in the main view and have the rest of it happen by "magic"

<%= render :url=>"/elephants/dancing/pink", :remote => true %>

Am I missing something?

like image 233
cailinanne Avatar asked Jun 02 '11 11:06

cailinanne


People also ask

How can I load a page in AJAX?

load(URL,data,callback); The required URL parameter specifies the URL you wish to load. The optional data parameter specifies a set of querystring key/value pairs to send along with the request. The optional callback parameter is the name of a function to be executed after the load() method is completed.

What kind of information can be received by an AJAX request?

AJAX stands for Asynchronous JavaScript And XML. In a nutshell, it is the use of the XMLHttpRequest object to communicate with servers. It can send and receive information in various formats, including JSON, XML, HTML, and text files.

Why do we use content type in AJAX?

The ajax() function is used to perform an asynchronous HTTP request to the server and by using the contenttype option it describes to the server what data is sending and expecting to process it. contenttype- This is an optional option.


2 Answers

I am using the method described in @cailinanne's comment to Dan L's post and it's worked well for me. I like the readability of the data tag that's attached to the div. Within your html you can see exactly what's going to load into that div, and you don't have to add any new JS if you want to add this functionality to multiple divs or pages.

Taking from this article: http://tech.thereq.com/post/16479390885/loading-page-content-via-ajax-in-rails-3-1

The simplest way to do this to use the jQuery load method.

$("#comments").load("/blogs/2/comments");

The awkward part is the AJAX path (/blogs/2/comments) which clearly changes according to which blog we are viewing. If we followed the jQuery documentation exactly, we could just plop a script tag in the middle of our HTML body, so that in our template file we might have something like

# show.html.erb

<div id="comments"></div>
<script>
  $("#comments").load("<%= blog_comments_path(@blog)%>");
</script>

Yuck. Not a fan of javascript mixed into my template files.

What to do instead? Follow the pattern suggested by Rails UJS and take advantage of the new HTML data- attributes.

First, when you want to load AJAX content in your page, do the following in your template

#show.html.erb

<div id="comments" data-load="<%= blog_comments_path(@blog. :format => :js)%>">
</div>

Second, add the following to your application.js

# application.js or any JS file loaded within application.js

$("div[data-load]").filter(":visible").each(function(){

  var path = $(this).attr('data-load');
  $(this).load(path);

});

Third, set up a route that matches a get request to blog_comments (type rake routes to see how your routes are named)

# routes.rb

# ajax load at page load
  get "/blogs/comments" => "blogs#comments"

And voila! Your comments div will magically be filled by whatever is returned by the /blogs/3/comments path!

like image 198
Danny Avatar answered Sep 19 '22 15:09

Danny


I think what I originally outlined is actually the best approach.

First put an empty, placeholder div in your main view

<div id="recent_posts"></div>

and then add a little jQuery to the page

$.ajax({
    url: "/posts/recent",
    cache: false,
    success: function(html){
      $("#recent_posts").append(html);
    }
});

and have the action that responses to /posts/recent return the blob of HTML that you want to have fill up the div. In the action that is invoked by the AJAX request, you'll want to render with :layout => false to keep the returned blob of HTML from including the entire frame. E.g.

# posts_controller.rb
def recent
  @recent_posts = #whatever
  render :layout => false
end

This would render the template in views/posts/recent.html.erb and then the jQuery will take care of inserting the rendered contents into your placeholder div.

like image 21
cailinanne Avatar answered Sep 21 '22 15:09

cailinanne