#はじめに
チャット機能を持つアプリケーションの実装中に、メッセージの2重送信を防ぎたいけど2重送信を防止したら連続送信できないじゃん!という現象にハマったのでその解決方法を記します。
#二重送信を防止
= f.submit "Send", "data-disable-with": "送信中..."
または
= f.submit "Send", data: {disable_with: '送信...'}
とすることで、送信中はボタンを押せなくして、"送信中..."なども文言を表示できます。
しかし、これを実装してしまうと連続投稿ができません。
#解決策①
data-disable-with属性を解除する。
$('セレクタ').removeAttr('data-disable-with')
#解決策②
submitのコールバック関数で返り値をfalseにする。
こうすることでフォームの送信を一旦止めることができます。
$('セレクタ').submit(function() {
…
return false;
});
解決策①②共に連続投稿ができるようになりました。
#実際のコード
##解決策①
$(function() {
// メッセージ送信情報を追加していく関数
function buildHTML(message) {
var html =
'<li class="chat-message">' +
'<p class="chat-message__name">' +
message.name +
'</p>' +
'<p class="chat-message__time">' +
message.time +
'</p>' +
'<p class="chat-message__body">' +
message.body +
'</p>' +
'<br>' +
'<img class="chat-message__image" src="' + message.image + '">'
'</li>'
return html;
}
$('#new_message').on('submit', function(e) {
// HTMLでの送信をキャンセル
e.preventDefault();
var form = $('#new_message');
var $this = $(this);
//追記部分
$('#chat-footer__send-btn').removeAttr('data-disable-with');
// フォームに入力された値を取得
var fd = new FormData($this.get(0));
$.ajax({
type: form.attr('method'), // フォーム要素("post")を取得
url: form.attr('action'), // フォーム要素("/chat_group/chat_group_id/messages")を取得
data: fd,
contentType : false,
processData : false,
dataType: 'json'
})
// サーバーから値が正しく返ってきた場合
.done(function(data) {
var html = buildHTML(data.message);
$('.chat-messages').append(html);
$this.get(0).reset();
autoScroll();
})
// 正しく返ってこなかった場合
.fail(function() {
alert('メッセージを送信できません');
});
});
});
##解決策②
$(function() {
// メッセージ送信情報を追加していく関数
function buildHTML(message) {
var html =
'<li class="chat-message">' +
'<p class="chat-message__name">' +
message.name +
'</p>' +
'<p class="chat-message__time">' +
message.time +
'</p>' +
'<p class="chat-message__body">' +
message.body +
'</p>' +
'<br>' +
'<img class="chat-message__image" src="' + message.image + '">'
'</li>'
return html;
}
$('#new_message').submit(function(e) {//修正部分
// HTMLでの送信をキャンセル
e.preventDefault();
var form = $('#new_message');
var $this = $(this);
// フォームに入力された値を取得
var fd = new FormData($this.get(0));
$.ajax({
type: form.attr('method'), // フォーム要素("post")を取得
url: form.attr('action'), // フォーム要素("/chat_group/chat_group_id/messages")を取得
data: fd,
contentType : false,
processData : false,
dataType: 'json'
})
// サーバーから値が正しく返ってきた場合
.done(function(data) {
var html = buildHTML(data.message);
$('.chat-messages').append(html);
$this.get(0).reset();
autoScroll();
})
// 正しく返ってこなかった場合
.fail(function() {
alert('メッセージを送信できません');
});
//追記部分
return false;
});
});
##HTML
.chat-body
%ul.chat-messages
- @chat_group.messages.each do |message|
%li.chat-message
%p.chat-message__name
= message.user.name
%p.chat-message__time
= message.created_at
%p.chat-message__body
= message.body
- if message.image?
%br
= image_tag message.image.url
.chat-footer
= form_for [@chat_group, @message] do |f|
.chat-footer__body
= f.text_area :body, placeholder: "type a message"
.chat-footer__body__image
= f.label :image do
%i.fa.fa-image
= f.file_field :image
.chat-footer__btn
= f.submit "Send", "data-disable-with": "送信中...", id: 'chat-footer__send-btn', class: 'chat-footer__send-btn'
#おわりに
rails2ヶ月目、jquery1ヶ月目の超初心者です。
改善点、問題点がありましたらご指摘よろしくお願いいたします。
#参考記事
jQueryでフォームの送信を一旦止め、処理を挟んでから送信する方法
[Rails]submitタグにつけておきたいdisable_withオプション