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">×</a>
</div>
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