Reputation: 16215
In creating a ruby on rails / jquery app, there's a part of a page that is time-consuming to generate.
I want to change how the page is loaded so that most of the page loads right away, and a placeholder is reserved for the time-consuming part to load asynchronously, and be injected into the page with ajax / jquery when it is finished.
What I have now (simplified):
app/views/sample/show.html.erb:
<div id="theResult">
<%= render :partial => 'calculate', :object => @org) %>
</div>
and the partial will use some parts @org to generate some content (hitting another external REST service).
app/views/sample/_calculate.html.erb
<%
# code to take org and turn it into content
%>
<!--...html to display results here -->
I realize this is probably breaking proper MVC architecture rules since my partial seems to have too much logic, and would like to clean that up as well...
So I guess I have two questions in one: (1) how do I get this to work, and (2) how should I clean this up to follow good ruby/rails/mvc practices?
Upvotes: 46
Views: 26533
Reputation: 12893
There's a simpler way to do it compared to @cailinanne.
Using her same example, but I tend to use this technique to update a div, so my div would first have that partial:
<div id="pink-dancing-elephants">
<%= render "elephants/dancing", elephant: some_thing %>
</div>
But then use the jQuery load method:
$("#pink-dancing-elephants").load("/elephants/dancing");
This will return the whole partial. Be sure to use layout: false, and optionally set params. I tend to use a partial like this
# elephants_controller.rb
def dancing
render "elephants/_dancing",
locals: { elephant: some_thing },
layout: false
end
This would render the template in views/elephants/_dancing.html.erb.
NOTE the underscore in the partial name for the controller method and how you don't use it when calling render in the view.
Upvotes: 10
Reputation: 8372
First put 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",
cache: false,
success: function(html){
$("#pink-dancing-elephants").append(html);
}
});
and have the action that responses to /elephants/dancing/pink 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.
# elephants_controller.rb
def dancing
@elephants = #whatever
render :layout => false
end
This would render the template in views/elephants/dancing.html.erb.
Upvotes: 72