Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Morphing is updates an a tag, but not it's content, but only on the client who initiated the action #1189

Open
trobrock opened this issue Feb 16, 2024 · 10 comments

Comments

@trobrock
Copy link

I am trying to get morphing into my app, but am running into a weird bug.

I have an a tag with a single span inside it. When the user clicks the link it hits the controller, updates the object, and redirects back. This also kicks off a refresh.

Everything works fine with morphing on other clients, but the one who initiated the action doesn't have their button text updated, but the actual link updates.

Heres a video:
morphing-bug

Here is the relevant HTML
Screenshot 2024-02-16 at 3 23 02 PM

And the controller action:

  def pause
    @housekeeping.pause!

    redirect_to housekeeping_path(@housekeeping)
  end

  def resume
    @housekeeping.resume!

    redirect_to housekeeping_path(@housekeeping)
  end

Am I doing something wrong?

@krschacht
Copy link

@trobrock Your model needs to broadcast the change and your view needs to subscribe to changes from that model. Watch the demo video in this sample repo: https://github.com/basecamp/turbo-8-morphing-demo/tree/page-refreshes and then you can reference the code in this branch.

I've come back to this sample project many times as I've gotten morphing to work in my app. :)

@krschacht
Copy link

I don't think this issue you've opened is an issue with the project so it's probably worth closing.

@trobrock
Copy link
Author

@krschacht I have broadcast in the model and am subscribed in the view, which is why the page on the left is updating with morphing just fine. The issue is on the right screen the morphing happens but only updates the a tag, not the contents within that same a tag.

@trobrock
Copy link
Author

@krschacht for more context, here is my diff to enable morphing:

diff --git a/app/models/housekeeping.rb b/app/models/housekeeping.rb
index 4786943e..bb86fe50 100644
--- a/app/models/housekeeping.rb
+++ b/app/models/housekeeping.rb
@@ -17,7 +17,9 @@ class Housekeeping < ApplicationRecord
 
   scope :today, -> { where(date: Time.zone.today) }
 
-  after_commit :broadcast_update
+  # after_commit :broadcast_update
+
+  broadcasts_refreshes
 
   has_rich_text :notes
 
diff --git a/app/views/housekeepings/show.html.haml b/app/views/housekeepings/show.html.haml
index 06058684..dceb2b48 100644
--- a/app/views/housekeepings/show.html.haml
+++ b/app/views/housekeepings/show.html.haml
@@ -1,6 +1,8 @@
 = title @housekeeping.unit.name
 = subtitle @housekeeping.clean_type.humanize
 
+= turbo_stream_from @housekeeping
+
 - if @housekeeping.inspection_failed? && @housekeeping.assigned_to?(Current.user)
   .p-4.bg-contrast.rounded-lg.md:flex.items-center.justify-between.mb-8.mt-4.lg:mt-0
     .flex.items-center.space-x-4.text-white.font-bold.mb-4.md:mb-0
diff --git a/app/views/layouts/application.html.haml b/app/views/layouts/application.html.haml
index 9edc8e6b..612b7379 100644
--- a/app/views/layouts/application.html.haml
+++ b/app/views/layouts/application.html.haml
@@ -37,6 +37,7 @@
 
     %meta{ name: 'turbo-prefetch', content: true }
     %meta{ name: 'view-transition', content: 'same-origin' }
+    = turbo_refreshes_with method: :morph, scroll: :preserve
     = yield :head
 
     :javascript

Also, here is the HTML before and after I click the button.
Before:

<a class="inline-block flex items-center justify-center transition-all transform-gpu duration-150 disabled:opacity-25 disabled:cursor-not-allowed disabled:shadow-none px-5 py-3 border border-secondary bg-secondary hoverable:hover:bg-secondary-dark hoverable:hover:border-secondary-dark hoverable:active:bg-secondary active:bg-secondary-dark text-white w-full rounded-none" data-turbo-method="post" href="/housekeeping/12/pause"><div class="flex flex-col lg:flex-row items-center">
<svg class="fill-current -ml-0.5 hidden spin fill-current w-4 h-4 lg:mr-3" data-button-loading-target="loadingIcon" viewBox="0 0 512 512"><!--! Font Awesome Pro 6.4.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2023 Fonticons, Inc. --><path d="M477.7 384c21.8-37.7 34.3-81.4 34.3-128C512 114.6 397.4 0 256 0V32c123.7 0 224 100.3 224 224c0 40.8-10.9 79.1-30 112l27.7 16z"></path></svg>

<svg class="fill-current fill-current w-4 h-4 lg:mr-3" data-button-loading-target="icon" viewBox="0 0 320 512"><!--! Font Awesome Pro 6.4.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2023 Fonticons, Inc. --><path d="M32 96V416h80V96H32zM0 64H32h80 32V96 416v32H112 32 0V416 96 64zM208 96V416h80V96H208zM176 64h32 80 32V96 416v32H288 208 176V416 96 64z"></path></svg>

<span>Pause</span>
</div>

</a>

After:

