ruby-on-railsturbo-rails

Rails (with turbo) render form in place - how to update element outside of form


I have a model with some boolean columns. I would like to edit these as checkboxes in a form with instant update every time a checkbox is clicked. I managed to do this with onchange: "this.form.requestSubmit()" on each checkbox and then rendering the form in the controller with render :edit, status: :ok so we stay on the form.

Now I want to show an example of what the model does on the page but (I think) since the example is not part of the model, the element doesn't get refreshed. I used the logger to print out the value of the example and I see it changing in the logger output but I don't see it change on the page.

In the below examples I removed form error handling to make the code shorter.

view

<div><%= @sample_invoice_number_format %></div>
<%= render "form", invoice_number_format: @invoice_number_format %>

form partial

<%= form_with model: invoice_number_format do |form| %>
  <div>
    <%= form.label :yyyy %>
    <%= form.check_box :yyyy, onchange: "this.form.requestSubmit()" %>
  </div>
  <div>
    <%= form.label :yy %>
    <%= form.check_box :yy, onchange: "this.form.requestSubmit()" %>
  </div>
  <div>
    <%= form.label :mm %>
    <%= form.check_box :mm, onchange: "this.form.requestSubmit()" %>
    <% end %>
  </div>
  <div>
    <%= form.submit %>
  </div>
<% end %>

controller

  def update
    if @invoice_number_format.update(invoice_number_format_params)
      sample_invoice_number_format # this updates @sample_invoice_number_format
      logger.warn(@sample_invoice_number_format) # this shows the changed value
      render :edit, status: :ok
    else
      render :edit, status: :unprocessable_entity
    end
  end

Solution

  • When you render, the page is not updated, you have to redirect on a successful from submission:

    # render :edit, status: :ok
    redirect_to edit_invoice_number_format_url(@invoice_number_format)
    

    https://turbo.hotwired.dev/handbook/drive#redirecting-after-a-form-submission


    You could also respond with a turbo stream and update specific part of the page:

    <div id="invoice_format">
      <%= @sample_invoice_number_format %>
    </div>
    
    <%= render "form", invoice_number_format: @invoice_number_format %>
    
    def update
      respond_to do |format|
        if @invoice_number_format.update(invoice_number_format_params)
          format.turbo_stream do
            sample_invoice_number_format
            render turbo_stream: turbo_stream.update("invoice_format", @sample_invoice_number_format)
          end
        else
          render :edit, status: :unprocessable_entity
        end
      end
    end