はじめに
Rails7以前までは[Rails]submitタグにつけておきたいdisable_withオプションの記事にあるように、data属性にdisable_with
を付与すれば、二重送信が防止できておりました。
= form_with(model: model) do |form|
= form.submit '登録', { data: { disable_with: '登録中・・・' }
ですが、Rails7移行では、disable_with
オプションが機能しなくなっているので、どのように実現したかを残しておきます。
どう変わったのか
Rails 7.0 + Ruby 3.1でゼロからアプリを作ってみたときにハマったところあれこれ
の記事にある通り、クラスで登録
を登録中・・・
の表示を切り替えています。
turboのPRを覗いて見てもあんまり親切じゃないです。
サンプル
では、どのように二重送信を防止するかのサンプルです。
= form_with(model: model, data: { controller: 'form', action: 'submit->form#disableSubmitter' }) do |form|
button.submit_button data-form-target='submitter'
span.show-when-enabled 登録
span.show-when-disabled 登録中・・
@tailwind base;
@tailwind components;
@tailwind utilities;
/* 送信ボタン disabled 切り替え */
button {
.show-when-disabled {
@apply hidden;
}
.show-when-enabled {
@apply inline;
}
}
button:disabled {
.show-when-disabled {
@apply inline;
}
.show-when-enabled {
@apply hidden;
}
}
import { Controller } from "@hotwired/stimulus";
export default class extends Controller {
static targets = ["submitter"];
disableSubmitter() {
this.submitterTarget.disabled = true;
}
}
formをsubmitするときにdisableSubmitter
を呼び、submitter
のdisabedをtrue
にしています。
BE側のバリデーションのみの場合はこちらで機能します。
フロント側でバリデーションをする場合
FE側でもバリデーションをする場合は少し工夫が必要です。
= form_with(model: model, data: { controller: 'form', action: 'submit->form#disableSubmitter' }) do |form|
button.submit_button data-form-target='submitter'
span.show-when-enabled 登録
span.show-when-disabled 登録中・・
view側は同じです。
import { Controller } from "@hotwired/stimulus";
export default class extends Controller {
static targets = ["submitter"];
disableSubmitter() {
this.submitterTarget.disabled = true;
if (!this.validateForm()) {
event.preventDefault(); // フォーム送信をキャンセル
this.submitterTarget.disabled = false;
}
}
validateForm(){
// some validations
}
}
バリデーションがfalse
の場合は、フォームの送信をキャンセルし、submitter
のdisabledをfalse
にし、再度submitできるようにしています。
まとめ
Rails7でFormの二重送信防止方法を紹介しました。
これまで通りdisable_with
で二重送信防止ができると思っていたら、実はできていなかった...。
そんなことにならないように、一役立てれば幸いです。
参考