Web開発をしていれば、二重クリックを防止したくなることがあります。
ただのページ遷移であれば不要かもしれませんが、データを更新するようなボタンが2度押されると面倒です。
そんなケースで、うっかりダブルクリックしてしまったときに意図せぬ挙動にならないよう、一度押したボタンを非活性にする必要があります。(=フロントで防止)
色々な方法がありましたので、まとめてご紹介します。
form_with~submitに対して二重クリック防止
二重クリックを防止したいボタンって、ページ遷移とかではなく、何かデータの更新が入る処理だと思います。つまり、多くの場合、問題になるのはsubmitボタンを押す時です。
1.RailsのViewヘルパーを使用する方法
slimファイル表記で、
= form_with ... |f|
.
.
.
= f.submit "hoge", 〜
の場合、実は、特に対策しなくても二重クリックは起きません。ヘルパーが裏でよしなにしてくれているみたいです。これが一番簡単で確実ですね。
2.disable_withを使う方法
そうは言っても、デザインが指定されている場合など、どうしてもbutton[type="submit"]
(あるいはtype=“button”
)を使わざるを得ないこともあるかもしれません。
その場合は、対策しないと二重クリックが起きてしまいます。
そんなときは、button_tagのdataオプションを利用してあげたらうまくいきました。
edit.html.slim = form_with... . . . = button_tag "送信する", class: "button-primary", data: { disable_with: "送信する" }
これで送信できました。submitってどこにも書いてないのに・・・(不思議)←勉強不足
3.確認ダイアログを挟む方法
そもそも、DBにそんな破壊的な変更を加えるボタンなら、うっかりクリックしないように確認ダイアログを挟んであげる方がユーザーフレンドリーです。
= button_tag '削除', data: { confirm: "ユーザー削除", commit: "削除する", cancel: "キャンセル" }, title: "ユーザーを完全に削除しますがよろしいですか?"
ボタンを押しても確認ダイアログが出てくるだけですので、二重クリックを心配する必要はありません。
確認ダイアログのコミットボタンは、押した瞬間引っ込んで消えるので、こちらも二重クリックを心配する必要がありません。
もちろん、link_to
でもこちらのdataオプションは使えます。
link_toに対して
= link_to に対しても、上記確認ダイアログを挟む方法は有効です。ただ、UI的にそこまでしたくない、という場合は、JS制御が必要です。
application.js // 二重クリックを防止したいlink_toに"prevent-double-click"クラスを設定 $(document).on("turbolinks:load", function () { $(".prevent-double-click").on("click", function () { $(this).addClass("disabled"); }); });
上記に加え、HTMLのlink_to要素にprevent-double-clickクラスを付与してください。
= link_to "ユーザーを削除する", user_path, method: :delete, class: 'prevent-double-click'
これで、クリックした瞬間にボタンが非活性になりそれ以上押せなくなります。
別途バックエンドでも対策を
二重クリックをフロントで防止する方法について紹介してきました。
ただ、ここでひとつ注意喚起です。二重クリック対策はフロントだけで防止して満足せず、バックエンド(コントローラー側)で対策することも怠らないでください。なぜなら、二重クリックせずとも2回以上クリックすることは可能だからです。例えば、そのボタンの画面をブラウザの別タブでも開いておけば、画面遷移せずにそのボタンを連続で2回押すことができてしまいます。これを防止するため、ステータスチェックを挟んだり、lock_versionを使って排他制御(楽観ロック)をかけることを検討すべきです。
もちろん、逆にバックエンドのみの対策だと、うっかり二重クリックした際に意図しない挙動になってしまいます。(ユーザー削除ボタンを押した際にうっかり二重クリックしてしまったら、「そんなユーザーはいません」みたいな)
したがって、フロントを制御することは大切なのです。そのときに、この記事がお役に立てましたらこの上ない喜びです。
最後まで読んでくださってありがとうございました!
コメント