Render a partial view in Rails is very straighforward. If you have a partial view file named _form.html.erb
, in your view page, you could just do <%= render "form" %>
. That's the most basic partial rendering. What about there are variables involved or the partial view needs to be refreshed triggered by an ajax call?
Let's look at a slightly more complicated case. First this is partial view mark up _restaurant_list.html.erb
<table>
<tr>
<td onclick="changeVote('up', <%= mrs.id %>)"><img alt="upvote" src=<%=image_path("upvote.png")%>>
</td>
<td rowspan="3">
<%= mrs.restaurant.name %>
</td>
</tr>
<tr>
<td><%= vote_count %></td>
</tr>
<tr>
<td onclick="changeVote('down', <%= mrs.id %>)"><img alt="downvote" src=<%=image_path("downvote.png")%>>
</td>
</tr>
</table>
There is a variable in the partial view, named <%=mrs%>
. How is this variable passed in there? Here is show.html.erb
page, where partial view's rendered.
<p>
<strong>Title:</strong>
<%= @meeting.title %>
</p>
<p>
<strong>Description:</strong>
<%= @meeting.description %>
</p>
<p>
<strong>Date:</strong>
<%= @meeting.date.in_time_zone %>
</p>
<div id="restaurant_table">
<%= render partial: "restaurant_list", locals: {mrs: @meeting_mrs %>
</div>
<br>
<%= link_to 'Edit', edit_meeting_path(@meeting) %> |
<%= link_to 'Back', meetings_path %>
<%= render partial: "restaurant_list", locals: {mrs: @meeting_mrs} %>
is how you pass the variable to the partial view.
Now let's say each time a user presses upvote/downvote image, it triggers an ajax call to update the votes in database. We will have an ajax call like this:
function changeVote(vote, mrs_id) {
var id = '<%=@meeting_id%>';
var url = "../meetings/" + id + "/" + "update_vote";
$.ajax({
url: url,
type: "GET",
data: {
mrs_id: mrs_id,
vote: vote,
id: id
},
datatype: "json",
success: function(data, textStatus, xhr){
...
},
error: function(request, status, error){
console.log(error);
},
});
}
The goal is that when the call comes back, it refreshes the partial view. The method that ajax call invokes:
def update_vote
mrs_id = params[:mrs_id]
vote = params[:vote]
id = params[:id]
umv = Vote.new(:meeting_restaurant_selection_id=>mrs_id, :vote=>vote)
umv.save
end
In order to make the partial view refresh correctly, the method need to render all the data back to the page. At the end of update_vote
method, we need to specify:
mrs = Meeting.find(id).meeting_restaurant_selections
render :partial=>"restaurant_list", :locals=>{:mrs=>meeting_mrs}
Also, inside the ajax call, when the call is successful, it should pass in the entire data:
success: function(data, textStatus, xhr){
$("#restaurant_table").html(data)
},
There, it completes the whole process.
In summary, there are three pieces to make it work right.
-
The html markup page where partial view is rendered passes varialbes via
locals=>{variable name=>value}
-
The ajax call return has to put the data in html context using: (using jquery as an example)
$(<id>).html(data)
-
ajax call method returns partial and do remember to pass in necessary params
render :partial=>"restaurant_list", :locals=>{:mrs=>meeting_mrs}