Rails hotwire edit link broken after update

1.3k Views Asked by At

I've created a small test app to explore hotwire and I'm having trouble after I click update, my edit button doesn't work any more. I have a jobs model and with-in the show I can click edit and the turbo frame will replace the contents with the edit form. I can then hit update and the show contents is updated without the page reload, but the edit button no longer works.

Job Show ERB

<p id="notice"><%= notice %></p>
<%= Time.now %>

<%= turbo_stream_from @job %>

<%= turbo_frame_tag dom_id(@job) do %>
  <%= render "job_show", job: @job %>

  <%= link_to 'Edit', edit_job_path(@job) %> |
  <%= link_to 'Back', jobs_path, 'data-turbo-frame': :_top %>
<% end %>

Job show partial

<div id="<%= dom_id job %>" class="job">
  <p>
    <strong>Code:</strong>
    <%= job.code %>
  </p>

  <p>
    <strong>Name:</strong>
    <%= job.name %>
  </p>
</div>

Job controller

  # PATCH/PUT /jobs/1 or /jobs/1.json
  def update
    respond_to do |format|
      if @job.update(job_params)
        format.html { redirect_to @job, notice: "Job was successfully updated." }
        format.json { render :show, status: :ok, location: @job }
      else
        format.html { render :edit, status: :unprocessable_entity }
        format.json { render json: @job.errors, status: :unprocessable_entity }
      end
    end
  end

Job model

class Job < ApplicationRecord

  # We're going to publish to the stream :jobs
  # It'll update the element with the ID of the dom_id for this object,
  # Or append our jobs/_job partial, to the #jobs <tbody>

  broadcasts_to -> (job) {:jobs}
end

I have noticed that when it's in the error state and I cannot hit the 'edit' button, if I use inspect in the browser can change the turbo_frame line it then works;

From

<turbo-frame id="job_7" src="http://localhost:3001/jobs/7">

To

<turbo-frame id="job_7">

What is putting the 'src' option onto that turbo-frame line? Can I disable that to get this working?

Full code: https://github.com/map7/hotwire_jobs_example

2

There are 2 best solutions below

1
On

When you want to target a resource from outside the frame, remember to use the correct target, as in:

<%= turbo_frame_tag dom_id(@job), target: '_top' do %>
  <%= render "job_show", job: @job %>

  <%= link_to 'Edit', edit_job_path(@job) %> |
  <%= link_to 'Back', jobs_path, 'data-turbo-frame': :_top %>
<% end %>

That will help you handle both Edit and Back actions.

You also need to tell your controller how to stream, by doing:

  # PATCH/PUT /jobs/1 or /jobs/1.json
  def update
    respond_to do |format|
      if @job.update(job_params)
        format.turbo_stream
        format.html { redirect_to @job, notice: "Job was successfully updated." }
        format.json { render :show, status: :ok, location: @job }
      else
        format.html { render :edit, status: :unprocessable_entity }
        format.json { render json: @job.errors, status: :unprocessable_entity }
      end
    end
  end
0
On

Any link inside a Turbo frame will be handled by Turbo by default. I don't think manipulating the src attribute is really your issue.

There are three ways you can restore regular (non-Turbo) link behavior.

1: Set the data-turbo attribute.

<%= link_to "Click Here", path_helper_method, data: { turbo: false } %>
(or in plain html)
<a href="" data-turbo="false">

2: Set the target attribute.

<%= link_to "Click Here", path_helper_method, target: "_top" %>
(or in plain html)
<a href="" target="_top">
  1. Move the link outside any Turbo frame. Any link inside a Turbo frame, without one of the above attributes, will be handled by Turbo by default, often in unexpected ways.