4

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

map7
  • 5,096
  • 6
  • 65
  • 128

2 Answers2

4

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
Ulisses Caon
  • 430
  • 6
  • 11
  • Before I added this I could go to a job's show page, click edit, click update and then I couldn't click edit again but everything worked up to that point. Now with this I can go to the job's show page, click edit and then when clicking 'update' the view stays on the edit form. The item is updated in the background but the view is not updated. – map7 Apr 28 '21 at 00:02
1

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.
aidan
  • 1,627
  • 17
  • 27