.rjsファイルからAjaxを利用してみる。
.rjsファイルとは、RubyとJavaScriptを混在して利用するためのファイル形式と勝手に思い込んでいる。(Rubyとhtmlを混在して利用するファイルは.rhtmlというファイル形式になるように。)
今までのAjaxの利用方法...
- ビュー app/views/models/softwares/_edit2.rhtml
- .rhtmlファイルで、更新箇所とアクションを指定する。
<%= link_to_remote '選択', :update => 'select_or_typing',......更新箇所 :url => {:action => 'list_keyword'} %>......アクション
- コントローラー app/controllers/softwares_controller.rb
- コントローラーで、処理内容を指定する。
def list_keyword @text_input = false render :partial => "models/softwares/edit2_keyword"......処理内容 end
.rjsファイルから利用する場合...
- ビュー app/views/models/softwares/_edit2.rhtml
- .rhtmlファイルでは、アクションだけ指定する。
<%= link_to_remote '選択', :url => {:action => 'list_keyword'} %>......アクション
- コントローラー app/controllers/softwares_controller.rb
- コントローラーは、list_keyword.rjsを呼び出すだけ。*1
def list_keyword @text_input = false end
- ビュー app/views/softwares/list_keyword.rjs
- .rjsファイルで、更新箇所と処理内容を指定する。
page.replace_html :select_or_typing, render(:partial => "models/softwares/edit2_keyword")......更新箇所, 処理内容
違いは?
- 今までのAjaxの利用方法では、1回のアクションで1箇所しか、部分更新できなかった。
- .rjsファイルを利用すれば、1回のアクションで複数箇所の部分更新が可能になる。(より複雑な処理に対応できる。)
.rjsファイルを利用してキーワード登録
それでは、実際にrjsを利用して、キーワード登録の処理を修正してみた。
現状では、キーワードを入力する場合のテキストフィールドとプルダウンリストの切り替えに、「選択|新規」の二つのリンクを表示している。さらに無駄の無いインタフェースを考えれば、テキストフィールドの時は「選択」のリンクだけ、プルダウンリストの時は「新規」のリンクだけが表示される方が良い。目標はこんな表示だ。
「新規」をクリックすると...
-
-
- リンク表示が「選択」になる。
- キーワードの入力フォームがテキストフィールドになる。
-
今まで、更新箇所が2箇所になるため実現できなかったが、rjsを利用して以下のようにやってみた。
-
-
- 以下、オレンジ色の部分が追記したコード。緑色の部分はコードの説明。
- 今回、変数@new_keywordを@text_inputに変更したり、id=で指定する名前を変更しているので、前回との比較が分かり難くなってしまった...。
- 最初から分かり易く変数やメソッドなどを命名することは、とても大切なこと。
-
- ビュー app/views/models/softwares/_edit2.rhtml
- 選択または新規のリンクを表示する部分を、パーシャルファイル_edit2_keyword_link.rhtmlを呼び出して表示するようにした。
...(途中省略)... <% unless @controller.class.hidden_field?(@action_name, 'keyword_id') %> <tr> <td class="<%= localized_label_class_on(@software, 'keyword_id') %>" id='select_or_typing_label'>......ビジュアルエフェクトでハイライト処理する部分 <%= human_attribute_name(@software, 'keyword_id') %> <sub id="select_or_typing_link">......選択、または新規のリンクを表示する部分 <%= render :partial=>"models/softwares/edit2_keyword_link" %> </sub> </td> <td id="select_or_typing">......プルダウンリスト、またはテキストフィールドを表示する部分 <%= render :partial=>"models/softwares/edit2_keyword" %> </td> </tr> <% end %>
- ビュー app/views/models/softwares/_edit2_keyword_link.rhtml
- 上記で呼び出されて、選択または新規のリンクを描画するパーシャルファイル。ファイルを新規追加した。
<% if @text_input %>
<%= link_to_remote '選択',
:url => {:action => 'change_keyword_form', :text_input => false} %>
<% else %>
<%= link_to_remote '新規',
:url => {:action => 'change_keyword_form', :text_input => true} %>
<% end %>
- パラメーター:text_inputをセットして、change_keyword_formメソッドを呼び出す。
- ビュー app/views/models/softwares/_edit2_keyword.rhtml
- キーワードの入力フォームを描画する。変更なし。
<% if @text_input %> <%= text_field :keyword, :name, :size => 60 %> <% else %> <%= collection_select :software, :keyword_id, Keyword.find_all, :id, :name, :include_blank => false, :prompt => '選択してください。' %> <% end %>
- コントローラー app/controllers/softwares_controller.rb
- new_keyword、list_keywordメソッドを一つにまとめて、change_keyword_formメソッドにした。
...(途中省略)... protected def create_keyword if params[:keyword] @keyword = Keyword.find(:first, :conditions => ["name LIKE ?", params[:keyword][:name]]) if @keyword == nil form = Software.new(params[:software]) form.keyword_id = 1 @text_input = true @keyword = Keyword.new(params[:keyword]) @keyword.save if form.valid? || !@keyword.valid? end params[:software][:keyword_id] = @keyword.id || @keyword.name end end ...(途中省略)... def change_keyword_form @text_input = params[:text_input]......パラメーターをインスタンス変数にセットして、change_keyword_form.rjsを実行する。 end ...(途中省略)...
- ビュー app/views/softwares/change_keyword_form.rjs
- ファイルを新規追加した。
page.replace_html :select_or_typing_link, render(:partial => "models/softwares/edit2_keyword_label")
page.replace_html :select_or_typing, render(:partial => "models/softwares/edit2_keyword")
page.visual_effect :highlight, 'select_or_typing_label'
page.visual_effect :highlight, 'select_or_typing'
- 選択または新規のリンクと、キーワード入力のフォームを部分更新して、ビジュアルエフェクトのハイライト処理をする。
- pageは、ブラウザが表示している処理対象のページのオブジェクトを示す。
- 「page . 処理するJavaScriptの指定 オプション指定」の書式でコーディングする。
参考リンク
以下のページがとても参考になりました。感謝です。
*1:コントローラーでrenderを指定しない場合、デフォルトでメソッド名と同じlist_keyword.rjsを呼び出す。(もし、list_keyword.rhtmlが存在すれば、それが優先される。)