Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rails/AJAX partial rendering

I made an application that has a project model. The model has some information stored in it, and a user can add comments to the project (using the comment model). In the show view of a project I want the user to be able to switch between an "info" partial (containing the project information, and a "comment" partial (containing the comments wrote on the project). I want to do this using AJAX. So I will have two buttons: Information & Comments.

Now I know how to render a partial based on a "remote link", but I'll also have to find out which link was clicked. So far I can render one partial when one link is clicked like so:

// In show.html.haml

= link_to("Information", :project, :id => "link_one", :remote => true)
= link_to("Comments", :project, :id => "link_two", :remote => true)

#partial_window


// In show.js.haml
$("#partial_window").html("#{j(render("comments"))}")

Now this renders the _comment.html.haml partial when I click on one of the links. What I need to know is how to check which link was clicked, and then render the appropriate partial: _info.html.haml or _comments.html.haml.

Thanks in advance for your help!

like image 763
Stefan Hagen Avatar asked Dec 18 '12 20:12

Stefan Hagen


People also ask

What is render partial in Rails?

Rails Guides describes partials this way: Partial templates - usually just called "partials" - are another device for breaking the rendering process into more manageable chunks. With a partial, you can move the code for rendering a particular piece of a response to its own file.

How can you tell Rails to render without a layout?

2.2. By default, if you use the :plain option, the text is rendered without using the current layout. If you want Rails to put the text into the current layout, you need to add the layout: true option and use the . text. erb extension for the layout file.

What is remote true in Rails?

remote: true is really just telling the browser to not refresh the page. Do the action that you would normally do, but don't do anything to the page.

How do you add Ruby code inside Rails views and have its result outputted in the HTML file?

The most popular way to add Ruby code inside Rails views is with embedded Ruby (ERB). Files with embedded Ruby have the extension . html. erb and these files can have any amount of regular html markup.


1 Answers

Something like this should work. We are going to use nested routes. Check out ryan's screencast (a little old, but it gets the point across) or this more updated version about nested forms (uses the same principles). You'll have to pay for the updated version, but I find my RailsCast subscription to be more than worth the $9/month. Also, here are the docs for examples.

config/routes.rb

resources :projects do
  resources :comments
end

comments_controller.rb

class CommentsController < ApplicationController
  def index
    project = Project.find params[:project_id]
    @comments = project.comments
    respond_to do |format|
     format.html #responds with default html file
     format.js #this will be the javascript file we respond with
    end
  end
end

views/comments/index.js.erb

$('#holderDiv').empty().append('<ul> <%= j render @comments %> </li>')

This uses a nifty thing of rails that looks for a comment partial and renders it for each comment in @comments. The j helper escapes javascript and pretty much inserts the rendered partial into the append function.

views/comments/_comment.html.erb

 <li> <%= @comment.description %> </li>

So we've now cleared the #holdingDiv and inserted our comments. For information, maybe something like this:

projects_controller.rb

class ProjectsController < ApplicationController
  def index
    @project = Project.find params[:id]
    respond_to do |format|
      format.html
      format.js
    end
  end
end

views/project/index.js.erb

 $('#holderDiv').empty().append('<%= j render 'information', information: @project.information %>')

views/project/_information.html.erb

<h2>
  <%= information.title %>
</h2>
<p>
  <%= infomration.details %>
</p>

Then, your remote links would be something like:

= link_to("Information", @project, :remote => true)
= link_to("Comments", project_comments_url(@project), :remote => true)

I had to make some assumptions about what your data structures were. Let me know where I've confused you.

Also, I am sure I have some typos, sorry for that. I did not test this, just went off the top of my head.

like image 129
Tyler DeWitt Avatar answered Sep 24 '22 19:09

Tyler DeWitt