我很满意我提出的the solution。基本上,我有一个帮助方法重新加载闪存内联,然后我有一个after_filter,如果请求是xhr清除闪存。有人有比这更简单的解决方案吗?
更新:上述解决方案已在Rails 1.x中回写,不再受支持。
答案 0 :(得分:62)
您还可以使用after_filter块将Flash消息存储在响应标头中,并使用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
在application.js中添加一个全局的ajax处理程序。对于jquery做这样的事情:
$(document).ajaxError(function(event, request) {
var msg = request.getResponseHeader('X-Message');
if (msg) alert(msg);
});
将alert()替换为您自己的javascript flash函数或尝试使用jGrowl。
答案 1 :(得分:29)
这是我的基于@emzero的版本,修改了jQuery,在Rails 3.2上测试
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
// 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();
};
$(document).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
});
#flash-message
- flash.each do |name, msg|
= content_tag :div, msg, :id => "flash_#{name}"
答案 2 :(得分:15)
这在js响应中是必需的
如果您使用的是RSJ:
page.replace_html :notice, flash[:notice]
flash.discard
如果您使用的是jQuery:
$("#flash_notice").html(<%=escape_javascript(flash.delete(:notice)) %>');
答案 3 :(得分:14)
我是这样做的..
<强>控制器强>:
respond_to do |format| flash.now[:notice] = @msg / 'blah blah...' format.html format.js end
查看:强>
<div id='notice'>
<%= render :partial => 'layouts/flash' , :locals => { :flash => flash } %>
</div>
<强>布局/ _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 %>");
答案 4 :(得分:9)
建立在其他人之上 -
(我们将完整的flash对象作为JSON传递,使我们能够在浏览器中重建完整的flash对象。这可以用来确保在Rails生成多个flash消息的情况下显示所有flash消息。)
#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
}
答案 5 :(得分:6)
看起来你需要的是flash.now[:notice]
,它只在当前操作中可用,而在下一个操作中不可用。您可以在此处查看文档:{{3}}
答案 6 :(得分:5)
在控制器中分配消息,如下所示:
flash.now[:notice] = 'Your message'
app / views / layouts / application.js.erb - Ajax请求的布局。 在这里你可以简单地使用
<%= yield %>
alert('<%= escape_javascript(flash.now[:notice]) %>');
或使用gritter的一些丰富动画:http://boedesign.com/demos/gritter/
<%= yield %>
<% if flash.now[:notice] %>
$.gritter.add({
title: '--',
text: '<%= escape_javascript(flash.now[:notice]) %>'
});
<% end %>
答案 7 :(得分:3)
基于gudleik回答:
class ApplicationController < ActionController::Base
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
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
然后在你的application.js上(如果你使用的是Rails原生Prototype助手)添加:
Ajax.Responders.register({
onComplete: function(event, request) {
var msg = request.getResponseHeader('X-Message');
var type = request.getResponseHeader('X-Message-Type');
showAjaxMessage(msg, type); //use whatever popup, notification or whatever plugin you want
}
});
答案 8 :(得分:3)
有一个名为Unobtrusive Flash的gem可以自动将Flash消息编码为cookie。客户端的javascript检查闪存并以您想要的任何方式显示它。这在普通和ajax请求中无缝地工作。
答案 9 :(得分:3)
我修改了Victor S的答案,以修复flash[type].blank?
无法正常工作的一些案例,正如评论中很少有人所指出的那样。
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, nil].each do |type|
return "" if type.nil?
return flash[type] unless flash[type].blank?
end
end
def flash_type
[:error, :warning, :notice, nil].each do |type|
return "" if type.nil?
return type unless flash[type].blank?
end
end
然后休息是一样的
// 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");
};
var show_ajax_message = function(msg, type) {
$(".flash_message").html('<div class="flash_'+type+'">'+msg+'</div>');
fade_flash();
};
$( document ).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
});
答案 10 :(得分:3)
这是我的版本(使用多重闪存通知和特殊字符UTF-8编码):
Inside ApplicationController:
after_filter :flash_to_headers
def flash_to_headers
return unless request.xhr?
[:error, :warning, :notice].each do |type|
if flash[type]
response.headers["X-Ajax-#{type.to_s.humanize}"] = flash[type]
end
end
flash.discard
end
在我的咖啡脚本(twitter bootstrap版本)中:
css_class = {
Notice: 'success',
Warning: 'warning',
Error: 'error'
}
$(document).ajaxComplete (event, request) ->
for type in ["Notice", "Warning", "Error"]
msg = request.getResponseHeader("X-Ajax-#{type}")
if msg?
$('#notices').append("<div class=\"alert #{css_class[type]}\">#{decodeURIComponent(escape(msg))}</div>")
答案 11 :(得分:1)
另一种方法是使用来自Ajax请求“OnFailure”处理程序的消息更新/显示“notice”div。它使您能够显示具有所需效果的这些Flash消息。我用过这个
render :text => "Some error happened", :status => 444
在Javascript中
new AjaxRequest(... , OnFailure:function(transport) { $("#notice").update(transport.responseText); // show the message } );
HTH
答案 12 :(得分:1)
我构建了一个引擎,其中包含一些application_controller的行为,以便像你们中的一些人提议的那样在响应头中发送flash消息。
答案 13 :(得分:0)
我能想到的唯一改进是使page.reload_flash默认(不必将其放在每个rjs文件上,如果你不想重新加载flash,请将其设为expicit,如page.keep_flash。< / p>
我不知道从哪里开始,但知道一些导轨我确信它并不那么难。
答案 14 :(得分:0)
如果您想使用AJAX调用,则不应在控制器中使用redirect_to。相反,应明确表示flash消息:
在your_controller中:
respond_to :js
def your_ajax_method
flash[:notice] = 'Your message!'
end
在your_ajax_method_in_the_controller命名的视图中
<强> your_ajax_method_in_the_controller.js.haml 强>
:plain
$("form[data-remote]")
.on("ajax:success", function(e, data, status, xhr) {
$('.messages').html("#{escape_javascript(render 'layouts/messages')}");
setTimeout(function(){ $(".alert").alert('close') }, 5000);
})
请注意,消息类是呈现消息的锚点。此类应存在于视图或应用程序布局中。如果您使用ERB,则该行变为$('.messages').html("<%= j(render 'layouts/messages') %>");
嵌入HAML / ERB的上述JavaScript是使用AJAX时显示flash消息的关键。对于非AJAX调用,所有其他组件保持不变。
您可以使用your_ajax_method_in_the_controller.js.coffee
或普通.js,但JS / Coffee将无法使用rails变量。即使我不在这里使用变量,我更喜欢在HAML中包装JS以保持一致的代码库。
我利用Twitter Bootstrap来设置消息样式,因此$(".alert").alert('close')
消除了通知。这是消息部分:
<强>布局/ _messages.html.haml 强>
- flash.each do |name, msg|
- if msg.is_a?(String)
.alert-messages
%div{class: "alert alert-#{name == :notice ? "success" : "error"} fade in"}
%a.close{"data-dismiss" => "alert"}
%i.icon-remove-circle
= content_tag :div, msg, id: "flash_#{name}"
以防万一,警报的CSS低于
.alert-messages {
position: fixed;
top: 37px;
left: 30%;
right: 30%;
z-index: 7000;
}