0

Thanks for your time!

I get some reports data on my hand and I want to present these data on the web. The view of the HTML will be divided into two parts, the left part and the right part. There's a tree view in the left part consisting of the report names. In the right part presents the contents of the report.

What I want to achieve is when I click the report name on the left part, it will call an Action in the Controller, and passed the report name as parameter. The Action will fetch the data from the database and represent the data in the right part. And now I am stuck on how to realize this kind of view.

I've Googled a lot on the Internet and found Frameset, Partials or Ajax may capable of this. Because I've never developed web applications before and also new to Rails. So can anyone give me some advise or suggestion?

Things I've already known :

  1. I've used Frameset to accomplish a view like this. But I found it needs a lot of .html files and all these .html files are static. And many people don't suggest it at all.

  2. Then I've Googled Partials. But it seems Partials don't call the Action. It directly loads the _partials.html.erb to the main view. And besides, how can I control the layout? Using CSS?

  3. I've never used Ajax.

mCY
  • 2,731
  • 7
  • 25
  • 43
  • This is a really broad question. I think you should check out the http://www.guides.rubyonrails.org – wpp Oct 24 '12 at 10:50

2 Answers2

4

If you want a fluid, seamless transition between one report and another, you should use both AJAX and Partials.

The way that it works is something like:

  • Make a left column in the html that has some links
  • Make the right column inside a partial
  • Assign the links to jQuery listeners to call the AJAX.

I'll put a bit of code here to show how it works:

Controller:

def index
    reports = Report.all
    if params[:report_id]
        reports = Report.find(params[:report_id]
    end
    respond_to do |format|
        format.html
        format.js { render :template => "update_reports" }
    end
end

update_reports.js.erb (in the same folder as the report views):

$('#report_viewer').html('<%= escape_javascript render :partial => "report_detail" %>');

In your view:

<div style=float:left>
    <ul>
        <li><%= link_to "Some report", "#", :class => "ajax" %></li>
    </ul>
</div>
<div style=float:right id="report_viewer">
    <%= render :partial => "report_detail" %>
</div>

<script type='text/javascript'>
    $(document).ready(function() {
        $(".ajax").click(function(e) {
            $(this).ajax("your route to the action");
        }
    });
</script>

I think it's basically this, now let me explain a few things:

  • I don't remember if you have to do this, but in my case I created a new custom route to force the call to the action to be a json call instead of a html one. You can do this by adding :format => "js" to your route
  • You must name all your partials like "_yourname.html.erb". Rails won't recognize partials without the leading underscore.
  • In the controller, everything that comes after "format.js" is optional, you don't need to specify the template name, and if you don't Rails will look for the file index.js.erb.
  • The update_reports.js.erb file is basically a callback javascript that executes to update the current page. It finds the div where the partial is, and updates it rendering a new partial with the new report.
  • In the view, the link to change the report don't need to be a link at all if you're using the jQuery.click listener, but if it is a link, it must have the href as "#", or else the browser will just try to redirect to that location.
  • There are several ways to hook your link to the ajax function, I just chose the one I like it better, but you also could have a named function and call it in the html tag "onClick='yourFunction()'".
  • You need jQuery to call ajax like this. If you're sing Rails 3.0 or lower, you should replace the default Prototype with jQuery, because it's much better (IMHO), but I think prototype also have some ajax features.
  • It may seem complicated, but once you get the idea of it it'll become simple as writing any other action.
  • In the js callback file you could also add an animation to smooth the transition, like a fading. Look for the jQuery fade function for more info on this.
Rodrigo Castro
  • 1,573
  • 14
  • 38
3

This is quite an open question so don't take this answer verbatim, but merely as a guide.

app/views/layouts/reports.html.erb

<!DOCTYPE html>
<html itemscope itemtype="http://schema.org/">
<head>
   # omitted
</head>
<body>
<div id="body-container">
  <div id="left-column">
    <ul id="reports-list">
      <% for report in @reports %>
        <li><%= link_to report.name, report %></li>
      <% end %>
    </ul>
  </div>
  <div id="right-column">
    <%= yield %>
  </div>
</div>
</body>
</html>

app/controllers/reports_controller.rb

class ReportsController < ApplicationController

  before_filter { @reports = Report.all }

  def index

  end

  def show
    @report = Report.find(params[:id])
  end

  def edit
    @report = Report.find(params[:id])
  end

  def new
    @report = Report.new
  end

  def update
   # omitted
  end

  def create
   # omitted
  end

  def destroy
   @report = Report.find(params[:id])
  end
end

routes.rb

YourApp::Application.routes.draw do
  resources :reports

  root to: "reports#index"
end

This would achieve the effect your after using just rails, of course adding ajax could add a better user experience.

veritas1
  • 8,740
  • 6
  • 27
  • 37