Tag: Rails/Ajax

目次

関連ページ

参考情報

インクリメンタル検索の実装

フォームとJavaScript

  • ransackを使った検索フォーム
    <!-- 検索フォーム部分 -->     
          <%= search_form_for(@search) do |f| %>
              <%= f.text_field :title_cont, {:placeholder => '検索'} %>
          <% end %>
    
  • JavaScript部分。jQueryを使用して一定時間ごとにイベントを送信する。データの送信にはjQuery Form PluginのajaxSubmitを使う。
    <!-- JavaScript部分 -->     
    <script type="text/javascript">
      // 内容の自動保存処理
      var preFunc = null;
      var preInput = ''
      var input = '';
      var timeoutValue = 10;
    
      ajaxPost = function() {
        $("#book_search").ajaxSubmit({
          url: '/books/',
          type: 'get'
        });
      }
    
      $('#q_title_cont').on('keyup', function () {
        input = $.trim($(this).val());   //前後の不要な空白を削除
        if (preInput !== input) {
          clearTimeout(preFunc);
          preFunc = setTimeout("ajaxPost()", timeoutValue);
        }
        preInput = input;
      });
    
    </script>
    
  • コントローラー。通常検索件Ajaxを処理する場合respond_toでformat.jsを先に書かないとindex.js.erbが呼ばれないかも?
      def index
        @books = @search.result.page(params[:page])
        respond_to do |format|
          format.js {}
          format.html {}
        end
      end
    
  • index.js.erb。もともとのコンテンツを隠し検索結果を表示する。
    $("#main_content").hide();
    $("#booklist_list").show();
    $("#booklist_list").html("<div class='well'><h2>インクリメンタル検索</h2></div><%= escape_javascript(render 'shared/search_book_list') %>");
    

フォームの内容の自動保存する

フォームの入力フィールド

  • class="create-temp"のdivがポイント
    <div class="blog-form">
        <%= form_for(@post) do |f| %>
    
            <%= f.text_field :tilte %>
            <%= f.text_area :body %>
            <!-- for temporal saving -->
            <div class="create-temp"></div>
            <%= f.submit "送信する" %>
    
        <% end %>
    </div>
    

フォームの送信処理部分(JavaScript版)

  • submit用にjQuery Form Pluginを使う。
  • keydownにより何か変更があったら5秒後に送信されることになる。
  • spanのdeta-result属性がtrueでない場合はcreate-tempを、trueの場合はupdateを呼び出すようにする。
    var ready, tempSubmit;

    ready = function() {
        if ($('.create-temp')) {
            window.tempTimer = null;
            return $('.blog-form form').keydown(function() {
                window.clearTimeout(tempTimer);
                return window.tempTimer = window.setTimeout(function() {
                    return tempSubmit();
                }, 5000);
            });
        }
    };

    tempSubmit = function() {
        if ($('.create-temp span').data('result') !== true) {
            return $(".blog-form form").ajaxSubmit({
                url: '/posts/temp',
                type: 'post'
            });
        } else {
            return $(".blog-form form").ajaxSubmit();
        }
    };

    $(document).ready(ready);
    $(document).on('page:load', ready);

routes.rb

  • 上記JavaScriptでPostしているrouteをを作成。
      post '/posts/temp', to: 'posts#create_temp', as: :temp_post
    

コントローラー

  • createは通常の保存処理。create_tempからajaxから呼ばれるメソッド。
      def create
        @post = Post.new(post_params)
    
        if @post.save
          redirect_to(@post)
        else
          render('new')
        end
    
      def create_temp
        @post = Post.new(post_params)
        @post.save
      end
    
    
      def update
        respond_to do |format|
          if @post.update(post_params)
            format.js {}
            format.html {redirect_to @post, notice: 'Post was successfully updated.'}
          else
            format.js {}
            format.html {render :edit}
          end
        end
      end
    

レスポンス用のjs.erb

  • create_temp.js.erbの内容
    var result = <%= @post.valid? %>;
    var msg = "";
    var notice = "";
    
    if (result == true) {
        msg = "下書き保存されました";
    
        // This is for Temporal saving
        // forcing the form to look update method.
    
        // Add id
        $('.blog-form form').prepend('<input name="post[id]" type="hidden" value="<%= @post.id %>">');
    
        // Chnage REST method
        $('.blog-form input[name=_method]').remove();
        $('.blog-form form').prepend('<input name="_method" type="hidden" value="patch">');
    
        // Change URL
        $('.blog-form form').attr('action', '/posts/<%= @post.id %>');
    
    } else {
        msg = "下書き保存のための情報が足りません";
    }
    
    
    // Message
    notice = "<span data-result=" + result + ">" + msg + "</span>";
    $('.create-temp span').remove();
    $('.create-temp').hide().append(notice).fadeIn();
    
    
  • update.js.erbの内容。
    var persisted = <%= @post.persisted? %>;
    var result = <%= @post.valid? %>;
    var msg = "";
    if (result == true) {
        msg = "下書きが更新保存されました";
    } else {
        msg = "下書き更新保存のための情報が足りません";
    }
    // Message
    notice = "<span data-result=" + persisted + ">" + msg + "</span>";
    $('.create-temp span').remove();
    $('.create-temp').hide().append(notice).fadeIn();
    
    

flashメッセージの取り扱い

  • 通常のrequestと取り扱いがことなるためajax_requestで設定したメッセージが2重に表示されたりする場合がある。
  • How do you handle Rail's flash with Ajax requests? - Stack Overflow
  • これを回避するためにApplicationControlerにafter_filterを設定する。
      after_filter :clear_flash
    
      private
      def clear_flash
        flash.discard if request.xhr?
      end
    

トラブルシューティング

js.erbがレンダリングされない

  • 例えばupdateメソッドでupdate.js.erbが実行されない。
  • 以下のようにresponde_toで、「format.js {}」を追加する必要がある。
  • さらにformat.jsが、format.htmlより先にないとだめかも?
      def update
        respond_to do |format|
          if @post.update(post_params)
            format.js {}
            format.html {redirect_to @post, notice: 'Post was successfully updated.'}
          else
            format.js {}
            format.html {render :edit}
          end
        end
      end
    

ActionController::UnknownFormatエラーが発生する

  • コントローラーにビューから呼び出されるメソッドは存在するものの以下の部分でエラーが発生する。
        respond_to do |format|
          format.js { }
        end
    
  • このrespond_to自体がなくても改善しない。原因としてありがちなことはviewで「remote: true」を指定しなかったこと。
  • あるいはJavaScriptを使ってonclickでsubmit()処理を実行しているとうまくいかない。viewがノーマルな設定(submit処理)になっているかどうか確認する。

トップ   編集 凍結 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2016-04-13 (水) 16:47:30