Je suis assez content de la solution que j'ai proposée . En gros, j'ai une méthode d'assistance qui recharge le flash en ligne, puis un filtre after_filter qui efface le flash si la demande est xhr. Est-ce que quelqu'un a une solution plus simple que celle?
Réponses
Trop de publicités?Vous pouvez également stocker les messages flash dans les en-têtes de réponse à l'aide d'un bloc after_filter et les afficher à l'aide de javascript:
class ApplicationController < ActionController::Base
after_filter :flash_to_headers
def flash_to_headers
return unless request.xhr?
response.headers['X-Message'] = flash[:error] unless flash[:error].blank?
# repeat for other flash types...
flash.discard # don't want the flash to appear when you reload page
end
Et dans application.js, ajoutez un gestionnaire ajax global. Pour jQuery faire quelque chose comme ça:
$(document).ajaxError(function(event, request) {
var msg = request.getResponseHeader('X-Message');
if (msg) alert(msg);
});
Remplacez alert () par votre propre fonction flash javascript ou essayez jGrowl.
Et voici ma version basée sur @emzero, avec des modifications pour fonctionner avec jQuery, testée sur Rails 3.2
application_controller.rb
class ApplicationController < ActionController::Base
protect_from_forgery
after_filter :flash_to_headers
def flash_to_headers
return unless request.xhr?
response.headers['X-Message'] = flash_message
response.headers["X-Message-Type"] = flash_type.to_s
flash.discard # don't want the flash to appear when you reload page
end
private
def flash_message
[:error, :warning, :notice].each do |type|
return flash[type] unless flash[type].blank?
end
end
def flash_type
[:error, :warning, :notice].each do |type|
return type unless flash[type].blank?
end
end
end
application.js
// FLASH NOTICE ANIMATION
var fade_flash = function() {
$("#flash_notice").delay(5000).fadeOut("slow");
$("#flash_alert").delay(5000).fadeOut("slow");
$("#flash_error").delay(5000).fadeOut("slow");
};
fade_flash();
var show_ajax_message = function(msg, type) {
$("#flash-message").html('<div id="flash_'+type+'">'+msg+'</div>');
fade_flash();
};
$("#flash-message").ajaxComplete(function(event, request) {
var msg = request.getResponseHeader('X-Message');
var type = request.getResponseHeader('X-Message-Type');
show_ajax_message(msg, type); //use whatever popup, notification or whatever plugin you want
});
layout: application.html.haml
#flash-message
- flash.each do |name, msg|
= content_tag :div, msg, :id => "flash_#{name}"
Je l'ai fait de cette façon ..
contrôleur :
respond_to do |format| flash.now[:notice] = @msg / 'blah blah...' format.html format.js end
vue:
<div id='notice'>
<%= render :partial => 'layouts/flash' , :locals => { :flash => flash } %>
</div>
layouts / _flash.html.erb
<% flash.each do |name, msg| %>
<div class="alert-message info">
<a class="close dismiss" href="#">x</a>
<p><%= msg %></p>
</div>
<% end %>
post.js.erb
$("#notice").html("<%= escape_javascript(render :partial => 'layouts/flash' , :locals => { :flash => flash }).html_safe %>");
Construire sur d'autres -
(Nous transmettons l'objet flash complet en tant que JSON, ce qui nous permet de reconstruire l'objet flash complet dans le navigateur. Cela peut être utilisé pour garantir que tous les messages flash sont affichés au cas où plusieurs messages flash seraient générés par Rails.)
#application_controller.rb
class ApplicationController < ActionController::Base
after_filter :flash_to_headers
def flash_to_headers
if request.xhr?
#avoiding XSS injections via flash
flash_json = Hash[flash.map{|k,v| [k,ERB::Util.h(v)] }].to_json
response.headers['X-Flash-Messages'] = flash_json
flash.discard
end
end
end
//application.js
$(document).ajaxComplete(function(event, request){
var flash = $.parseJSON(request.getResponseHeader('X-Flash-Messages'));
if(!flash) return;
if(flash.notice) { /* code to display the 'notice' flash */ $('.flash.notice').html(flash.notice); }
if(flash.error) { /* code to display the 'error' flash */ alert(flash.error); }
//so forth
}