Reputation: 125
Currently I have a modal rendering for each piece on the page. It works but I don't want to render a modal for each piece each time the page is loaded.
Here is the code where my modal is rendered now:
site/gallery.html.erb
<% @pieces.each_slice(3) do |pieces| %>
<div class="row">
<% pieces.each do |piece| %>
<div class="col-lg-4">
<%= image_tag (piece.images.joins(:blob).order('active_storage_blobs.filename ASC').first if piece.images.attached?), data: { toggle: "modal", target: "#modal#{piece.id}" }, class:"img-thumbnail mx-auto d-block img-size" %>
<p><%= piece.name %></p>
<p><%= piece.description %></p>
<%= render 'site/modal', piece: piece %>
</div>
<% end %>
</div>
<% end %>
Here is the modal partial:
site/_modal.html.erb
<div class="modal fade" id="modal<%=piece.id%>" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="modalLabel"><%= piece.name %></h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
//code involving video and images for the piece
</div>
<div class="modal-footer">
<% if piece.quantity == 1 %>
<%= button_to 'Purchase', checkout_create_path, method: :post, params: {id: piece.id}, remote: true, class:"btn btn-dark" %>
<% else %>
<p>SOLD</p>
<% end %>
</div>
</div>
</div>
</div>
What I believe I need to do is add remote: true and pass the piece.id through my image_tag link somehow. I think I would need a modal.js.erb with something along these lines in there
$('modal').html('<%= j render "site/modal", piece: @piece %>');
$('#modal<%=piece.id%>').modal('show');
And then render the modal at the top of the gallery.html.erb page. I'm not quite sure how to go about this though
EDIT I've made some progress with trying to use AJAX to display the modals. I've moved my modal into the pieces directory and created a javascript file to go with it.
_piece_modal.html.erb
<div class="modal fade" id="piece-modal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered" role="document">
<div class="modal-content">
//modal content here
</div>
</div>
</div>
piece_modal.js.erb
$('body').append('<%= j render "piece_modal", piece: @piece %>');
$('#piece-modal').modal('show');
In my pieces controller
def piece_modal
@piece = Piece.find_by(params[:piece])
end
In my routes
get 'piece_modal' => 'pieces#piece_modal'
And here is the loop I'm using images to link to my modals
<% @pieces.each_slice(3) do |pieces| %>
<div class="row">
<% pieces.each do |piece| %>
<div class="col-lg-4">
<%= link_to piece_modal_path(piece), remote: true do %>
<%= image_tag (piece.images.joins(:blob).order('active_storage_blobs.filename ASC').first if piece.images.attached?), class:"img-thumbnail mx-auto d-block img-size" %>
<% end %>
<p><%= piece.name %></p>
<p><%= piece.description %></p>
</div>
<% end %>
</div>
<% end %>
The modal displays now but it only displays images from the first piece in the loop. How can I get it to display the correct content when I click on different images?
Upvotes: 0
Views: 2030
Reputation: 125
Okay I found a way for the modal to load dynamically with some ajax.
I changed up my link_to like this
<%= link_to piece_modal_path(piece_id: piece.id), remote: true do %>
I made this change in the pieces controller
def piece_modal
@piece = Piece.find(params[:piece_id])
end
And I made this change to my piece_modal.js.erb
$('body').append('<%= j render "piece_modal", piece: @piece %>');
$('#piece-modal').modal('show');
$('#piece-modal').on('hidden.bs.modal', function () {
$(this).remove();
});
So now instead of each piece on the site rendering it's own modal, only one gets rendered when I click on the image of the piece. On hide though I have to remove it from the DOM or else the modal will stay rendered with the properties of the first piece I click on.
Upvotes: 5
Reputation: 1714
You have written your code like:
<%= image_tag (piece.images.joins(:blob).order('active_storage_blobs.filename ASC').first if piece.images.attached?), class:"img-thumbnail mx-auto d-block img-size" %>
But notice that you use .first
which will always return the first property.
You could do something like this instead:
<% @pieces.each_slice(3) do |pieces| %>
<div class="row">
<% pieces.each_with_index do |piece, index| %>
<div class="col-lg-4">
<%= link_to piece_modal_path(piece), remote: true do %>
<%= image_tag (piece.images.joins(:blob).order('active_storage_blobs.filename ASC')[index] if piece.images.attached?), class:"img-thumbnail mx-auto d-block img-size" %>
<% end %>
<p><%= piece.name %></p>
<p><%= piece.description %></p>
</div>
<% end %>
</div>
<% end %>
p/s: I'm writing this on the fly and didn't actually test it.
Upvotes: 0