Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rails 3.2 Modal popup on show action

None of the questions on this forum seem to address my specific need. Basically, I have a "Details" button. I want it that when it clicks, a modal dialog shows up with information drawn from the show.html.erb of the model. I have a book.rb model. In the index page I have:

<div class="detail_button"><%= link_to "Details", book %></div>

Clicking this button normally would take me to the book/id page, using the show action. But I don't want it to leave the page, rather I want a modal popup which can be closed. I've tried all the jquery and javascript code on related topics in this forum but none seem to do the trick. Most seem to be addressed to only create or custom actions.

Just to avoid any repeats, I have tried the following, none of which worked:

This:

You could look at modal dialogs by www.jqueryui.com. Add jquery ui to your application.

Put a hidden div (display:none) in your layout page.

<div class="modal" style="display:none;">
</div>

Your link should be an ajax link:

<%= link_to 'Link', events_path(@event), :remote => true %>

Your controller should accept ajax response:

def show
  @event = Event.find(params[:id])
  respond_to do |format|
    format.js
  end
end

This is where the magic happens. After pressing the link via ajax, your show.js file will insert content into your empty hidden div and display the popup. Your views should have a javascript file: /view/events/show.js.erb

$('.modal').html(<%= escape_javascript(render(@event)) %>); //inserts content into your empty div.
$('.modal').dialog(); //jquery ui will open it as a modal popup

This:

$('a[data-popup]').live('click', function(e) { 
    window.open($(this).attr('href')); 
    e.preventDefault(); 
}); 

And this:

$('a[data-popup]').live('click', function(e) { window.open($(this).attr('href')); e.preventDefault(); });

= link_to( 'Create a new company', new_company_path, 'data-popup' => true )

Any help guys? Total noob here.

like image 610
Shikasan Avatar asked May 08 '13 23:05

Shikasan


1 Answers

I'm not sure how @events relates to your Book model, but assuming we're just going off a single model (being Book), this is one way your code could be set up:


app/views/books/index.html.erb

Where you iterate through @books and include the link to 'View Details' with the remote: true set to enable AJAX.

<table>
<% @books.each do |book| %>
<tr>
  <td><%= book.title %></td>
  <td><%= book.author %></td>
  <td><%= number_to_currency(book.price) %></td>
  <td><%= link_to 'View Details', book, remote: true %></td>
</tr>
<% end %>
</table>

On this page you should also render your modal/dialog box, but it should have a class on it that keeps it hidden (you'll later toggle this with JS/jQuery). I used a partial to keep the code more modular but you could just put the modal divs directly underneath.

<%= render "layouts/modal" %>


app/views/layouts/_modal.html.erb

This is a partial with the structure of the model. I used Twitter Bootstrap's version, which has predefined styling as well as some nice animation triggers.

<div class="modal hide fade">
  <div class="modal-header">
    <button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
    <h3 class="modal-heading">Modal header</h3>
  </div>
  <div class="modal-body">
    <p>One fine body…</p>
  </div>
  <div class="modal-footer">
    <a href="#" class="btn" data-dismiss="modal">Close</a>
    <a href="#" class="btn btn-primary">Add to Cart</a>
  </div>
</div>


app/controllers/books_controller.rb

If your controller is set up with the standard scaffold, you only need to add format.js to the respond_to block of the show action. This will automatically render a file named show.js.erb (which you have to manually create) when that action is triggered.

def show
    @book = Book.find(params[:id])

    respond_to do |format|
        format.html # show.html.erb
        format.js # show.js.erb
        format.json { render json: @book }
    end
end


app/views/books/show.js.erb

As you aptly stated, this is where the magic happens and the AJAX response is sent to your page. Using jQuery, I'm setting some variables and replacing the HTML in the modal template with that rendered by @book (which comes from a partial you have to create named _book.html.erb).

$modal = $('.modal'),
$modalBody = $('.modal .modal-body'),
$modalHeading = $('.modal .modal-heading');
$modalHeading.html("<%= @book.title %>");
$modalBody.html("<%= escape_javascript(render @book) %>");
$modal.modal();


app/views/_book.html.erb

This is where you create the template for what will go inside the modal on the successful AJAX response.

<p><b>Title:</b> <%= @book.title %></p>

<p><b>Author:</b> <%= @book.author %></p>

<p><b>Price:</b> <%= number_to_currency(@book.price) %></p>

<p><b>Description:</b> <%= @book.description %></p>

<p><b>Publisher:</b> <%= @book.publisher %></p>

<p><b><%= @book.style %></b> <%= @book.number_of_pages %> pages</p>

<p><b>ISBN:</b><%= @book.ISBN %></p>

<%= link_to 'Edit', edit_book_path(@book) %> |
<%= link_to 'Show', @book %> |
<%= link_to 'Remove', @book, method: :delete, data: { confirm: 'Are you sure?' } %>

I created a sample Bookstore application using this code on Github. Hope this helps.

like image 176
Web Guy Ian Avatar answered Oct 26 '22 14:10

Web Guy Ian