40
52

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

【jQuery】二重送信を防止しつつ、連続送信をする方法

Last updated at Posted at 2017-02-13

#はじめに
チャット機能を持つアプリケーションの実装中に、メッセージの2重送信を防ぎたいけど2重送信を防止したら連続送信できないじゃん!という現象にハマったのでその解決方法を記します。

#二重送信を防止
= f.submit "Send", "data-disable-with": "送信中..."
または
= f.submit "Send", data: {disable_with: '送信...'}
とすることで、送信中はボタンを押せなくして、"送信中..."なども文言を表示できます。
しかし、これを実装してしまうと連続投稿ができません。

<連続送信不可>
fda2ca3c63d60385c1b754be5bd68be1.gif

#解決策①
data-disable-with属性を解除する。
$('セレクタ').removeAttr('data-disable-with')

#解決策②
submitのコールバック関数で返り値をfalseにする。
こうすることでフォームの送信を一旦止めることができます。

$('セレクタ').submit(function() {
  …
 return false;
});

<連続送信可能>
63e556849385a64a7b827c54969d59c4.gif

解決策①②共に連続投稿ができるようになりました。

#実際のコード
##解決策①

message.js
$(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('メッセージを送信できません');
    });
  });
});

##解決策②

message.js
$(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

message.html.haml
.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オプション

40
52
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
40
52

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?