web-dev-qa-db-fra.com

Rails avis flash via ajax

Pour faire court, j'ai un bouton. En cliquant dessus, je veux qu'une requête ajax soit déclenchée qui obtient flash [: notice] et l'affiche dans un div en $

Voici ma vue raccourcie:

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

 <div id="notice">

 </div>

Ma demande ajax dans la vue:

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

Mon contrôleur:

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

Mon show.js.erb

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

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

Le problème est que lorsque je clique sur le bouton, l'avis s'affiche correctement. Mais le même avis persiste également sur les prochains clics. La recherche partielle contient le tableau Aidez-moi!

Voici un exemple que j'ai réussi à travailler, grâce à la réponse de Rich Peck. Je devais utiliser flash.now pour vous assurer que l'avis flash n'a pas persisté.

Déclencheur AJAX dans la vue:

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

Manette:

# 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

Vue rendue:

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

où l'avis flash est affiché dans la mise en page:

# 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

Sessions

le même avis persiste également lors des prochains clics

Cela est dû au fait que flash est stocké dans la variable session de Rails :

Le flash est une partie spéciale de la session qui est effacée à chaque demande. Cela signifie que les valeurs qui y sont stockées ne seront disponibles que dans la prochaine demande, ce qui est utile pour transmettre des messages d'erreur, etc.

Le problème que vous avez est que puisque je ne pense pas que ajax compte comme une nouvelle demande (besoin d'une référence pour cela), les données persisteront dans la prochaine fois que vous demanderez via HTTP.

-

Correction

Je voudrais d'abord essayer ceci:

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

Le principal problème que vous rencontrez est que vous traitez la variable flash dans votre JS en utilisant le préprocesseur ERB. Il s'agit d'un problème car cela signifie que vous ne pourrez pas utiliser la précompilation d'actifs pour l'aider à fonctionner.

Après avoir regardé cette question , pourquoi ne pas essayer d'utiliser after_filter callback , comme ceci:

#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

-

Mise à jour

Vous devez inclure la fonctionnalité success dans votre show.js.erb:

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

Cela signifie que vous pouvez supprimer la totalité de l'appel ajax du application.js, et remplacez par remote: true pour votre formulaire de recherche:

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

La raison pour laquelle cela fonctionne est que lorsque vous utilisez le format.js bloc de réponse, Rails chargera le [action].js.erb fichier dans vos vues. Étant donné que cela ne se produit que après l'action est terminée, c'est équivalent à la fonction success de votre ajax.

Ce faisant, vous pourrez supprimer la fonction ajax de votre application.js, et remplacez-le par la version UJS, comme décrit ci-dessus

21
Richard Peck