Rails에서 페이지 전환 없이 부분 업데이트(페이지의 일부를 동적으로 바꾸기)

15417 단어 아약스RailsjQuery

ajax로 서버로부터 데이터를 받고・・・그 후의 묘화는?



얼마 전부터 Rails를 만져 온 분이라면, 프런트 측에서 jquery를 사용되고있는 분도 많다고 생각합니다.
필자도 jquery를 일로 사용하고 있으며, ajax를 사용하여 서버 측에 데이터를 보내고 그 반환 값을 클라이언트 측에 그리는 동작을 자주 사용합니다.

자주 사용하는 것이,
- 서버에서 데이터 수신
- view에 준비하고 있는 요소에 jquery로 셀렉터를 지정해, 값을 넣어 간다
- $('선택자').val(('서버의 반환값'));
- $('셀렉터').html(('서버의 반환값'));

같은 움직임입니다.

이것이 위와 같은 단순한 것이면 좋지만, 예를 들면 「단조를 한 테이블을 그려라」
라든가 「쓸데없이 세련된 낭비가 없는 코드로 복잡한 html을 생성하라」라고 말해진 날에는, 귀찮게 뱉어 버릴 것입니다.

Rails에는 각종 폼 헬퍼 메소드를 시작해, view측에서도 Ruby의 코드를 걸 수 있는 기능이 있습니다만, jquery로↓와 같은 기술을 해도, 당연히 jquery로 Rails의 폼에 루퍼를 해석해 묘화 한다 할 수 없습니다.
//ダメな例。当然Railsのメソッドはjsでは解釈できない
$('#target').html('<%= telephone_field_tag :test,:id,value:"1",id:"id1",class:"form-control" %>')

//やるならこう。
$('#target').html('<input type="tel" name="test" id="id1" value="1" class="form-control">')

모처럼, Rails에는 부분(부품화)이나 폼을 편하게 하거나 반복 처리를 간단하게 걸치기 때문에, 그 이점을 살리면서, jquery+ajax로 동적으로 페이지를 갱신하고 싶다는 것이 이번의 목적 입니다.

즉시 코드를



이번에는 이러한 페이지를 준비하고 텍스트 상자에 넣은 수치를 ajax로 보내면 그 id를 가진 사용자를 페이지 전이 없이 표시하도록 해 보겠습니다.

before
after

Rails 측


#パーシャル(_list.html.erb)
<div>
    <h2>ここからがパーシャルだよ</h2>
    <% if @user_list.present? %>
    <p>部分更新されたので、DBから受け取った人の名前が表示されるよ<p>
        <ul>
            <% @user_list.each do |user| %>
                <li><%= "#{user.name}(#{user.name_kana})" %></li>
            <% end %>
        </ul>
    <!-- 初期では↓が表示され、ajaxで↑を表示する -->
    <% else %>
        <p>初期値だよ。ajaxで部分更新するとユーザーの名前が取れるよ</p>
        <p>ここにユーザーIDを3つ入れて送ってみるとな・・・</p>
        <div class="col-sm-4">
            <%= telephone_field_tag :test,:id,value:"1",id:"id1",class:"form-control" %>
            <%= telephone_field_tag :test,:id,value:"2",id:"id2",class:"form-control" %>
            <%= telephone_field_tag :test,:id,value:"3",id:"id3",class:"form-control" %>
        </div>
        <a href="javascript:void(0)" type="button" id="id_submit" class="btn btn-save"><i class="material-icons">save</i>ajax!</a>
    <% end %>
</div>
#パーシャルを呼び出すview
<h1>ajaxを使ってページ遷移なしでパーシャルを更新しよう!</h1>
    <div id="target">
        <%= render :partial => "list", locals:{user_list: @user_list} %>
    </div>
<%= javascript_pack_tag 'test.js' %>

#ルーター
resources:test do
    collection do
      #ajaxを行うルートの設定
      post 'search'
    end
  end
#コントローラー
class TestController < ApplicationController
  def index
    @user_list = nil
  end

  def search
    #例
    id_list = params[:id_list]
    @user_list = []
    id_list.each do |id|
      @user_list.push(User.find(id))
    end
    #ここが肝!render_to_stringで変数を渡した状態で文字列に変換しちゃおう    
    partial = render_to_string(partial:'list', :locals => { user_list: @user_list })
    puts partial
    render json:{html:partial}
  end
end


↑의 컨트롤러 처리가 중요합니다.

결국, Rails의 헬퍼 메소드로 erb 안에서 Ruby의 each문을 사용하기도 합니다만,
이 메서드에서 반환 값으로 반환되는 것이 ↓와 같은 html 태그입니다.
<!-- Railsで解釈されこのようなhtmlが生成されている -->
<div>
    <h2>ここからがパーシャルだよ</h2>
    <p>部分更新されたので、DBから受け取った人の名前が表示されるよ</p><p>
        </p><ul>
                <li>金沢 均(かなざわ ひとし)</li>
                <li>落合 安未(おちあい やすみ)</li>
                <li>浅野 克之(あさの かつゆき)</li>
        </ul>

</div>

이번에는 Rails의 컨트롤러 측에서 부분을 html 태그로 Rails 측으로 변환하고 그것을 render_to_string에서 문자열 정보로 ajax 통신으로 js 측에 전달하고 있습니다.

js


$(function(){
    $('#id_submit').on('click',function(){
        //テキストボックスの入力値をサーバーへ送る
        var id_list = [$('#id1').val(),$('#id2').val(),$('#id3').val()];
        $.ajax({
            url: '/test/search',
            dataType: 'json',
            type: 'POST',
            data:{
                id_list:id_list
            },
          }).done(function(result) {
            //今呼び出しているパーシャルを消して、受け取ったパーシャルを表示
            $('#target').children().remove();
            $('#target').html(result.html);
          }).fail(function(err){
              console.log(err);
          })
    })
})

그리고 이러한 형태로 Rails의 파셜이나 헬퍼 메소드를 유효하게 활용하면서, jquery로 페이지 천이 없는 움직임을 구현해 보았습니다.

이번은 매우 간단한 예이지만, 정해진 템플릿을 Rails의 기능을 사용해 기술하고 싶을 때에 유용합니다.

물론, 이것으로는 대응할 수 없는 사례나, partial을 만들 때까지 없는 변경등은 별도 대응할 필요가 있습니다.

좋은 웹페이지 즐겨찾기