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

Turbo can't be disabled for links with method: post/delete #288

Closed
efatsi opened this issue Jun 18, 2021 · 20 comments
Closed

Turbo can't be disabled for links with method: post/delete #288

efatsi opened this issue Jun 18, 2021 · 20 comments

Comments

@efatsi
Copy link

efatsi commented Jun 18, 2021

I've seen a few issues hovering around this issue (hotwired/turbo-rails#31, #45, #74). But it seems that disabling turbo is not respected for links with non-GET methods.

I'm attempting to do the following:

link_to "Log Out", destroy_user_session_path, method: :delete, data: { turbo: false }

and the request is always processed as TURBO_STREAM:

Started DELETE "/users/sign_out" for ::1 at 2021-06-18 13:25:48 -0400
Processing by Users::SessionsController#destroy as TURBO_STREAM

If I use button_to instead of link_to, the disabling of turbo works properly.

Versions:

  • Ruby Gems:
    • rails (6.1.3.2)
    • turbo-rails (0.5.9)
  • NPMs:
    • @hotwired/turbo-rails: 7.0.0-beta.5
    • @rails/ujs: 6.1.3
@tleish
Copy link
Contributor

tleish commented Jun 24, 2021

The team added support for links and POST|PUT|PATCH|DELETE in v7.0.0-beta.6

see: https://github.com/hotwired/turbo/releases/tag/v7.0.0-beta.6

@efatsi efatsi closed this as completed Jun 24, 2021
@reinaris
Copy link

@efatsi did the new release fixed this for you?

In my case, it does work, but it's still processing the delete as turbo_stream. Which caused my flash message to disappear (it redirects twice).

@efatsi
Copy link
Author

efatsi commented Jul 27, 2021

I pulled down 7.0.0-beta.6 and it looks like the rails server is still processing the actions as TURBO_STREAM.

@efatsi efatsi reopened this Jul 27, 2021
@jonatassalgado
Copy link

jonatassalgado commented Aug 2, 2021

@efatsi did the new release fixed this for you?

In my case, it does work, but it's still processing the delete as turbo_stream. Which caused my flash message to disappear (it redirects twice).

For me works only forcing redirect to html format in sessions controller, like below:

# app/controllers/users/sessions_controller.rb

def destroy
    signed_out = (Devise.sign_out_all_scopes ? sign_out : sign_out(resource_name))
    set_flash_message! :notice, :signed_out if signed_out
    yield if block_given?
    respond_to_on_destroy
end


private

def respond_to_on_destroy
    respond_to do |format|
	format.all { redirect_to root_path(format: :html) }
    end
end

@mmhan
Copy link

mmhan commented Aug 7, 2021

I am also facing the same issue, I wish to turn off turbo for my omniauth buttons and currently they are not working.

