2019-11-15に更新

【Rails】Ajaxでプルダウンを選択したらフォームに自動挿入2

参考にしたサイト

はじめに

前回の続きで、入力フォーム画面で、プルダウンで事前に作っておいたテンプレートを選択したらそれを自動でフォームに反映されるような機能の実装について。

具体的にJavascript(jQuery)の記述に入ってきますが、この辺の文法のインプットが追いついていないので手順メインの備忘録として。

1.実装の流れ

おさらい。


(1)まずjQueryをRailsで動かせるようにする
    - Gemfile と application.js に書き足す

(2)ルーティング
    - routes.rb に記述

(3)ajax通信したいフォームをパーシャル化して中身を記述
    - views/works以下に_work_body.html.erbというパーシャル作成

<↑前回ココまで↑>
<↓今回ココから↓>

(4)プルダウンを選択したらJavascriptの機能を呼び出すように記述
    - collection_selectにHTMLオプションでonchangeでJavascriptメソッドを

(5)Javascriptで具体的な機能を記述

(6)コントローラーの中にajaxに関連する処理を記述
- templatesコントローラーに記述
- respond_toの中にformat.jsを記述してajaxを使用可能に

(7)ajaxで呼び出されるjsファイルを作成し、中身を記述
- views/templates以下にget_body.js.erbというファイル作成

2.実装内容

具体的に見ていきます。

(4)プルダウンを選択したらJavascriptの機能を呼び出すように記述

プルダウンリストを作っているcollection_selectに追加します。
HTMLオプションとしてonchangeを使ってJavascript関数を呼び出すように記述します。

views/works/_form.html.erb

<%= collection_select(:template, :name, templates, :id, :name, {:include_blank => true},{class: 'ChoseTemplate', :onchange => "changeTemplate($(this).val())"}) %>

こんな感じですね。確認ですがnew.html.erbから飛んできてるフォーム部分のパーシャルです。

{class: 'ChoseTemplate', :onchange => "changeTemplate($(this).val())"}

この部分がHTMLオプションになります。
onchange以降が、フォーム(ここではプルダウンリスト)が変更された時に関数(イベント)を呼び出す書き方です。関数名はchangeTemplateと名前をつけましたが、この中身については次で記述します。

(5)Javascriptで具体的な機能を記述

ビューの下にscriptタグで呼び出されるJavascript関数を記述してみます。

views/works/_form.html.erb

<script>
  function changeTemplate(val){
    var template_id = val;

    $.ajax({
      url: "/templates/get_body",
      type: "GET",
      data: {
        template_id: template_id
      }
    })
  }
</script>

文法の解説は省略!(すんませんw)
この関数によって色々とごにょごにょされて、変数template_idにプルダウンで選択されたテンプレートのidが入って吐き出される訳です。
これを次のコントローラーに渡して処理してもらえれば良さそうです。
というか、ajaxの記述部分で渡しているっぽいですね。url: "/templates/get_body,"のところで、変数を渡すコントローラー名とメソッド名を指定しています。メソッド名は何でも良さそうなのでget_bodyとします。

ビューの中にscriptタグでJavascript関数を記述しましたが、
Javascript関数はapp/assets/javascriptsの中にjsファイルを作ってまとめておく方が後から探しやすかったり色々と便利そうです(メンターさんからは好みとも言われましたが)
ファイル名で動作がわかりやすいようにchange_templates.jsという名前ででも作っておきます。

(6)コントローラーの中に処理を書いて、Ajaxを使用可能にする

templatesコントローラーに処理を書きます。
処理されるのは先ほどajaxで記述したget_bodyメソッドなので、このメソッドを定義して記述します。

controllers/concerns/templates_controller.rb

  def get_body
    template = Template.find(params[:template_id])
    @template_body = template.body
    respond_to do |format|
      format.js
    end
  end

うまくいっていれば先ほどプルダウンで選択したテンプレートのidがtemplate_idで渡されてくるので、
コントローラー側ではまずそのidに該当するテンプレートを探してきて、そのbodyを取得して変数@template_bodyに格納します。これが最終的にビューに表示させたい内容ですね。

その後のrespond_toの中にformat.jsを書くのは「Ajaxリクエストの場合js形式で返す」という意味があるようです。
要するに普段はアクションが実行された時は、コントローラー名と同じフォルダのアクション名.html.erbというファイルが呼び出されて画面に表示されますが、
今回はAjaxリクエストなので、アクション名.js.erbというファイルが呼び出される、ということでしょうかね。

では最後にこのjsファイルを作成します。

(7)ajaxで呼び出されるjsファイルを作成し、中身を記述

views/templates以下に、アクション名と同名のget_body.html.erbというファイルを作成。その中に、取得したtemplate_bodyを画面に表示させる処理を書きます。

views/templates/get_body.html.erb

$("#template_body").html("<%= j(@template_body) %>") 

文法の解説は省略!(すんませんw)

長くなりましたが、これでめでたく「プルダウンでテンプレートを選択し、そのテンプレートのbodyをフォームに表示させる」機能が実装完了となります!

3.補足

参考リンクとして2つのページのリンクを貼っていますが、これらは僕が実装したかったことと全く同じではないですが、手がかりのない中で実装の流れを把握する上で大いに参考にさせてもらったサイトです。
参考リンク1は僕が学んでいる先生のRailsプログラミング学習サービスで、チュートリアル的に学習することができるようになっています。

MEMO

今回の実装内容では、リストから選択したら自動でフォームに入力される挙動をとりますが、
プルダウンリストを選択した状態で「挿入」ボタンをクリックしたらそのテンプレートの内容が追加される、というものも実装できるようにしてみたいなーとか考えています。
 
 
自分の理解度が低すぎてこんなの公開していいのやら小一時間悩みましたが、
アウトプットは理解度を深めたり再現性を高めたりするために大切な作業だなあとも感じます。
クソ記事に分類されてしまう不安と戦いながら公開ボタンをポチッと

技術ブログをしっかり書いてみて困ったのが、用語を正確に使えないことでした。
調べながらやってはいますが、普段用語の正確な意味を理解せずなんとなくインプットしているんだな…と突きつけられます。
要素、属性、プロパティ、メソッド、アクションの使い方とかかなり怪しい。
JavascriptとjQueryの理解も怪しい。(正直言ってしまうとJavascriptとjQueryの違いすら曖昧なレベルでとてもはずかしい)

このテンプレート機能はしっかりまとめておくと面白そうなので、今後しっかり書き直すことを目標に実力をつけていきます!


Massa

北海道の畑作専業農家・WEBエンジニア修行中の30代。「自然の中で感じたことをカタチにする」をモットーに、農業とITを掛け合わせた仕事に携わりたいなあと思ってます。農業の効率化と発展を目指して。のんびり畑を耕したいw ■Ruby/Rails ■Capoeiraがライフワーク ◇noteでブログ書いてます

Crieitは個人で開発中です。 興味がある方は是非記事の投稿をお願いします! どんな軽い内容でも嬉しいです。
なぜCrieitを作ろうと思ったか

また、「こんな記事が読みたいけど見つからない!」という方は是非記事投稿リクエストボードへ!

こじんまりと作業ログやメモ、進捗を書き残しておきたい方はボード機能をご利用ください!

ボードとは?

コメント