I have <%= simple_form_for @offer, remote: true %>
with Turbolinks enabled. I'm trying to redirect and show success flash with something like this in my update
action:
respond_to do |format|
if @offer.update(offer_params)
flash[:success] = "#{@offer.name} #{t(:updated)}"
format.html { redirect_to seller_offers_path }
format.js
else
format.html { render :edit }
end
end
My update.js.erb
has code not related to redirect or flash:
$(".ibox-content.actions").removeClass('sk-loading');
$('.sk-spinner').css("display", "none");
In application.html.erb I can render flash with this:
<div class="row">
<% flash.each do |message_type, message| %>
<%= content_tag(:div, content_tag(:strong, message), id: "flash_message",
class: "text-bold alert alert-#{message_type}") %>
<% end %>
</div>
At the moment my form is saved, however no redirect.
When I add Turbolinks.visit(<%= seller_offers_path %>)
in update.js.erb
form is saved, redirect is done, however there is no flash.
Is there a way I can have flash shown on redirected page with Turbolinks and remote: true
, please? So far I've tried this suggestion, however it works only for showing flash on same page - it doesn't work with redirect_to
.
Update
This does redirect, however no flash:
respond_to do |format|
if @offer.update(offer_params)
format.js { redirect_to seller_offers_path, success: "#{@offer.name} #{t(:updated)}" }
else
format.html { render :edit }
end
end
Update 2
At the moment I'm trying to implement something like
Turbolinks.visit(url, { keep: 'flash' });
as mentioned in docs, however doesn't seem to be working with Turbolinks 5.2
Update 3
I've removerd update.js.erb
and in my controller I have
def update
if @offer.update(offer_params)
flash[:success] = "#{@offer.name} #{t(:updated)}"
redirect_to seller_offers_path
else
render :edit
end
end
Redirect is done as expected, however still no flash displayed on index
. I can print my flash at the end of update
action:
#<ActionDispatch::Flash::FlashHash:0x00007f180d2a1c60 @discard=#<Set: {}>, @flashes={"success"=>"My offer updated!"}, @now=nil>
however at the end of index
action (where I redirect_to) it is empty:
#<ActionDispatch::Flash::FlashHash:0x00007f180eb3b780 @discard=#<Set: {}>, @flashes={}, @now=nil>
Looks like my flash is not kept for next request. Is it because of Turbolinks, or other some reason? I'd be happy for any hint.
When you use forms that submit via JS (e.g. remote: true
or the default form_with
), Rails will lookup and render the conventional js
response (in this case offers/update.js.erb
) and ignore any others, such as the html
redirect.
Your original update.js.erb
did not include any code to perform the visit to the redirect location, and so it only removed the class name and hid the spinner.
As you've figured out, the js
response needs to make a Turbolinks visit
to the redirect location. It's also a good idea to clear the Turbolinks cache after a form submission, so your update.js.erb
might look something like:
$(".ibox-content.actions").removeClass('sk-loading');
$('.sk-spinner').css("display", "none");
Turbolinks.clearCache();
Turbolinks.visit(<%= seller_offers_path %>);
If you have the turbolinks-rails gem installed, and do not need to run any custom JS, like the first two lines above, then in your controller you can simply do:
def update
if @offer.update(offer_params)
flash[:success] = "#{@offer.name} #{t(:updated)}"
redirect_to seller_offers_path
else
render :edit # see note below*
end
You won't need update.js.erb
; turbolinks-rails will automatically clear the cache and visit the redirect path. This is nice as it keeps your controller code tidy (no need for respond_to
), and works for both HTML and JS requests.
* It's worth noting that error responses from JS requests will still need to be handled manually. To do this, you may find this comment useful: https://github.com/turbolinks/turbolinks/issues/85#issuecomment-338784510
I think the reason why your flash isn't showing in your updated code is because you are using the shorthand style of setting flash messages in redirect_to, which only supports
noticeand
alert`:
redirect_to seller_offers_path, notice: '…' # sets flash[:notice]
redirect_to seller_offers_path, alert: '…' # sets flash[:slert]
redirect_to seller_offers_path, success: '…' # doesn't work
If you wish to use your own flash key you'll need to set the flash explicitly:
flash[:success] = "#{@offer.name} #{t(:updated)}"
I should also add that the Turbolinks keep
option is not supported in Turbolinks 5. I think it was a feature in Turbolinks 2 or 3. The Turbolinks README is the place for the most up-to-date docs.
I hope that helps :)