%a.btn.btn-outline-facebook.w-100.mt-2{ href: user_facebook_omniauth_authorize_path,
                                                        data: { method: :post,
                                                                turbo: 'false' } 

I am on -

❯ bundle info turbo-rails
  * turbo-rails (0.6.0)

❯ yarn list @hotwired/turbo
└─ @hotwired/[email protected]

@mmhan
Copy link

mmhan commented Aug 9, 2021

I have seen other threads pointing out that you should use button_to with data-turbo="false" for form tag.

However, as it has been pointed out they are semantically different. Moreover, with button_to you cannot use font-awesome icons on your button's text.

Please let us know how can we workaround this, or if there is a fix coming soon.

@fabianzwodrei
Copy link

fabianzwodrei commented Aug 30, 2021

Using 7.0.0-beta.6: My sign-out link for devise is working with the data-turbo-method but its reponse comes via TUBRO_STREAM and the following redirection is misguided by keeping the DELETE method.

<%= link_to "Logout", destroy_user_session_path, method: "DELETE", data: {"turbo-method": "DELETE"}%>

log:

Started DELETE "/users/sign_out?locale=en" for 127.0.0.1 at 2021-08-30 21:12:59 +0200
Processing by Devise::SessionsController#destroy as TURBO_STREAM
  Parameters: {"locale"=>"en"}
  User Load (0.4ms)  SELECT "users".* FROM "users" WHERE "users"."id" = $1 ORDER BY "users"."id" ASC LIMIT $2  [["id", 2], ["LIMIT", 1]]
Redirected to http://localhost:3000/?locale=en
Completed 302 Found in 5ms (ActiveRecord: 0.4ms | Allocations: 1858)


Started DELETE "/?locale=en" for 127.0.0.1 at 2021-08-30 21:12:59 +0200
  
ActionController::RoutingError (No route matches [DELETE] "/"):

@tleish
Copy link
Contributor

tleish commented Aug 30, 2021

@fabianzwodrei - I think this is an issue with Devise and XHR requests, and creates problems with Turbo since it uses XHR. Similar issue reported on Stack **Overflow.

I believe this is because devise does not include status in redirect_to wi the session destroy (DELETE) action?

see: ActionController::Redirecting

If you are using XHR requests other than GET or POST and redirecting after the request then some browsers will follow the redirect using the original request method. This may lead to undesirable behavior such as a double DELETE. To work around this you can return a 303 See Other status code which will be followed using a GET request.

redirect_to posts_url, status: :see_other
redirect_to action: 'index', status: 303

I'm not sure any changes to turbo would solve this.

I think your options are:

  1. Use button_to (instead of link_to). This works since button_to creates a POST request (instead of DELETE) with params[:_method] = 'DELETE'.
  2. Configure devise sign out via GET with link_to (config.sign_out_via = :get)
  3. MonkeyPatch Devise controller to include status in redirect_to

@fabianzwodrei
Copy link

Thanks @tleish !

I tried the button_to and a form (incl the turbo method) method, but the problem was the same.

Your suggestion to change the devise configuration to use a GET for sign_out was the most elegant solution for me right now.

@afomera
Copy link

afomera commented Sep 10, 2021

Also running into this and was quite confused what was happening/why it was still sending as a TURBO_STREAM despite having disabled turbo both at my link level and higher up.

Edit: 7.0.0-rc.3 for Turbo-rails package here

@mmhan
Copy link

mmhan commented Sep 13, 2021

@afomera - From what I have observed, ujs creates a brand-new form element when you click a link with data-method and submits the form. Since the form element isn't created with data-turbo="false" it will submit via Turbo and result in a fetch request.

@nachoal
Copy link

nachoal commented Oct 29, 2021

I solved with @tleish solutions, it was the simplest way right now:

Configure devise sign out via GET with link_to (config.sign_out_via = :get)

Thanks!

@Erayd24
Copy link

Erayd24 commented Oct 30, 2021

<%= button_to "Delete", url, method: :delete, class: 'button med-button', "data-turbo": false %>

This code works for me, though if I change it to a link_to or remove the data-turbo line it doesnt redirect. Just data-turbo = false or just button_to doesnt work either, it has to be both. And for whatever reason I can't figure out, it was somehow ending up at my show method for pages instead of redirecting to the page I specified. I dont understand why it just ignores redirects. Doesn't even get in to the desired controller action.

satoryu added a commit to satoryu/sealion-rails that referenced this issue Nov 27, 2021
@guilhermereis1
Copy link

It's work for me 100%
<%= link_to "Logout", destroy_user_session_path, method: "DELETE", data: { "turbo-method": "DELETE" } %>

@mikehulbert
Copy link

I'd imagine a few people will get caught out with Rails 7 like myself, clear explanation in the docs here.

  • turbo attempts to submit forms although it can be easily disabled by wrapping form
  • avoid using <%= link_to %> for anything other than get requests
  • use <%= button_to %> for post requests
<div data-turbo="false">
    <form>
       <a href="/" data-turbo="true">Enabled if needed</a>
   </form>
</div>

@dahveed-rb
Copy link

I'd imagine a few people will get caught out with Rails 7 like myself, clear explanation in the docs here.

  • turbo attempts to submit forms although it can be easily disabled by wrapping form
  • avoid using <%= link_to %> for anything other than get requests
  • use <%= button_to %> for post requests
<div data-turbo="false">
    <form>
       <a href="/" data-turbo="true">Enabled if needed</a>
   </form>
</div>

Same goes for all other non get requests (i.e. patch, delete)

@arusa
Copy link

arusa commented Feb 13, 2022

I'd imagine a few people will get caught out with Rails 7 like myself, clear explanation in the docs here.

  • turbo attempts to submit forms although it can be easily disabled by wrapping form
  • avoid using <%= link_to %> for anything other than get requests
  • use <%= button_to %> for post requests
<div data-turbo="false">
    <form>
       <a href="/" data-turbo="true">Enabled if needed</a>
   </form>
</div>

Cool to see some helpful advice, but in my case it doesn't seem too easy to avoid link_to for my button.

I'm using a tailwindcss styled link_to button with an SVG inside. When I change link_to to button_to I get something that doesn't work:

<input type="submit" value="<svg..."...

Also setting turbo-method: "DELETE" doesn't work for me, because the requested format is still TURBO_STREAM.

I would like to be able to use turbo/hotwire for live deleting elements from pages like index, but when deleting an object using a button on the show page I would like to do a redirect, because the show page is obsolete after deleting the object.

@arusa
Copy link

arusa commented Feb 13, 2022

OMG I was thinking too complicated. If you want to change the request type you just have to add .html to the end of the request. Or more sophisticated:

# instead of:
link_to "Delete", object, method: :delete
# do
link_to "Delete", polymorphic_path(object, format: :html), method: :delete

@caiofct
Copy link

caiofct commented Jun 28, 2023

Just adding this comment here since it could help others migrating to Turbo and keeping UJS working together.

The link_to "Link", method: :delete helper will create a form behind the scenes with UJS using this code and the form element won't have any data attributes passed down from the link element so adding data: { turbo: false } won't help and the form will essentially be submitted twice, once via turbo and another via html.

We found a really good alternative to keep the existing behavior of UJS without having to change anything else:

Turbo.setFormMode("optin");

By doing this all forms will need to add data-turbo=true in order to be handled by Turbo. This was added by: #419 and can be used with on or off as well.

NOTE: I've tried using button_to "Button", method: :delete, data: { turbo: false } but it will render a form element and that won't work when nested inside another form element and could be very tricky to identify those cases when there are multiple levels of partials being nested.

@Austio
Copy link

Austio commented Jul 23, 2023

Have we considered duplicating the data-turbo attributes from the link to the form?

Something similar to this in rails-ujs.js


        var dataTurbo = e.target.attributes["data-turbo"]

        if (dataTurbo != undefined ) {
          form.setAttribute("data-turbo", dataTurbo)
        }

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