Ajax を使ってウェブサイトの一部分のみを更新する方法です。Ajaxを使うことにより、ページ遷移をなしで、DBと通信しながらページコンテンツの一部を変更することができます。今回は、<select>の<option>が変更されるたびにページの一部を変更するという機能を実装してみます。実装方法は違うかもしれませんが、http://www.assist.org/web-assist/welcome.html と同じような処理です。
htmlページの準備
まずは、DBとの通信のトリガーになる<select>をページに追加します。ユーザーがページの<select>を変更すると、<select>のonchange()が起動します。onchange()からのちほど作成するカスタム関数を呼び出し、その関数からDBとの通信を発動します。そして、ページのコンテンツを変更します。
1 2 | # test.html.erb <%= collection_select(:major, :id, @majors, :id, :name, {:prompt => "Please select your major"},{:onchange => "changeMajor()" }) %> |
これにより、 @majors に格納されている major モデルの id と name がそれぞれ value と<option></option>に動的に記述されます。valueはサーバーに送信される値で、<option></option>はページに表示される文字列です。ここでは :prompt オプションにより何も表示されていない時には “Please select your major” と表示されるます。onchange() メソッドではこれから自分で作成する changeMajor()メソッドを<select>の<option>が変更されるたびに呼び出されます。また<select>のhtml属性idはmajor_idとなります。
1 2 3 4 | # test.html.erb <div id="classList" style="display: inline;"> <%= render :partial => 'classList_body' %> </div> |
この箇所がDBとの通信が終わった時に変更される箇所です。のちほど _classList_body.html.erb というファイルは作成します。<select>が変更されDBとの通信ごとに_classList_body.html.erb が新しくレンダリングされるということですね。
onchange で呼ばれる Javascript 関数の準備
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | // test.html.erb // onchange メソッド function changeMajor(){ var select = document.getElementById('major_id'); var options = document.getElementById('major_id').options; var value = options.item(select.selectedIndex).value; var universityID = <%= @student.universities.first.id %>; $.ajax({ url: "/students/listEachClass", type: "POST", data: 'id=<%= @student.id %>&majorID=' + value + '&universityID=' + universityID }) } |
これが呼び出されるchangeMajor()メソッドです。ポイントは後半の$.ajaxですね。送信するurlと通信方法の指定、そしてコントローラー側が受け取る値をdataで指定しています。前半のJSはもう少しスマートな方法がありそうですね。。。JSはいつもやっつけになってしまいます。
通信ごとに呼ばれるパーシャルの準備
1 2 3 | #_classList_body.html.erb <p><%= @universityID %></p> <p><%= @majorID %></p> |
今回はとてもシンプルです。この@universityID と@majorID はコントローラーで作成される変数?です。onchagenメソッドで選択されている<select>の値がサーバーに送信され、コントローラーで作成された変数を後ほど作成するJavascriptファイルからこのパーシャルをレンダリングする際に、それらの値を渡すことで、このパーシャルの中で使うことができます。
Javascriptファイルの準備
1 2 3 | # listEachClass.js.erb # 上記のtest.html.erbがあるviewフォルダにこのファイルを作成 $("#classList").html("<%= escape_javascript(render 'classList_body', :majorID => @majorID, :universityID => @universityID) %>"); |
ここでは上記の test.html.erb で指定した id=classList <div>に 2 で作成したパーシャルをレンダリングするということを記述しています。render する際に、コントローラーで作成された変数をパーシャルで使えるように渡しています。
コントローラーの準備
1 2 3 4 5 6 7 8 | def listEachClass puts "==== Here is the listEachClass!! ====" @majorID = params[:majorID].to_i @universityID = params[:universityID].to_i puts @majorID puts @universityID end |
コントローラーはみなさん思い思いの処理をしていただければいいと思います。params[:majorID] やparams[:universityID] と記述することにより、1で作成したchangeMajor()のdataで渡された値を参照することができます。ここでは単に数値にしてそれをログに表示させているだけです。何もしていませんね。
以上です。