77 Stimmen

Wie behandeln Sie Rail's Flash mit Ajax-Anfragen?

Ich bin ziemlich zufrieden mit die Lösung die ich mir ausgedacht habe. Grundsätzlich habe ich eine Helfer-Methode, die das Flash inline neu lädt, und dann habe ich einen after_filter, der das Flash löschen, wenn die Anforderung xhr ist. Hat jemand eine einfachere Lösung als das?

Aktualisierung: Die obige Lösung wurde in Rails 1.x geschrieben und wird nicht mehr unterstützt.

64voto

gudleik Punkte 2941

Sie können die Flash-Nachrichten auch mit einem after_filter-Block in den Antwort-Headern speichern und sie 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

Und fügen Sie in application.js einen globalen Ajax-Handler hinzu. Für jquery tun etwas wie dieses:

$(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 jGrowl.

29voto

Victor S Punkte 4970

Und hier ist meine Version basierend auf @emzero, mit Änderungen, um mit jQuery zu arbeiten, getestet auf 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();
};

$(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}"

15voto

dbKooper Punkte 1037

Ich habe es so gemacht

Controller :

respond_to do |format|
    flash.now[:notice] = @msg / 'blah blah...'
    format.html 
    format.js
  end

Ansicht:

<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 %>");

15voto

Silviu Postavaru Punkte 1754

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)) %>');

10voto

Vikrant Chaudhary Punkte 10769

Auf anderen aufbauen -

(Wir übergeben das komplette Flash-Objekt als JSON, damit wir das komplette 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 erzeugt 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
}

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X