<a class="inline-block flex items-center justify-center transition-all transform-gpu duration-150 disabled:opacity-25 disabled:cursor-not-allowed disabled:shadow-none px-5 py-3 border border-secondary bg-secondary hoverable:hover:bg-secondary-dark hoverable:hover:border-secondary-dark hoverable:active:bg-secondary active:bg-secondary-dark text-white w-full rounded-none" data-turbo-method="post" href="/housekeeping/12/resume"><div class="flex flex-col lg:flex-row items-center">
<svg class="fill-current -ml-0.5 hidden spin fill-current w-4 h-4 lg:mr-3" data-button-loading-target="loadingIcon" viewBox="0 0 512 512"><!--! Font Awesome Pro 6.4.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2023 Fonticons, Inc. --><path d="M477.7 384c21.8-37.7 34.3-81.4 34.3-128C512 114.6 397.4 0 256 0V32c123.7 0 224 100.3 224 224c0 40.8-10.9 79.1-30 112l27.7 16z"></path></svg>

<svg class="fill-current fill-current w-4 h-4 lg:mr-3" data-button-loading-target="icon" viewBox="0 0 320 512"><!--! Font Awesome Pro 6.4.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2023 Fonticons, Inc. --><path d="M32 96V416h80V96H32zM0 64H32h80 32V96 416v32H112 32 0V416 96 64zM208 96V416h80V96H208zM176 64h32 80 32V96 416v32H288 208 176V416 96 64z"></path></svg>

<span>Pause</span>
</div>

</a>

Then the HTML if I just refresh the browser window:

<a class="inline-block flex items-center justify-center transition-all transform-gpu duration-150 disabled:opacity-25 disabled:cursor-not-allowed disabled:shadow-none px-5 py-3 border border-secondary bg-secondary hoverable:hover:bg-secondary-dark hoverable:hover:border-secondary-dark hoverable:active:bg-secondary active:bg-secondary-dark text-white w-full rounded-none" data-turbo-method="post" href="/housekeeping/12/resume"><div class="flex flex-col lg:flex-row items-center">
<svg class="fill-current fill-current w-4 h-4 lg:mr-3" data-button-loading-target="icon" viewBox="0 0 384 512"><!--! Font Awesome Pro 6.4.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2023 Fonticons, Inc. --><path d="M32 461.3L0 480V443 69 32L32 50.7 352.2 237.5 384 256l-31.8 18.5L32 461.3zM320.5 256L32 87.7V424.3L320.5 256z"></path></svg>

<span>Resume</span>
</div>

</a>

You'll notice in the before and after the URL of the button gets updated via morphing, but the content does not.

Let me know if there is anything else I can provide.

@trobrock
Copy link
Author

trobrock commented Feb 19, 2024

@krschacht I managed to reproduce this with this repo here: https://github.com/trobrock/rails-morphing-bug

It's worth also mentioning that using a button_tag instead of a link_to works, but I'm not sure why the link tag causes it to break.

@krschacht
Copy link

Hi @trobrock, ah, I see! You're definitely right that it's a bug. I pulled your repo and added a couple other elements to the page too just to convince myself it was morphing. You can see in this animated gif that my

with a random number is updating.

AND... I even duplicated your link_to right beneath the current one and that one morphs just fine! So it's not the link_to.

Zight Recording 2024-02-19 at 02 37 35 PM

@trobrock
Copy link
Author

@krschacht I currently suspect it's something to do with the fact that turbo handles the link click, but I don't know the internals well enough to really know. Morphing works great on this page, except on the link you click. Super weird. If I can help at all, please let me know.

I was able to re-work my code to use button_to, so I'm not blocked on launching morphing anymore.

@krschacht
Copy link

Yes, that's what I thought too. I've tee'd up a couple PRs for Turbo but I don't know it well. I looked a few places that I suspect may be the root, like form_observer.js, form_link_click_observer.js, and morph_renderer.js but I didn't see anything obvious. It would take a bunch of log statements to track it down. I'm not going to chase this one myself but at least there is a clear repro in case someone wants to tackle this.

@trobrock
Copy link
Author

trobrock commented Feb 19, 2024

@krschacht happy to spend some time tracking it down, do you have any recommendations on the easiest way to run a development copy of turbo on this project that I can add those logs into?

@krschacht
Copy link

  • fork this repo and pull down your fork
  • reference this contributors guide: https://github.com/hotwired/turbo/blob/main/CONTRIBUTING.md but most relevant was, yarn playwright install --with-deps, then yarn build, and then run specific tests
  • When I tried running all tests on my dev machine it took forever and there were a lot of failures. I don't quite get that. So I just focus on running specific tests that I find using yarn test:browser src/tests/functional/drive_tests.js:11 --project=chrome

Here's my specific recommendation:

  • Open /tests/functional/form_submission_tests.js and the corresponding tests/fixtures/form.html
  • Fire up a development browser with yarn start and then open http://localhost:9000/src/tests/fixtures/form.html
  • Modify that file in some way in order to get a repro of the specific case you have identified
  • Write a test in form_submission_tests that demonstrates the failure
  • At the top of your test that fails, add page.on('console', message => console.log(message.text())) and then within any of the JS files in the whole repo you can now add console.log(...) and it'll show up every time you run your test. I don't know why, but console.log() from the source is suppressed from the test output unless you add that line.

Good luck spelunking. :) Hopefully that's enough to get you started. And even if you aren't able to track down the bug, even just submitting a PR with a test that repros the bug will be valuable.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

No branches or pull requests

2 participants