【Rails7】ページ移動時に「このサイトを離れますか?」の確認メッセージを表示させる(Stimulusで実装)

コンテンツの編集時に誤ってページを移動して編集内容が消えてしまわないよう、ページ移動時に「このサイトを離れますか?」といった確認メッセージを表示させたい場合があると思います。

今回は、その確認メッセージをRails7のStimulusで実装してみたので、忘備録がてら手順を書き残しておこうと思います。

目次

開発環境

  • Ruby 3.1.2
  • Ruby on Rails 7.0.4
  • Bootstrap 5.2.3
  • M1 Macbook Air 2020
  • mac OS Monterey (ver. 12.4)
  • ターミナル bash (Rosetta 2 使用

確認メッセージの実装手順

やることは非常にシンプルです。

まず、以下のコマンドで確認メッセージ表示用のstimulusコントローラーを作成します。

$ rais g stimulus confirms

app/javascript/controller内にconfirms_controller.jsが生成されるので、これを開いて以下のコードを記述します。

export default class extends Controller {

  connect() {
    const confirmMsg = true
    window.onbeforeunload = function(e){
      e.preventDefault()
      if(confirmMsg){
        e = e || window.e
        e.returnValue = '入力中のページから移動しますか?';
      }
    }
  }

}

また、確認メッセージを表示させたいページに以下のコードを追記してconfirms_controller.jsが反映されるようにします。

今回は入力フォーム(記事投稿フォーム)に表示させたいので、フォーム用のテンプレートファイル_form.html.erb内に記述します。

<!-- confirms_controller.jsを適用させたい範囲を data-controller="confirms" で囲う -->
<div data-controller="confirms">
  <%= form_with(model: post) do |form| %>
    
    ・・・

    <div class="my-3">
      <%= form.submit "投稿する" %>
      <%= link_to "削除する", post, data: { turbo_method: :delete, turbo_confirm: "本当に削除しますか?" } %>
    </div>
  <% end %>
</div>

以上です。

これで入力フォームで編集中にページ移動もしくは更新ボタンを押した場合、確認ダイアログが表示されます。

しかし、このままでは「投稿する」ボタン(Submit)を押した時にも確認ダイアログが表示されてしまい少々鬱陶しいです。

次章では、Submitボタンなど確認ダイアログを表示させたくない要素だけ適用外にする方法について述べていきます。

確認メッセージを適用させたくない要素がある場合(Submitボタンなど)

app/javascript/controller/confirms_controller.jsに以下のコードを追記します。

export default class extends Controller {

  connect() {
    const confirmMsg = true
    window.onbeforeunload = function(e){
      e.preventDefault()
      if(confirmMsg){
        e = e || window.e
        e.returnValue = '入力中のページから移動しますか?';
      }
    }
  }

/************* ↓ 追記 **************/
  notConfirm(){
    window.onbeforeunload = false;
  }
/***********************************/
}

続いて、確認メッセージを表示させたくない要素にdata-action="click->confirms#notConfirm"を追記します。

(rubyコード内に記述する場合はdata: { action: "click->confirms#notConfirm" } と記述。)

<!-- confirms_controller.jsを適用させたい範囲を data-controller="confirms" で囲う -->
<div data-controller="confirms">
  <%= form_with(model: post) do |form| %>
    
    ・・・

    <div class="my-3">
      <!-- 適用させたくない要素に data-action="click->confirms#notConfirm" を追記 -->
      <%= form.submit "投稿する", class: "btn btn-primary", data: { action: "click->confirms#notConfirm" } %>
      <%= link_to "削除する", post, class: "d-inline-block text-danger", data: { turbo_method: :delete, turbo_confirm: "本当に削除しますか?", action: "click->confirms#notConfirm" } %>
    </div>
  <% end %>
</div>

これで指定した要素をクリックした場合は確認メッセージが表示されなくなるはずです。

以上。

参考資料

papadays
「このサイトを離れますか?」を実装するための「beforeunload」イベントの使い方 beforeunloadイベントを使って「このサイトを離れますか?」アラートを制御する方法をご紹介
よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

愛知の34歳。無職で暇になり始めたプログラミング(Ruby on Rails)の忘備録をまとめたブログです。最近は別にやりたいことができたのでプログラミングほぼやっていません。気が向いたらまた再開するかも。僕の日常はメインブログの方で更新しています。

コメント

コメントする

目次