75 votes

Comment gérez-vous le flash de Rail avec les demandes Ajax?

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?

63voto

gudleik Points 1791

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.

29voto

Victor S Points 1615

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

15voto

Silviu Postavaru Points 973

Ceci est nécessaire dans la réponse de js

Si vous utilisez RSJ:

 page.replace_html :notice, flash[:notice]
flash.discard
 

Si vous utilisez jQuery:

 $("#flash_notice").html(<%=escape_javascript(flash.delete(:notice)) %>');
 

15voto

dbKooper Points 682

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

10voto

Vikrant Chaudhary Points 4306

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
}
 

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X