Hi all, I’m currently using turbo frames to display an inline form. I have a button add unit that replaces a turbo frame tag with a form. After submission I would like the form to be replaced by the first turbo frame tag that loads the form.
<div class="px-4 sm:px-6 lg:px-6 py-8">
<%= turbo_frame_tag('new_unit') do %>
<div class="sm:flex sm:items-center">
<div class="sm:flex-auto">
<h1 class="text-xl font-semibold text-gray-900">Units</h1>
<p class="mt-2 text-sm text-gray-700">A list of all the units that belong to this property</p>
</div>
<div class="mt-4 sm:mt-0 sm:ml-16 sm:flex-none">
<%= link_to new_property_unit_path(@property), class:"inline-flex items-center justify-center rounded-md border border-transparent bg-indigo-600 px-4 py-2 text-sm font-medium text-white shadow-sm hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2 sm:w-auto" do %>
<svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
<path stroke-linecap="round" stroke-linejoin="round" d="M12 6v6m0 0v6m0-6h6m-6 0H6" />
</svg>
Add Unit
<% end %>
</div>
</div>
<% end %>
<div class="mt-8 flex flex-col">
<div class="-my-2 -mx-4 overflow-x-auto sm:-mx-6 lg:-mx-8">
<div class="inline-block min-w-full py-2 align-middle md:px-6 lg:px-8">
<table class="min-w-full divide-y divide-gray-300">
<thead>
<tr>
<th scope="col" class="py-3.5 pl-4 pr-3 text-left text-sm font-semibold text-gray-900 sm:pl-6 md:pl-0">Unit Name</th>
<th scope="col" class="py-3.5 px-3 text-left text-sm font-semibold text-gray-900">Monthly Rent</th>
<th scope="col" class="py-3.5 px-3 text-left text-sm font-semibold text-gray-900">Rooms</th>
<th scope="col" class="py-3.5 px-3 text-left text-sm font-semibold text-gray-900">Status</th>
<th scope="col" class="relative py-3.5 pl-3 pr-4 sm:pr-6 md:pr-0">
<span class="sr-only">Edit</span>
</th>
</tr>
</thead>
<tbody class="divide-y divide-gray-200" id="unit_list">
<% @property.units.each do |unit| %>
<%= render partial: 'properties/unit', locals: { unit: unit } %>
<% end %>
</tbody>
</table>
</div>
</div>
</div>
</div>
<!-- /End replace -->
</div>
</div>
So I have a turbo_frame_tag('new_unit')
within this turbo frame tag I have a button that links to a properties/:id/units/new
. When I click on the link, the turbo stream tag is replaced with the form in views/units/form
.
<%= turbo_frame_tag(dom_id(unit)) do %>
<%= form_for [@property, @unit], html: { class: "space-y-8 divide-gray-200" } do |f| %>
<div class="space-y-8 divide-y divide-gray-200 sm:space-y-5">
<div class="pt-8 space-y-6 sm:pt-10 sm:space-y-5">
<div>
<p class="mt-1 max-w-2xl text-sm text-gray-500">A unit can be an apartment number or a floor</p>
</div>
<div class="space-y-6 sm:space-y-5">
<div class="sm:grid sm:grid-cols-3 sm:gap-4 sm:items-start sm:border-t sm:border-gray-200 sm:pt-5">
<label class="block text-sm font-medium text-gray-700 sm:mt-px sm:pt-2">
<%= f.label :apartment_name, 'Unit name' %>
</label>
<div class="mt-1 sm:mt-0 sm:col-span-2">
<%= f.text_field :apartment_name, value: "APT 4B", class: "block max-w-lg w-full shadow-sm focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm border-gray-300 rounded-md" %>
</div>
</div>
<div class="sm:grid sm:grid-cols-3 sm:gap-4 sm:items-start sm:border-t sm:border-gray-200 sm:pt-5">
<label class="block text-sm font-medium text-gray-700 sm:mt-px sm:pt-2">
<%= f.label :status, 'Status' %>
</label>
<div class="mt-1 sm:mt-0 sm:col-span-2">
<%= f.select(:status, ['vacant', 'rented'], {}, { class: "max-w-lg block w-full shadow-sm focus:ring-indigo-500 focus:border-indigo-500 sm:max-w-xs sm:text-sm border-gray-300 rounded-md" }) %>
</div>
</div>
<div class="sm:grid sm:grid-cols-3 sm:gap-4 sm:items-start sm:border-t sm:border-gray-200 sm:pt-5">
<label class="block text-sm font-medium text-gray-700 sm:mt-px sm:pt-2">
<%= f.label :day_rent_due, 'Day of the month when rent is due' %>
</label>
<div class="mt-1 sm:mt-0 sm:col-span-2">
<%= f.number_field :day_rent_due, in: 1..31, value: "Day the rent for the unit is due", class: "block max-w-lg w-full shadow-sm focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm border-gray-300 rounded-md" %>
</div>
</div>
<div class="sm:grid sm:grid-cols-3 sm:gap-4 sm:items-start sm:border-t sm:border-gray-200 sm:pt-5">
<label for="city" class="block text-sm font-medium text-gray-700 sm:mt-px sm:pt-2">
<%= f.label :monthly_rent_cents, 'Monthly Rent' %>
</label>
<div class="mt-1 sm:mt-0 sm:col-span-2">
<div class="mt-1 relative rounded-md shadow-sm">
<div class="absolute inset-y-0 left-0 pl-3 flex items-center pointer-events-none">
<span class="text-gray-500 sm:text-sm"> $ </span>
</div>
<%= f.number_field :monthly_rent_cents, value: 0.00, class: "focus:ring-indigo-500 focus:border-indigo-500 block w-full pl-7 pr-12 sm:text-sm border-gray-300 rounded-md"%>
<div class="absolute inset-y-0 right-0 pr-3 flex items-center pointer-events-none">
<span class="text-gray-500 sm:text-sm" id="price-currency"> USD </span>
</div>
</div>
</div>
</div>
<div class="sm:grid sm:grid-cols-3 sm:gap-4 sm:items-start sm:border-t sm:border-gray-200 sm:pt-5">
<label for="country" class="block text-sm font-medium text-gray-700 sm:mt-px sm:pt-2">
<%= f.label :rooms, 'Rooms' %>
</label>
<div class="mt-1 sm:mt-0 sm:col-span-2">
<%= f.select(:rooms, ['studio', '1', '2','3', '4', '5+'], {}, { class: "max-w-lg block w-full shadow-sm focus:ring-indigo-500 focus:border-indigo-500 sm:max-w-xs sm:text-sm border-gray-300 rounded-md" }) %>
</div>
</div>
<div class="sm:border-t sm:border-gray-200 sm:pt-5">
<div>
<%= f.label :notes, 'Add your notes & documents', class: "block text-sm font-medium text-gray-700" %>
<div class="mt-1">
<%= f.rich_text_area :notes, class: "shadow-sm focus:ring-indigo-500 focus:border-indigo-500 block w-full sm:text-sm border-gray-300 rounded-md" %>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="pt-5">
<div class="flex justify-end">
<%= link_to 'Cancel', property_path(@property), class: "bg-white py-2 px-4 border border-gray-300 rounded-md shadow-sm text-sm font-medium text-gray-700 hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500" %>
<%= f.submit "Save", class: "ml-3 inline-flex justify-center py-2 px-4 border border-transparent shadow-sm text-sm font-medium rounded-md text-white bg-indigo-600 hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500" %>
</div>
</div>
<% end %>
<% end %>
When I submit the form, which created a unit
instance. In the controller I add this unit to a list via the append
method.
class UnitsController < ApplicationController
def create
@property = Property.find(params[:property_id])
@unit = @property.units.create(unit_params)
respond_to do |format|
format.turbo_stream do
render turbo_stream: turbo_stream.prepend(:unit_list, partial: "properties/unit",
locals: { unit: @unit })
end
format.html { redirect_to unit_url }
end
end
However, the form stays rendered. Shouldn’t after submission the form be reseted to the previous state? It keeps updating the unit list. But I would like for the form after a submission to go back to it’s previous state . Any guidance on how to achieve that?