Monday, May 20, 2024
150
rated 0 times [  157] [ 7]  / answers: 1 / hits: 20988  / 11 Years ago, thu, january 9, 2014, 12:00:00

I'm writing a rails 4.0.2 app, and am trying to get a Flash notice to display in my view after an AJAX event.



In my view I display a calendar with days a user can click on. When they do so, I fire an AJAX event via an onclick event handler which updates my model, either adding or removing a record. After firing the event, I complete a page refresh in order to display the updated results.



I found I had to do a page refresh during the JS click event in order to get the view to update properly. A redirect or render in the controller alone wasn't enough.



So, to that effect, I have set a Flash notice in my controller...



def set_conflicts
@conflict = @member.conflicts.for_date(params[:date]).first

if @conflict
@conflict.destroy
else
conflict_date = Date.parse(params[:date])
unless Conflict.create(
month: conflict_date.month,
day: conflict_date.day,
year: conflict_date.year,
member: @member
)
flash[:alert] = 'Oops, there was a problem updating conflicts'
end
end
flash[:notice] = 'This is a test!'
redirect_to manage_member_conflicts_path(@member)
end


... and have included the following flash display logic in my application.haml...



...
%body
= p flash.inspect
- flash.each do |type, message|
= content_tag(:div, message, :class => flash-#{type})

= render 'devise/menu/login_items'
= yield


Note: I use HAML instead of ERB in my views



Yet, no matter what I try, the Flash message does not display. Everything else works as expected except the flash message, and I haven't been able to figure out why.



I suspect it's got something to do with the AJAX refresh I'm doing combined with the redirect (and maybe even turbolinks) but I've looked through other answers here on SO and simply can't get it to work. Clearly, I'm missing something.



Here's the JS click handler (it's pretty simple):



window.calendarClick = (eventDate, linkURL) ->
event = $(document.getElementById(eventDate))
event.toggleClass('selected')

# Set or Remove conflicts
$.ajax
url: linkURL
data:
date: eventDate

# Refresh the page
$.ajax
url: '',
context: document.body,
success: (s,x) ->
$(this).html(s)

More From » ruby-on-rails

 Answers
10

Firstly, thanks for comprehensive question



Here is an equally comprehensive answer: How do you handle Rail's flash with Ajax requests?






Ajax



I'd seriously look at your Ajax refresh process. Refreshing the whole page is super inefficient, and I think covering a deeper issue



Why don't you try using a .js.erb file in the views folder, to handle JS directly by the method:



def set_conflicts
@conflict = @member.conflicts.for_date(params[:date]).first

if @conflict
@conflict.destroy
else
conflict_date = Date.parse(params[:date])
unless Conflict.create(
month: conflict_date.month,
day: conflict_date.day,
year: conflict_date.year,
member: @member
)
flash[:alert] = 'Oops, there was a problem updating conflicts'
end
end
flash[:notice] = 'This is a test!'

respond_to do |format|
format.html { redirect_to manage_member_conflicts_path(@member) }
format.js
end
end

#app/views/controller/set_conflicts.js.erb
$(#your_element).html(<%=j render manage_member_conflicts_path(@member) ) %>);





Response



Although I don't know this for sure, I know the Flash objects are handled by ActionDispatch::Flash middleware. I believe this is not handled for XHR in the same way as standard HTTP requests, consequently preventing Flash from being shown in your response



This means you'll have to do something to pass the Flash object through your Ajax request. And according to the question I posted at the top of this answer, you can use the response headers to do it:



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

$(document).ajaxError(function(event, request) {
var msg = request.getResponseHeader('X-Message');
if (msg) alert(msg);
});

[#73276] Wednesday, January 8, 2014, 11 Years  [reply] [flag answer]
Only authorized users can answer the question. Please sign in first, or register a free account.
dylondaytond

Total Points: 92
Total Questions: 88
Total Answers: 96

Location: China
Member since Fri, Jan 15, 2021
3 Years ago
dylondaytond questions
Tue, Jun 22, 21, 00:00, 3 Years ago
Thu, May 7, 20, 00:00, 4 Years ago
;