11

Previously in Rails when using the button_to tag, it was possible to use a confirmation dialog like this

<%= button_to 'Destroy', @post, method: :delete, data: { confirm: 'Are you sure?' } %>

data: { confirm: 'Are you sure?' } is Rails magic data attribute that was used by @rails/ujs library under the hood

Following Rails 7, this library is no longer on by default. Instead of this Rails use Turbo library

And now this code does not work

There is no information in official Rails docs and Turbo handbook

What I tried

<%= button_to 'Destroy', @post, method: :delete, data: { turbo_confirm: 'Are you sure?' } %>
<%= button_to 'Destroy', @post, method: :delete, data: { 'turbo-confirm': 'Are you sure?' } %>

But there is no result

I didn't find any solution on SO but found on Hotwire forum. This solution with Stimulus action. I just improve it a little

<%= form_with model: @post, method: :delete, data: { controller:  'confirmation', message: 'Are you sure?', action: 'submit->confirmation#confirm' } do |f| %>
  <%= f.submit 'Destroy' %>
<% end %>
// app/javascript/confirmation_controller.js
import { Controller } from '@hotwired/stimulus'

export default class extends Controller {
  confirm(event) {
    if (!(window.confirm(this.element.dataset.message))) {
      event.preventDefault()
    }
  }
}

It works but it's quite difficult and looks ugly, and we are used to Rails being cool

mechnicov
  • 12,025
  • 4
  • 33
  • 56

5 Answers5

21

In Rails with Turbo without rails-ujs to call confirmation popup window with button_to we need to use code like this

<%= button_to 'Destroy', @post, method: :delete, form: { data: { turbo_confirm: 'Are you sure?' } } %>

or

<%= button_to 'Destroy', @post, method: :delete, form: { data: { 'turbo-confirm': 'Are you sure?' } } %>

Both generate data-turbo-confirm attribute

So we need to add this attribute not to submit button (like in rails-ujs) but directly to form containing this button (let me remind you this tag generates a form with button)

mechnicov
  • 12,025
  • 4
  • 33
  • 56
  • I have weird experience with `link_to` and `method: :delete`. It will do delete the current record, but weird enough to also delete its parent record. – Yakob Ubaidi Apr 14 '22 at 08:09
  • 3
    @YakobUbaidi If your `destroy` action ends with a `redirect_to` (which I doubt is your case), some browsers will redirect to a new location with `DELETE` method, so make sure to add `status: :see_other` parameter to `redirect_to`, like the guides [suggest](https://guides.rubyonrails.org/getting_started.html#deleting-an-article) – mechnicov Jul 06 '22 at 13:43
7

This is a bit complicated in 7.0.3, if it is a page that is using turbo it looks like this:

  <%= button_to "Delete",
                  user_path(user),
                  method: :delete,
                  class: "button tight danger",
                  form: { 
                   data: { 
                     turbo_confirm: "Are you sure you want delete?"
                   }
                  } %>

This makes a little form. Now if you are using turbo, but not on that specific page, you no longer get the simple comfirm: 'message' from the old rails ujs. Instead you have to use stimulus controllers.

# app/javascript/controllers/confirmation_controller.js
import { Controller } from "@hotwired/stimulus"

export default class extends Controller {
  static values = { message: String };

  confirm(event) {
    if (!(window.confirm(this.messageValue))) {
      event.preventDefault();
      event.stopImmediatePropagation();
    };
  };
}

then

# app/javascript/controllers/index.js
import ConfirmationController from "./confirmation_controller"
application.register("confirmation", ConfirmationController)

then

    <%= button_to "Delete",
                  user_path(user),
                  method: :delete,
                  class: "button danger",
                  form: {
                    data: {
                      turbo: false,
                      controller: "confirmation",
                      action: 'submit->confirmation#confirm',
                      confirmation_message_value: "Are you sure you want to delete?",
                    }
                  } %>

It is a bummer that rails removed functionality, but if you want to use hotwire you need to commit to full buy in to the whole ecosystem.

0

I'm not fully understanding this, but the following worked for me

<%= button_to post_path(post), method: :delete, form: { data: { turbo_confirm: 'Are you sure?' } } do %>

an svg which shows a trash can

<% end %>.

I also don't have anything that looks like the OP's confirmation_controller

Greg
  • 2,359
  • 5
  • 22
  • 35
0

not the original question, but as of rails 7.0.4, it would work the same (stimulus-free) :

<%= link_to("Del",
            del_path,
            data: { turbo_method: :delete, turbo_confirm: "Sure?" }) %>
Ben
  • 5,030
  • 6
  • 53
  • 94
0

I ran into this same problem when doing the Ruby on Rails guide here.

The answer above with using the button_to and method: :delete made the delete work, but the confirmation still wasn't working.


Somewhere along the way of me trying things, I stumbled upon mention of the turbo-rails gem. I found a working solution with these pieces:

  1. Add this in the application.html.erb file:
    <%= javascript_include_tag "turbo", type: "module" %>
    
  2. Add gem "turbo-rails", "~> 1.0" to your Gemfile
  3. Run bundle install
  4. Run bin/rails turbo:install
    Note: not sure if this last step is necessary, but I was following instructions from here

Using these steps, the code from the rails guide works, along with the confirmation dialog.

Candice
  • 11
  • 1
  • 2