web-dev-qa-db-ja.com

Rails ajaxによるフラッシュ通知

要するに、ボタンがあります。クリックすると、flash [:notice]を取得してdiv in $に表示するajaxリクエストをトリガーしたい

これが私の短縮ビューです。

 <input type="button" id="search" value="display"/>

 <div id="notice">

 </div>

ビューでの私のajaxリクエスト:

$("#search").submit(function(){
                            $.ajax({
                                type: "POST",
                                url: //url to my show action
                                success: function(data){
                                      /*$("#notice").html("<%= flash[:notice] %>");
                                        $("#content").html(data);*/
                                }
                            });
                            return false;
                    });

私のコントローラー:

def HomeController <  ActionController::Base
  def index

  end

  def show
    respond_to do |format|
    format.js {  flash[:notice] = "" + count.to_s + " results found for " + params[:query][:search_key] + "" }
    end
    #render :partial => 'search'
  end
end

私のshow.js.erb

#app/views/dashboard_home/show.js.erb
$("#notice").html("<%=j flash[:notice] %>");

$("#content").html("<%=j render partial: "search" %>");

問題は、ボタンをクリックすると通知が正常に表示されることです。ただし、次のクリックでも同じ通知が持続します。検索パーシャルにはテーブルが含まれています

Rich Peckの回答のおかげで、ここに私が働いた例があります。 flash.nowを使用して、フラッシュ通知が持続しないことを確認する必要がありました。

ビュー内のAJAXトリガー:

<%= link_to "Email report", users_path, remote: true %>

コントローラ:

# app/controllers/users_controller
class UsersController < ApplicationController

  def index
    # do some things here

    respond_to do |format|
      format.js { flash.now[:notice] = "Here is my flash notice" }
    end
  end
end

レンダリングビュー:

# app/views/users/index.js.erb
$("#flash").html('<%= j render partial: "shared/notice_banner" %>');

フラッシュ通知がレイアウトに表示される場所:

# app/views/layouts/application.html.erb
<div id="flash">
  <% if notice.present? %>
    <%= render partial: "shared/notice_banner" %>
  <% end %>
</div>


# app/views/shared/_notice_banner.html.erb
<div data-alert class="alert-box">
  <%= notice %>
  <a href="#" class="close">&times;</a>
</div>
24
littleforest

セッション

同じ通知は次のクリックでも持続します

これは、flashRailsのsession変数に格納されている であるために発生します。

フラッシュは、各リクエストでクリアされるセッションの特別な部分です。これは、そこに格納された値が次のリクエストでのみ利用できることを意味し、エラーメッセージなどを渡すのに役立ちます。

あなたが持っている問題は、ajaxが新しいリクエストとしてカウントされるとは思わないため(このための参照が必要)、データは次回HTTP経由でリクエストするときに持続することです。

-

修正

私は最初にこれを試してみました:

def show
    respond_to do |format|
        format.js {  flash[:notice] = "my secret number "+Rand(0,5)+" !" }
    end
end

主な問題は、flashプリプロセッサを使用してJSでERB変数を処理していることです。これは、アセットのプリコンパイルを使用して機能させることができないことを意味するため、問題です。

この質問 を見てから、次のように after_filterコールバック を使用してみてください。

#app/controllers/home_controller.rb
Class Home < ActionController::Base
   after_filter { flash.discard if request.xhr? }, only: :show

    def show
        respond_to do |format|
            format.js {  flash[:notice] = "my secret number "+Rand(0,5)+" !" }
        end
    end
end

-

更新

show.js.erbsuccess機能を含める必要があります。

#app/views/home/show.js.erb
$("#notice").html("<%= flash[:notice] %>");

つまり、application.jsからajax呼び出し全体を削除し、検索フォームのremote: trueに置き換えることができます。

#app/views/search/index.html.erb
<%= form_tag home_show_path, remote: true %>

これが機能する理由は、format.js応答ブロックを使用すると、Railsがビューに[action].js.erbファイルをロードします。これのみを考慮するとアクションが完了した後、これはajaxのsuccess関数と同等です。

これにより、application.jsからajax関数全体を削除し、上記のようにUJSバージョンに置き換えることができます。

21
Richard Peck