0
3

More than 1 year has passed since last update.

Railsのformを素のJavaScriptで送信する

Last updated at Posted at 2020-09-08

やりたかったこと

form送信後にJS側で何かしらの処理をしたい。

方法

fetchAPIのコールバックチェーンで行うことができる。

turbolinksrails-ujs は使用しないので、 remote: true を使ったAjax通信とも異なるやり方。

「form送信後のJS処理」を、
当初 form.submit() ~ setTimeout() のような感じで書いたが、実行順序が担保されなかったので書き直した。

ポイント

fetch では
1. credentials'same-origin'
2. bodynew FormData(form)
を指定。

= f.submit や %button{ type: 'submit' } を使うと Railsによってリクエストが飛ばされてしまうので、%button{ type: 'button' } を使って送信ボタンをクリックしたときにJavaScriptを呼び出すようにしている。

サンプル

あまりサンプルがなかった気がするのでさらっと残す。
送信ボタンを押した後に二度押せないようにする処理も入れてるが、もっとちゃんとした書き方はあるのかも。

const userForm = document.getElementById('user-form');
const submitBtn = document.getElementById('submit-btn');

submitBtn.addEventListener('click', () => {
  submitBtn.textContent = '送信中...';
  submitBtn.disabled = true;

  fetch('/users', {
    method: 'POST',
    credentials: 'same-origin',
    body: new FormData(userForm),
  }).then(response => {
    // 送信後の処理があればここに書く
  }).catch(error => {
    // 例外処理
  });
});
= form_with(model: @user, id: 'user-form') do |f|
  = f.text_field :name
  = f.text_field :mail
  %button{ type: 'button', id: 'submit-btn' }
    送信

追記

コントローラ側でリクエストを受け取るアクションに、 protect_from_forgery を適切に使うととりあえずリクエストを送信できるようになる
が、CSRF対策をちゃんとやるなら、fetch のパラメータに headers: { 'X-CSRF-Token': csrfToken } を付与する必要な場合がある。

jQueryを使っていると rails-ujs がよしなにやってくれるが、Vanilla.js で書く場合は Rails 側からCSRF のトークンを取ってくる必要がある。
詳しくは以下。

これが一番良さそう

追記2

ajax イベントをキャッチして、フォーム送信を制御する方法もある模様。

参考リンク

0
3
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
0
3