Bootstrap Modal for Show Page

I managed to get the _form to display inside of the modal and fire off.
I’m having trouble with displaying show actions inside of the modal.

The error that I’m receiving is undefined method ‘user’ for
nil:NilClass. The data request is not transferring over to the show
action when I click the link_to button. I’ll post what I wrote beneath
this. Thanks.

posts/_posts.html.erb

<% @post_items.each do |post| %>

<%= link_to image_tag(post.photo.url(:medium), style: ‘height: 300px;
width: 500px;’, lazy: true), post_path(controller: :posts, :action =>
:show, :id => post.id), remote: true, data: {:toggle => ‘modal’, :target
=> ‘#myModal’} %>

<% end %>

    <!-- Modal -->
    <div class="modal fade" id="myModal" tabindex="-1" role="dialog"

aria-labelledby=“myModalLabel” aria-hidden=“true”>





×

Show Page for
Post




<%= render ‘posts/post’, :locals => {post: post } %>



_post.html.erb

<%= @post.user.username.capitalize %>

<%= image_tag(@post.photo.url(:large)) %>

etc.

On 9 April 2016 at 23:57, David W. [email protected] wrote:

_post.html.erb

<%= @post.user.username.capitalize %>

As always it is best to paste the complete error message and tell us
which line it refers to. If it is the line above that is saying
undefined method ‘user’ for nil:NilClass
then that means @post is nil.

Colin

Colin L. wrote in post #1182722:

On 9 April 2016 at 23:57, David W. [email protected] wrote:

_post.html.erb

<%= @post.user.username.capitalize %>

As always it is best to paste the complete error message and tell us
which line it refers to. If it is the line above that is saying
undefined method ‘user’ for nil:NilClass
then that means @post is nil.

Colin

I added the modal before the end block, and then I used the larger image
inside of the modal body (instead of the partial posts/post partial).
The problem with that approach is that it doesn’t work for more than one
post. I need the modal button to listen for changes, so that it can open
up with new content.

undefined method ‘user’ for nil:NilClass
then that means @post is nil.

Colin

I added the modal before the end block, and then I used the larger image
inside of the modal body (instead of the partial posts/post partial).
The problem with that approach is that it doesn’t work for more than one
post. I need the modal button to listen for changes, so that it can open
up with new content.

This is a shortcoming of the Bootstrap modal design. In Bootstrap 3
documentation, they say that being able to reload a modal with different
content is deprecated, and in Bootstrap 4, they are going to remove the
possibility (IIRC). The docs mention that if you want to do something
like this, you should use a client-side framework (I am not a fan of
this idea).

Here’s what I use in Bootstrap 3 to work around this:

$(document).on(‘page:change’, function(){
// shims for the Bootstrap Modal, which is bloody-minded about caching
content per modal
$(document).on(‘click’, ‘#reusable_modal [data-dismiss=“modal”]’,
function (e) {
$(e.target).removeData(‘bs.modal’);
$(’#reusable_modal .modal-content’).empty();
});
$(document).on(‘click’, ‘[data-target="#reusable_modal"]’, function(e)
{
$("#reusable_modal .modal-content").load($(this).attr(“href”));
});
});

Walter

Walter D. wrote in post #1182728:

undefined method ‘user’ for nil:NilClass
then that means @post is nil.

I made some changes, is this ok?

<%= image_tag(post.photo.url(:large), style: 'max-width: 570px;') %> <%= sanitize content_with_emoji(post.body) %>

$(document).on(‘page:change’, function(){
// shims for the Bootstrap Modal, which is bloody-minded about
caching content per modal
$(document).on(‘click’, ‘#reusable_modal
[data-dismiss=“modal”]’,
function (e) {
$(e.target).removeData(‘bs.modal’);
$(’#reusable_modal’).find(’.modal-content’).empty();
});
$(document).on(‘click’, ‘[data-target="#reusable_modal"]’,
function(e)
{
$("#reusable_modal").find(".modal-content").load($(this).attr(“href”));
});
});

Will it still work if I add comments inside of the modal? Will it
basically clear everything inside of the container? I’ll wait for your
response. I would also like to add a commenting section inside of the
footer with overflow. Should I target the footer as well? I guess that I
don’t need to load the information in the header. Since the user’s name
isn’t going to change alongside the post.

× <%= image_tag(post.user.avatar_url(:thumb), class: 'round-image-50') %> <%= post.user.username %>

$(’#reusable_modal’).find(’.modal-content’).(’.modal-footer’).empty();
$("#reusable_modal").find(".modal-content").(’.modal-footer’).load();

It’s still not dynamically updating.

image converted into a clickable button

<%= link_to image_tag(post.photo.url(:medium), style: ‘height: 300px;
width: 500px;’), post_path(controller: :posts, :action => :show, :id =>
post.id), remote: true, data: {:toggle => ‘modal’, :target =>
#myModal’}, lazy: true %>

    <div class="modal fade reusable_modal" id="myModal"

tabindex="-1" role=“dialog” aria-labelledby=“myModalLabel”
aria-hidden=“true”>





×

<%= image_tag(post.user.avatar_url(:thumb), class:
‘round-image-50’) %>
<%= post.user.username %>




<%= image_tag(post.photo.url(:large), style: ‘max-width:
570px;’) %>
<%= sanitize content_with_emoji(post.body) %>


Hello Test




$(document).on(‘page:change’, function(){
// shims for the Bootstrap Modal, which is bloody-minded about
caching content per modal
$(document).on(‘click’, ‘#reusable_modal
[data-dismiss=“modal”]’,
function (e) {
$(e.target).removeData(‘bs.modal’);
$(’#reusable_modal’).find(’.modal-content’).empty();
});
$(document).on(‘click’, ‘[data-target="#reusable_modal"]’,
function(e)
{
$("#reusable_modal").find(".modal-content").load($(this).attr(“href”));
});
});

function (e) {

Where should I place id=“reusable_modal”? modal-content is already set.
Thanks.

I put that as the id of the modal itself.

Walter

Walter D. wrote in post #1182728:

Here’s what I use in Bootstrap 3 to work around this:

$(document).on(‘page:change’, function(){
// shims for the Bootstrap Modal, which is bloody-minded about caching
content per modal
$(document).on(‘click’, ‘#reusable_modal [data-dismiss=“modal”]’,
function (e) {
$(e.target).removeData(‘bs.modal’);
$(’#reusable_modal .modal-content’).empty();
});
$(document).on(‘click’, ‘[data-target="#reusable_modal"]’, function(e)
{
$("#reusable_modal .modal-content").load($(this).attr(“href”));
});
});

Walter

Where should I place id=“reusable_modal”? modal-content is already set.
Thanks.

This link is rendering the entire show action inside of the modal.
(Including the navigation bar)

<%= link_to image_tag(post.photo.url(:medium), style: ‘height: 300px;
width: 500px;’), post_path(controller: :posts, :action => :show, :id =>
post.id), remote: true, data: {:toggle => ‘modal’, :target =>
#reusable_modal’}, lazy: true %>

Should I take a different approach, than hard-coding the show action in
the link itself.

The JavaScript is working from what I can see.

         <div class="modal-header">
           <%= image_tag(post.photo.url(:large), style: 'max-width:

function(e)
{
$(“#reusable_modal”).find(“.modal-content”).load($(this).attr(“href”));
});
});

I think you’re missing something, then. Look at this Gist:

The first snippet is the HTML that your server would return if you
requested modal-content.html. Imagine if there was another snippet,
called other-modal-content.html, with different contents.

Then, in your page, you have a link to modal-content.html and another
to other-modal-content.html. Note how they are constructed: they have
a data-target to the same modal (using the id #reusable_modal) and they
each differ by their href attribute. The href is what jQuery reads and
uses to populate the body of the modal dialog.

Below those links, you have the outer “frame” of the #reusable_modal
itself. Note that it is empty, and will be filled by (and emptied again
by) the script, depending on whether you click on a URL with its
data-target, or click on a button with data-dismiss within that same
element.

I suspect that your only issue here is getting the HTML correct. Having
the right ID (as noted in the jQuery) in your HTML will mean that the
selector “finds” the content you wish to change.

In the Rails context, you would obviously not have static HTML for these
URLs and their snippets, but rather controller methods and routes to
them to construct your modal contents.

Walter

Walter D. wrote in post #1182737:

Ok, I tested a second link method

<%= link_to image_tag(post.photo.url(:medium), style: ‘height: 300px;
width: 500px;’), post, remote: true, data: {:toggle => ‘modal’, :target
=> ‘#reusable_modal’}, lazy: true %>

When I remove the post local variable -> targeting the action. The modal
doesn’t pop up an image at all.

Walter

Should I take a different approach, than hard-coding the show action in
the link itself.

You need a different method to render this, or if it will only ever
appear in the modal, then you need to add layout: false to your
controller so it doesn’t render the whole page. Make sure that your
show template only renders the stuff that will appear within the
modal, nothing else, and then turn off the layout so you don’t get the
entire page.

If the modals will be the only consumer of the “remote: true” requests,
then you can make that change in your show controller method, like this:

def show
#whatever else you regularly have here
respond_to do |format|
format.html { }
format.js { layout: false, template: ‘modal’ }
end
end

views/posts/modal.html.erb

×

<%= @post.title %>

<%= @post.whatever_else_you_want_to_render %>
Close

Walter

On 10 April 2016 at 22:01, David W. [email protected] wrote:

respond_to do |format|
  format.html
  format.js { render layout: false , template: 'modal'}
  format.json {render json: @post }
end

end

But, for whatever reason, the link_to image_tag button is targeting the
old show.html.erb action for the post.

How can it be targeting code that you have deleted?

Colin

When I remove the post local variable -> targeting the action. The modal
doesn’t pop up an image at all.

I suspect the issue is in how you are constructing this link, and how
you have directed your controller to respond to a “format: js” request.
When you say “remote: true”, then your controller must be set up to
respond with your desired layout in the format.js section of the
respond_to block.

In the past, I have done these without using the remote: true thing at
all. I suspect you can remove it as well. Try the following:

posts_controller.rb

add a new method next to show()

def modal
@post = Post.find params[:id]
end

views/posts/modal.html.erb

×

<%= @post.title %>

<%= @post.whatever_else_you_want_to_render %>
Close

(be sure to put whatever actual erb you want to use in your modal-body
section)

routes.rb

resources :posts do
member do
get :modal
end
end

Now to link to it, you will have a new modal_post_path() helper to play
with, so your link would look like this:

<%= link_to image_tag(post.photo.url(:medium), style: ‘height: 300px;
width: 500px;’), modal_post_path(post), data: {:toggle => ‘modal’,
:target =>
#reusable_modal’}, lazy: true %>

See how that goes for you.

Walter

modal, nothing else, and then turn off the layout so you don’t get the
end
@post = Post.find(params[:id])
@new_comment = Comment.build_from(@post, current_user.id, “”)
respond_to do |format|
format.html
format.js { render layout: false , template: ‘modal’}
format.json {render json: @post }
end
end

But, for whatever reason, the link_to image_tag button is targeting the
old show.html.erb action for the post.

Please have a look at this very simple Rails scaffold app with a modal:

git clone it, rake db:migrate, rails s, and look at it in a browser. Add
some posts, then return to the index page and click on the Show link and
then the Modal link (they are different). See how the modal appears and
shows you any post you click on when you use the modal link.

Walter

Walter D. wrote in post #1182744:

views/posts/modal.html.erb

routes.rb

resources :posts do
member do
get :modal
end
end

I tried this method, but it went back to the default one image showing
problem that I had earlier. I will see if I can find a way around it.

Walter D. wrote in post #1182747:

modal, nothing else, and then turn off the layout so you don’t get the

Please have a look at this very simple Rails scaffold app with a modal:
GitHub - walterdavis/modal-test: A quick scaffold to show how you reuse a Bootstrap modal

Walter

I’m checking it out now. Thanks.

David W. wrote in post #1182748:

Walter D. wrote in post #1182744:

views/posts/modal.html.erb

routes.rb

resources :posts do
member do
get :modal
end
end

I tried this method, but it went back to the default one image showing
problem that I had earlier. I will see if I can find a way around it.

The screen dims, but the modal itself doesn’t show. I wrote it exactly
the same way you put it.

× <%= image_tag(@post.user.avatar_url(:thumb), class: 'round-image-50') %>

<%= post.user.username %>

<% if @post.photo.present? %> <%= image_tag(@post.photo.url(:large), style: 'max-width: 570px;') %> <% end %>
<%= sanitize content_with_emoji(@post.body) %>
<%= render partial: 'comments/template', locals: {commentable: @post, new_comment: @comment} %>

In my _posts.html.erb
<% @post_items.each do |post| %>
<%= link_to image_tag(post.photo.url(:medium), style: ‘height: 300px;
width: 500px;’), modal_post_path(post), data: {:toggle => ‘modal’,
:target => ‘#reusable_modal’}, lazy: true %>

  <!-- Modal -->
  <div class="modal fade" id="reusable_modal" tabindex="-1" 

role=“dialog” aria-labelledby=“myModalLabel” aria-hidden=“true”>


      </div>
    </div>
  </div>

<% end %>

posts_controller.rb

def show
@post = Post.find(params[:id])
@new_comment = Comment.build_from(@post, current_user.id, “”)
respond_to do |format|
format.html
format.js { render layout: false , template: ‘posts/modal’ }
format.json {render json: @post }
end
end

def modal
render layout: false
end

David W. wrote in post #1182748:

Walter D. wrote in post #1182744:

views/posts/modal.html.erb

routes.rb

resources :posts do
member do
get :modal
end
end

I tried this method, but it went back to the default one image showing
problem that I had earlier. I will see if I can find a way around it.

Started GET “/posts/13/modal” for 127.0.0.1 at 2016-04-11 00:11:51 -0400
Processing by PostsController#modal as HTML
Parameters: {“id”=>“13”}
User Load (0.5ms) SELECT “users”.* FROM “users” WHERE “users”.“id” =
? ORDER BY “users”.“id” ASC LIMIT 1 [[“id”, 5]]
Rendered posts/modal.html.erb (32.5ms)
Completed 500 Internal Server Error in 90ms (ActiveRecord: 0.5ms)

NoMethodError - undefined method user' for nil:NilClass: app/views/posts/modal.html.erb:5:in_app_views_posts_modal_html_erb___915972257_62747604’

Very strange. It’s not including the user model