Ich bin ziemlich zufrieden mit der Lösung , die ich gefunden habe. Grundsätzlich habe ich eine Hilfsmethode, die den Flash-Inline neu lädt, und dann habe ich einen after_filter, der den Flash löscht, wenn die Anforderung xhr ist. Hat jemand eine einfachere Lösung als diese?
Update: Die obige Lösung wurde in Rails 1.x zurückgeschrieben und wird nicht mehr unterstützt.
ruby-on-rails
ajax
Jerry Cheung
quelle
quelle
after_filter { flash.discard if request.xhr? }
Antworten:
Sie können die Flash-Nachrichten auch mithilfe eines after_filter-Blocks in den Antwortheadern speichern und mit Javascript anzeigen:
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
Fügen Sie in application.js einen globalen Ajax-Handler hinzu. Für jquery machen Sie so etwas:
$(document).ajaxError(function(event, request) { var msg = request.getResponseHeader('X-Message'); if (msg) alert(msg); });
Ersetzen Sie alert () durch Ihre eigene Javascript-Flash-Funktion oder versuchen Sie es mit jGrowl.
quelle
response.headers['X-Message-Type'] = flash_type
(während flash_type den wichtigsten Typ zurückgibt (Fehler> Erfolg> Hinweis). Außerdem können SieajaxComplete
dann Erfolgsfälle einschließen:$(document).ajaxComplete(function(e, request, opts) { fireFlash(request.getResponseHeader('X-Message'), request.getResponseHeader('X-Message-Type')); });
Und hier ist meine auf @emzero basierende Version mit Änderungen für jQuery, die auf Rails 3.2 getestet wurden
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(); }; $(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 });
Layout: application.html.haml
#flash-message - flash.each do |name, msg| = content_tag :div, msg, :id => "flash_#{name}"
quelle
3.1.0
. Vielen Dank, Victor, hat sofort für mich gearbeitet.[:error, :warning, :notice].each {}
Gibt das Array zurück, wenn die Rückgabebedingung nicht erfüllt ist. Daher muss dieser Code etwas angepasst werden. Andernfalls ist er hilfreich.Dies wird in der js-Antwort benötigt
Wenn Sie RSJ verwenden:
page.replace_html :notice, flash[:notice] flash.discard
Wenn Sie jQuery verwenden:
$("#flash_notice").html(<%=escape_javascript(flash.delete(:notice)) %>');
quelle
flash.discard(:notice)
nichtflash.delete(:notice)
Ich habe es so gemacht ..
Controller :
Aussicht:
<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 %>");
quelle
flash.now[:notice]= @msg / 'blah blah..'
Ich war auch neugierig. Sie würden post.js.erb in den Pfad app / assets / javascripts einfügen, nicht wahr?Auf anderen aufbauen -
(Wir übergeben das vollständige Flash-Objekt als JSON, sodass wir das gesamte Flash-Objekt im Browser rekonstruieren können. Dies kann verwendet werden, um sicherzustellen, dass alle Flash-Nachrichten angezeigt werden, falls mehrere Flash-Nachrichten von Rails generiert werden.)
#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 }
quelle
$.each( $.parseJSON(request.getResponseHeader('X-Flash-Messages')), function(key,value){ flash_message(key,value) });
wenn Sie die js-Funktion haben, um eine Flash-Nachricht mit dem Parametertyp Flash und NachrichtSieht so aus, als ob Sie etwas benötigen
flash.now[:notice]
, das nur in der aktuellen Aktion und nicht in der nächsten verfügbar ist. Sie können sich die Dokumentation hier ansehen: http://api.rubyonrails.com/classes/ActionController/Flash/FlashHash.html#M000327quelle
flash.now
ist eine Lösung für ein anderes Problem. Der Inhalt vonflash.now
wird nicht auf magische Weise durch einen Ajax-Rückruf in die aktuelle Seite eingefügt.Weisen Sie die Nachricht im Controller folgendermaßen zu:
flash.now[:notice] = 'Your message'
app / views / layouts / application.js.erb - Layout für Ajax-Anfragen. Hier können Sie einfach verwenden
<%= yield %> alert('<%= escape_javascript(flash.now[:notice]) %>');
oder mit einigen umfangreichen Animationen mit Gritter: http://boedesign.com/demos/gritter/
<%= yield %> <% if flash.now[:notice] %> $.gritter.add({ title: '--', text: '<%= escape_javascript(flash.now[:notice]) %>' }); <% end %>
quelle
Basierend auf gudleik Antwort:
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
Fügen Sie dann in Ihrer application.js (wenn Sie native Prototyp-Helfer von Rails verwenden) Folgendes hinzu:
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 } });
quelle
return unless request.xhr
? Ich meine am Ende der aktuellen Anfrage, wenn wir Flash-Hinweise hinzugefügt haben, fügen wir sie zu den Antwortheadern hinzu, dann lesen wir sie in js - cool, aber ich bin nicht genau sicher, warum wir die obige Zeile habenEs gibt ein Juwel namens Unobtrusive Flash , das Flash-Nachrichten automatisch in ein Cookie codiert. Ein Javascript auf Client-Seite sucht nach Flash und zeigt es an, wie Sie möchten. Dies funktioniert nahtlos sowohl bei normalen als auch bei Ajax-Anfragen.
quelle
Ich habe die Antwort von Victor S geändert, um einige Fälle zu beheben, in denen
flash[type].blank?
nicht funktioniert hat, wie von wenigen Personen in den Kommentaren angegeben.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
Dann ist die Ruhe gleich
// 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 });
quelle
Hier ist meine Version (Arbeiten mit mehreren Flash-Hinweisen und UTF-8-Codierung für Sonderzeichen):
Innerhalb von 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
In meinem Kaffeeskript (Twitter Bootstrap Version):
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>")
quelle
Eine andere Möglichkeit wäre, das Div "Notice" mit der Nachricht vom "OnFailure" -Handler Ihrer Ajax-Anfragen zu aktualisieren / anzuzeigen. Sie haben die Möglichkeit, diese Flash-Meldungen mit der erforderlichen Wirkung anzuzeigen. Ich habe das benutzt
im Javascript
HTH
quelle
Ich baue eine Engine, die ein gewisses Verhalten an den application_controller enthält, um die Flash-Nachricht im Antwortheader zu senden, wie einige von euch vorschlagen.
https://github.com/bonzofenix/flajax
quelle
Die einzige Verbesserung, die ich mir vorstellen kann, besteht darin, die Seite.reload_flash als Standard festzulegen (sie muss nicht in jede rjs-Datei eingefügt werden und expizitiert werden, wenn Sie den Flash nicht neu laden möchten, z. B. page.keep_flash.
Ich würde nicht wissen, wo ich anfangen soll, aber ich bin mir sicher, dass es nicht so schwer ist, einige Schienen zu kennen.
quelle
Wenn Sie AJAX-Aufrufe verwenden möchten, sollte redirect_to nicht in der Steuerung verwendet werden. Flash-Nachrichten sollten vielmehr explizit bezeichnet werden:
In your_controller:
respond_to :js def your_ajax_method flash[:notice] = 'Your message!' end
In der Ansicht, die von your_ajax_method_in_the_controller benannt wird
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); })
Bitte beachten Sie, dass die Nachrichtenklasse ein Ankerpunkt zum Rendern von Nachrichten ist. Diese Klasse sollte in Ihrer Ansicht oder Ihrem Anwendungslayout vorhanden sein. Wenn Sie ERB verwenden, wird die Linie
$('.messages').html("<%= j(render 'layouts/messages') %>");
Das oben in HAML / ERB eingebettete JavaScript ist der Schlüssel zum Anzeigen von Flash-Nachrichten bei Verwendung von AJAX. Alle anderen Komponenten bleiben für Nicht-AJAX-Aufrufe gleich.
Sie können
your_ajax_method_in_the_controller.js.coffee
.js verwenden oder einfach, aber dann sind die Rails-Variablen für JS / Coffee nicht verfügbar. Obwohl ich hier keine Variablen verwende, ziehe ich es vor, JS in HAML zu verpacken, um eine konsistente Codebasis zu erhalten.Ich nutze Twitter Bootstrap zum Stylen von Nachrichten, um
$(".alert").alert('close')
den Hinweis auszublenden. Und hier sind die Nachrichten teilweise:Layouts / _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}"
Nur für den Fall, CSS für die Warnungen ist unten
.alert-messages { position: fixed; top: 37px; left: 30%; right: 30%; z-index: 7000; }
quelle