はじめに
Rails 初学者がアウトプットとして学習したことを投稿していきます。
環境
下記のバージョンで検証しています。
- Ruby 2.5.6
- Rails 5.2.3
やりたかったことと問題点
チェックリストを選択すると Ajax で動的にコンテンツが切り替わる実装をしたいと考えました。
そのために js 形式でリクエストを送信するフォーム (remote: ture
を設定) を作成し、フォーム内のチェックボックスの変更を起点に、jQuery でフォームの送信を試みました。
= form_with url: ajax_path, method: :get do |f|
= f.check_box :check_box
= f.label :check_box
実際に生成された HTML は以下のようになります。
<form action="/ajax" accept-charset="UTF-8" data-remote="true" method="get">
<input name="utf8" type="hidden" value="✓">
<input name="check_box" type="hidden" value="0">
<input type="checkbox" value="1" name="check_box" id="check_box">
<label for="check_box">Check box</label>
</form>
form_with
はデフォルトでremote: true
が設定されています。実際に生成された form タグにもdata-remote="true"
になっており、反映されています。
チェックボックスをチェックした時に、フォームを送信するように jQuery を記述しました。
jQuery(document).ready(function() {
// name="check_box" の input タグの変更を起点に発火
$('input[name="check_box"]').change(function() {
// チェックボックスの親要素 = フォームを送信
$('#check_box').parent().submit();
});
});
これでチェックボックスをチェックした時点でフォームが送信されるはずです。
しかし、実際には送信されたリクエストは js 形式ではなく、 html 形式になっていました。
原因
Rails 5.1 から導入された rails-ujs というライブラリが関係しているようです。Rails 5.0 まで使用されていた jquery-ujs が、jQuery 依存からの脱却のために rails-ujs へと切り替えられました。
その影響で、それまで問題なく js リクエストを送信できていたsubmit();
が html リクエストを送るようになってしまったようです。
解決策
rails-ujs から提供されているRails.fire
メソッドで対応できます。
jQuery(document).ready(function() {
// name="check_box" の input タグの変更を起点に発火
$('input[name="check_box"]').change(function() {
// ここを変更
Rails.fire($('#check_box').parent()[0], 'submit');
});
});
実際にチェックボックスにチェックを入れてみると、
js 形式リクエストで送れました。解決!
対応するコントローラー#アクションと、ajax.js.slim
のようなファイルを用意してあげれば Ajax で表示を変更することができると思います。
Ajax による表示変更の実装はこちらの記事がわかりやすいです。
終わりに
今回は対応できましたが、rails-ujs については正直わかっていない部分が多いので、勉強が必要ですね。
ちなみに、ajax:success
といったイベントハンドラも jquery-ujs から変更されているようなので、注意してください。