[Rails5] submit 태그에서 Ajax를 사용하면 두 번째 이후에 비활성화됩니다.

13549 단어 아약스Rails5

하고 싶은 일



메시지를 보내는 폼에서 submit을 실행했을 때 Ajax에서 POST를 실행시켜 메시지 목록에 보낸 내용을 추가한다.

환경



Ruby: 2.3.1
Rails: 5.0.7
브라우저: Google 크롬
OS: macOS 10

빠진 것



아래와 같이 구현했을 때, 최초의 메세지의 송신은 성공하지만, 2회째 이후는 submit 이벤트가 발화하지 않게 되었다.
라고 할까, 원래 submit 버튼을 누를 수 없게 되었다.



보기



index.html.haml
= form_for @message do |f|
  = f.text_field :content, class: "form__text"
  = f.submit "Send", class: "form__submit"

↓첫회 로드시에 완성된 HTML

색인
<form class="new_message" id="new_message" action="/messages" accept-charset="UTF-8" method="post">
  〜中略〜
 <input class="form__text" type="text" name="message[content]" id="message_content">
 <input type="submit" name="commit" value="Send" class="form__submit" data-disable-with="Send">
</form>

뷰 레이아웃


자바스크립트



JavaScript(jQuery)는 이런 느낌.

send.js
$(() => {
  // formタグのsubmitが実行された時の処理
  $("#new_message").on("submit", (e) => {
    e.preventDefault();
    const formData = new FormData(e.target);
    const url = $(e.target).attr("action");

    // Ajax処理
    $.ajax({
      url: url,
      type: "POST",
      data: formData,
      dataType: "json",
      processData: false,
      contentType: false
    }).done((data) => {
      // 成功したらメッセージ表示エリア(class="messages")に送信したメッセージをHTMLで追加する
      // ここはテンプレートリテラルで自力でHTMLを組み立てる
      const html = `<div class="message__content">
                   ${data.content}
                  </div>`;
      $(".messages").append(html);
      $(".form__text").val("");
    }).fail(() => {
      // 失敗した時の処理
      alert("メッセージの送信に失敗しました。");
    });
  });
});

직접 원인(왜 2회째 이후는 이벤트가 발화하지 않는 것인가?)



1회째의 submit 후, 다시 개발자 툴로 HTML을 봐 보면 이렇게 되어 있었다.

색인
<form class="new_message" id="new_message" action="messages" accept-charset="UTF-8" method="post">
 <input class="form__text" type="text" name="message[content]" id="message_content">
 <input type="submit" name="commit" value="Send" class="form__submit" data-disable-with="Send" disabled="">
</form>

왜 disabled가 들어 있는 거야! !
disabled 때문에 submit 버튼이 무효화되어 이벤트가 발화하지 않았던 것입니다.

간접 원인(왜 마음대로 disabled가 들어갔는가?)



한 번 보내면 자동으로 disabled가 활성화되는 이유는 "data-disable-with"라는 속성이 submit에 포함되어 있기 때문입니다.
이것은 이중 전송을 억제하기 위해 submit_tag에 Rails5에서 기본적으로 추가 된 사양 인 것 같습니다.

Rails5.0의 릴리스 노트에 썼습니다.

disable_with를 submit 태그의 기본 동작으로 설정합니다. 이렇게하면 전송시 버튼을 비활성화하고 이중 전송을 방지합니다.

해결책



사양으로 자동적으로 무효가 되어 버리는 것 같습니다만, 이 설정 자체를 무효화하는 (Rails4 이전의 사양에 되돌리는) 것도 가능한 것 같습니다.
다만, 그것이라고 이번 Rails 사양 변경으로 대책한 2중 송신 문제가 현재화해 버리므로, 이벤트 처리로 다시 유효화해 주는 쪽이 영향이 적어져 끝난 것 같습니다.

이후에 각각의 해결 방법을 기재합니다.

1) 레일의 설정을 변경하는 방법



config/application.rb
class Application < Rails::Application
  config.action_view.automatically_disable_submit_tag = false # この行を追加
end

↓ 웹 서버 재시작 후 HTML 파일

색인
<input type="submit" name="commit" value="Send" class="form__submit">

data-disable-with가 사라졌습니다!

2) jQuery에서 어떻게 든



submit 실행 후에 자동으로 disabled 속성이 추가되므로, Ajax 통신 종료 처리로서 이 속성을 지워 버립니다.

send.js
 〜中略
$.ajax({
 〜中略
}).done((data) => {
  const html = buildHTML(data);
  $(".messages").append(html);
  $(".form__text").val("");
}).fail(() => {
  alert("メッセージの送信に失敗しました。");
})
// ここから
.always(() => {
$(".form__submit").removeAttr("disabled");
});
// ここまで追加
 〜中略

참고


  • Rails5.0부터 data-disable-with가 디폴트의 움직임이 된 기재(Rails 가이드 5.0 릴리스 노트)
  • Rails 설정에서 피하는 방법(stack overflow: Rails data-disable-with re-enabling button)
  • 2중 송신을 하는 방법(Qiita: Rails로 form2중 송신으로 빠진다)
  • 템플릿 리터럴에 대해(Qiita: JavaScript 템플릿 리터럴을 극대화!

  • 근황



    최근에는 iOS 앱 개발에도 손을 잡으려고 Xcode와 Swift4와 함께 야후옥 앱 엔지니어의 등룡문 같은 할인 계산 앱을 만들어 공부 중.

    좋은 웹페이지 즐겨찾기