I have a standard scaffold from
rails g model Room name:string
index.html.erb:
<%= turbo_frame_tag "rooms" do %>
<turbo-frame id="room-list">
<div id="rooms">
<% #rooms.each do |room| %>
<turbo-frame id=<%= "room-controls-#{room.id}"%>>
<div>
<%= render room %>
<%= link_to "Show this room", room } %>
</div>
</turbo-frame>
<% end %>
</div>
</turbo-frame>
<% end %>
when the user clicks on "Show this room" it directs them to show.html.erb
<turbo-frame id=<%="room-controls-#{#room.id}"%>>
<div id="<%= dom_id #room %>">
<%= render #room %>
<div>
<%= link_to "Back to rooms", rooms_path, data: { turbo_frame: "room-controls-#{#room.id}" } %>
</div>
</div>
</turbo-frame>
when the user clicks on the "Back to rooms" link, it fetches the index page as expected, but I'm getting the outer turbo frame rooms in the network response, and not just room-controls-#{#room.id}
In other words, from looking at the network response, it appears reloading and replacing the outer turbo frame along with all the inner turbo frames instead of just the one inner turbo frame that got rendered when I initially clicked on the "Show this room" button.
I tried adding/removing data: { turbo_frame: "room-controls-#{room.id}" } to each of the links but its still behaving in the same manner where it's reloading the outer turbo frame with every instance of the inner turbo frames rather than just the one instance of the inner turbo frame. Is this normal/acceptable? I assume the performance is lower this way since it's re-rendering more than it needs to at O(n) time in the loop. Is there a way to control this so that it will focus on just the inner turbo frame?
Below is an example of the network response. If I clicked on room-controls-17, I'd prefer to only be receiving the turbo frame room-controls-17 instead of all of this
Related
i am on rails 7 trying out the turbo frame.
supposedly my code should fire a Response has no matching error because i do not have the similar id in the new page after clicking the new link. however it just loads the new page as usual, contradict with a tutorial. any idea how do i get the error logged instead of loading a new page? thanks.
# app/views/quotes/index.html.erb
<main class="container">
<%= turbo_frame_tag "first_turbo_frame" do %>
<div class="header">
<h1>Quotes</h1>
<%= link_to "New quote", new_quote_path, class: "btn btn--primary" %>
</div>
<% end %>
<%= render #quotes %>
</main>
# app/views/quotes/new.html.erb
<h1>New quote</h1>
<%= render "form", quote: #quote %>
I have a model subscription_tier with show and edit actions with corresponding views. I've wrapped each of these with a turbo frame
<%= turbo_frame_tag subscription_tier do %>
When I edit an existing subscription tier and save it, the turbo frame refreshes and shows my saved tier, but I'm unable to replicate this for creating new tiers.
My new tier frame:
<turbo-frame id="new_tier">
<%= link_to "Add Tier", new_create_subscription_tier_path(sub_type: "Free"), class: "btn btn-primary mb-3 fs-6"
%>
</turbo-frame>
and in new.html.erb
<turbo-frame id="new_tier">
<%= render partial: "create/subscription_tiers/edit", locals: {
subscription_tier: #subscription_tier
} %>
</turbo-frame>
Clicking Add Tier button successfully renders the form and I can save the object, but on save the turbo frame is destroyed with the error Response has no matching <turbo-frame id="new_tier"> element
I know this is because my show partial is wrapped with the <%= turbo_frame_tag subscription_tier do %>, but I don't know how to reconcile this.
I believe you need to add a data tag to your new link i.e.
<%= link_to "new subscription", subscription_path, data: { turbo_frame: dom_id(Subscription.new) } %>
On the same page as this link ^^^^ you need to add
<%= turbo_frame_tag Subscription.new %>
I believe this is what your trying to accomplish
There is a fantastic tutorial that goes over all this stuff that is free here
Perhaps the OP figured this out, but for anyone looking for a possible solution, you could always set the turbo frame ID manually, for example:
<!-- new.html.erb, edit.html.erb -->
<%= turbo_frame_tag 'subscription_tier_frame' do %>
<%-- form for subscription tier -->
<% end %>
and
<!-- show.html.erb -->
<%= turbo_frame_tag 'subscription_tier_frame' do %>
<%-- rendered subscription tier -->
<% end %>
That'll keep things in the same turbo frame.
I am building a website for a music database.
I would like to display categories like classical and hip hop first; when the user clicks on a category, I would like to display all the tracks names in that category (I would like to do this without a page refresh). I would also need to support pagination of this list displaying 10 items in one page (and I need to display buttons for display, edit, delete alongside each track in this list)
How can I accomplish this? Does bootstrap provide components that support this kind of implementation?
(If I could do this with a page refresh, I have done this before and I would know how to do it. But I am not sure how to do this without a page refresh)
On views/categories/index.html.erb:
<% #categories.each do |category| %>
<%= link_to category_path(category), :remote => true do %>
<%= category.name %>
<% end %>
<div class="category_<%= category.id %>">
</div>
<% end %>
Then create a partial views/categories/_show.html.erb (here you can insert a table or a structure with bootstrap row and columns):
<% #category.tracks.each do |track| %>
<%= track.name %>
... and you can add here delete and edit actions
<% end %>
Then create views/categories/show.js.erb:
$(".category_<%= #category.id %>").html("<%= escape_javascript(render("show")) %>");
Fyi what you are trying to do has nothing to do with bootstrap, unless you wanted for instance display tracks on a bootstrap modal.
Here is a poor man's bootstrap example I whipped up: when you click on the Track Category example, the table should expand. (You must have bootstrap v4 set up for this to work) and you must have a track_table partial as well - you can use the same partial for the two different tables that you want:
<div class="track-group">
<div class="track track-default">
<div class="track-heading">
<h4 class="track-title">
<p data-toggle="collapse" href="#collapse1"> Track Category (Click to Expand)</p>
</h4>
</div>
<div id="collapse1" class="track-collapse collapse">
<div class="track-body">
<%= render 'track-table' %>
</div>
<div class="track-footer">
</div>
</div>
</div>
</div>
Here's how it looks with an existing app on my computer:
I am creating an evaluation form where a user will submit form after form by using kaminari pagination. The way I have it set up right now though is that the user will answer the questions, submit the form with an f.submit button, then once the profile updates, the user will have to manually select 'Next User' using the paginate button below the f.submit button. I would love for it to both submit the form and send the user to the next evaluation in line under one button action, not two. I have been playing around with trying to incorporate the paginate code into my f.submit button, but it keeps throwing errors. I was wondering if there was an easy way to go about this, thanks in advance!
<h2>Team Member Evaluation</h2>
<br> </br>
<% #users.each do |user| %>
<h4> <%= user.name %> </h4>
<%= form_for(user) do |f| %>
<% begin %>
<h8> Hunger for Wisdom </h8>
<div class="form-inline">
<div class="form-group">
<%= f.radio_button :current_one, 1 %>
<h7> 1 </h7>
</div>
<div class="form-group">
<%= f.radio_button :current_one, 2 %>
<h7> 2 </h7>
</div>
<% end %>
<div class="col-md-3 col-md-offset-4">
<%= f.submit "Submit Score", class: "btn btn-default" %>
<% rescue ActionController::RedirectBackError %>
</div>
</div>
<% end %>
<%= paginate #users %>
<% end %>
<% end %>
Right now it is set up to whenever the user submits the form, the rescue action will direct the user back to a refreshed page of the evaulation form they just submitted, and then they must click next where the <% paginate #users %> is to go to the next form. I would like once the f.submit button is pressed to update and then immediately take the user to the next form.
In the controller action for the submit you could just increment the page count like this:
#users = User.page params[:page].to_i + 1
This is assuming you aren't using any other scopes to get the #users collection. The kaminari github repo has more information on available methods here.
If it is on the first page then the page query var is probably nil so you would have to account for this and send it to page 2 in this special case.
I have a User model, and each user has_many: Deliveries. I have a partial called _currentDeliveries, that shows a user some information about each of their Deliveries.
Each Delivery that is shown has a delete button next to it (which is just a little square div for now), and I'm using Ajax so if a user clicks the delete button next to one of their Deliveries, that delivery will be destroyed removed from the list (by re-rendering the partial) without refreshing the page.
I have it almost working the way I want, the only problem is when I click the delete button for one Delivery, it is not removed from the list until I click the delete button of another delivery. And, the second delivery I delete is not removed from the list until I click a third delete button, and so on.
Basically, the partial is always one move behind where it should be, which makes me think the partial is being rendered before the Delivery is completely Deleted.
Here is the div that contains the partial:
<div id="currentDeliveriesArea">
<%= render "currentDeliveries", user: #user %>
</div>
Here is the partial:
<% user.deliveries.each do |d| %>
<div class="deliveryBox">
<div class="deliveryBoxLeft">
<div class="editDeliveryButton">
</div>
</div>
<div class="deliveryBoxCenter">
<p class="deliveryTitleText">Delivery</p>
<p class="deliveryTimeText">
<% if d.minute > 9 %>
<% if d.am == 1 %>
<%= d.hour %>:<%= d.minute %> am
<% else %>
<%= d.hour %>:<%= d.minute %> pm
<%end%>
<% else %>
<% if d.am == 1 %>
<%= d.hour %>:0<%= d.minute %> am
<% else %>
<%= d.hour %>:0<%= d.minute %> pm
<%end%>
<%end%>
</p>
</div>
<div class="deliveryBoxRight">
<div class="deleteDeliveryButton" onclick="getDeleteDelivery(<%= d.id %>);">
</div>
</div>
</div>
Here is the javascript function that is called when div "deleteDeliveryButton" is clicked:
function getDeleteDelivery(delivery){
$.get("/deleteDelivery", {delivery: delivery})}
Here is the deleteDelivery action in the users_controller:
def deleteDelivery
#user = current_user
puts "made it to delete action"
#user.deliveries.each do |d|
puts "Delivery ID " + d.id.to_s
end
#delivery = params[:delivery]
puts "User deliveries count before: " + #user.deliveries.count.to_s
Delivery.find(#delivery).destroy
puts "User deliveries count after: " + #user.deliveries.count.to_s
respond_to do |format|
format.js
end
end
Here is the deleteDelivery.js.erb file that gets called from the action and re-renders the partial:
$("#currentDeliveriesArea").html("<%= j(render partial: 'currentDeliveries', locals: {user: #user}) %>");
If I refresh the page after every delete button click, deliveries are removed from the list each time, but for some reason the Ajax seems to lag 1 click behind. The console says that the delivery is deleted completely, and #user.deliveries.count is one less, before it says the _currentDeliveries is rendered and then deleteDelivery.js.erb is rendered, so I'm not really sure what is going on.
Sorry about the bad naming conventions btw!