hotwired / turbo

The speed of a single-page web application without having to write any JavaScript
https://turbo.hotwired.dev
MIT License
6.56k stars 415 forks source link

Force visit of same page with different params #820

Closed kalsan closed 1 year ago

kalsan commented 1 year ago

Assuming the following three paths:

path_a = '/a'
path_b1 = '/b?foo=1'
path_b2 = '/b?foo=2'

The following works fine:

link_to path_a
link_to path_b1
link_to path_b2

However, when adding Turbo's method as follows, visits from b1 to b2 and vice versa no longer work. The click triggers a page load, but the parameter does not change.

link_to path_a, data: { turbo_method: :get }
link_to path_b1, data: { turbo_method: :get }
link_to path_b2, data: { turbo_method: :get }

I suspect that Turbo thinks that b1 and b2 are the same thing, because just the parameter changes. Please note that above example is artificial and I did my best trying to understand and extract the problem that's going in the actual application, which is has more complexity around it.

If you can reproduce this, please let me know whether this is a bug or feature. In the latter case, is there another workaround than omitting turbo_method when it is get?

seanpdoyle commented 1 year ago

Thank you for opening this issue.

I've opened https://github.com/hotwired/turbo/pull/821 to try and resolve it.

It's worth highlighting the fact that <a data-turbo-method="get"> is redundant, since <a> elements are submitted as GET requests to begin with, and are already equivalent to <form method="get"> submissions.

Could you share more about your use case, and what led to these circumstances?

kalsan commented 1 year ago

Thank you for your blazingly fast answer. The reason why I ran into this is that I'm building a collection of convenience methods, in particular a helpers that renders a button. It's used somewhat like:

<%= button(label: 'Delete this post', method: :delete, path: delete_user_path(current_user)) %>

So the signature of the button is of the sorts:

def button(label:, path:, method: :get)
  ...
end

For the destroy button to work in Rails 7, data-turbo-method is necessary and I set it to the method param.

The workaround is trivial: omitting data-turbo-method entirely when method is :get. I decided to open this issue anyway as the behavior observed in conjunction with non-path GET params came as a bit of a surprise.

kalsan commented 1 year ago

Reading #821 :

Even though that pattern should be avoided, this commit aims to prevent surprising behavior whenever it occurs.

We're definitively on the same page here :-)

seanpdoyle commented 1 year ago

For the destroy button to work in Rails 7, data-turbo-method is necessary and I set it to the method param.

The data-turbo-method attribute should only be used on <a> elements. Does your button helper construct <a> elements?

If not, a <button> that submits a <form method="post"> containing an <input name="_method" value="delete"> would work with Turbo without any additional steps. It'd even work without JavaScript enabled at all.

kalsan commented 1 year ago

Does your button helper construct elements?

Yessir ^^