Flash Messages and Toasts with Hotwire & Turbo.js Discussion
Nice! I've been playing with Turbo and that comes on perfect timing, thanks!
But didn't you think that feels wrong?
We used to have the controller do all of that for us with the redirects and flashes.
I think this is a missing piece of Turbo. It has to work as seamlessly as it is without it.
I'm not following. If you're making realtime updates on the page without refreshing, you're going to want the same for flash and toasts.
Sorry for not being clear.
I mean having to create a template for turbo_stream to do flashes and such.
It's rjs with new clothes.
I think that ideally, turbo should work with the same flow that we have with "normal" Rails.
You can avoid that turbo_stream template by putting everything in the controller, like this:
respond_to do |format|
format.html { redirect_to tweets_path, notice: "Your tweet was successfully created." }
format.json { render :show, status: :created, location: @tweet }
format.turbo_stream { render turbo_stream: turbo_stream.prepend('tweets', partial: 'tweets/tweet', locals: { tweet: @tweet })}
end
But I personally liked a lot this approach of adding a proper template for the turbo_stream response.
Thanks a lot for this video, Chris!
It work with the current flow, in your controller you can have
def create
if @model.save
redirect_to list_path, 'Model created successfully'
else
render :new, status: :unprocessable_entity
end
end
and on application.html.erb
have the same approach for toats using flash
variables.
it will trigger the connect on stimulus controller and display the toast.
The approach showed on the video is more when you have complex pages and not only a regular CRUD.
having the ability to create reactive apps using this approach looks awesome.
So the format that Chris shows is what's encouraged by DHH, check here:
I'm trying to add a toast after running a background job, i.e., the type and content of the toast depends on wether or not a certain service object called in the BG job is successful or not.
I can render the toasts correctly when I stream from a turbo_stream controller format response, but if I try to stream from the Job with Turbo::StreamsChannel.broadcast_append_to 'toasts' ...
it doesn't have any error and in the logs I can see the partial was rendered but it never gets delivered to the UI.
Any ideas on how to do this?
There may be two reasons for this.
- Setup your own show, hide with a timeout in stimulus.
- Stimulus isn't setup. Follow these instructions to set it up: https://stimulus.hotwired.dev/handbook/installing
One cool thing is we also could use layouts. It is possible to create a layout app/views/layouts/application.turbo_stream.erb
and manage the code related to flash messages once for all turbo stream response. (Don't forget to use yield
😅)
<%= turbo_stream.prepend :flashes partial: "shared/flashes" %>
<%= yield %>
Great video, Chris. Just yesterday I was doing something to display flashes in a Turbo response and had to use Stimulus to handle some final touches.
As Alex Takitani said, having a create.turbo_stream.erb
feels like old create.js.erb
which I never liked. Feels very ugly (to me) but I can see it's utility in a big page with lots of Turbo Streams.
So far, I'd prefer to render the turbo_stream in the controller action. Either way this video is very useful to understand this part of using Hotwire.
Thanks for sharing the link, Shavin. I guess it's good to know both options. Using the template file can be left for larger streams so that the controller doesn't look to polluted.
It is, but DHH recommends using the template file, and personally I like this method myself because you don't have to look at two places in different instances!
Thanks for the video - by following the example I ran in a problem with the form replacement. This only works once. I cloned this repo and the same problem occurs. After submitting the second Tweet the submit button greys out and becomes disabled.
Anybody with the same experience and a solution?
I had a similar issue, it happened for me when the element I target to replace is outside the partial I was replacing
eg:
# _some_partial.html.erb
<a href="..."></a>
# other_html.html.erb
<div id="turbo-target">
<%= render 'some_partial' %>
</div>
If you use turbo_stream to replace turbo-target
with your partial it will be the div turbo-target
to dissapear from dom and when trying second time it does not works.
My flash partial renders in the terminal, but there's no content or message. Not sure what is going on. I am not re-directing after create, so do I need to use flash.now somehow?
Nice Video. Did you know how I can implement like notification, and call to multiple controller instead of every controller? thanks
I guess, I keep coming back to the idea of convention and whether it is preferable to set this up in a template and controller or to rely on the rails magic and do this in the model as is suggested in your other video (https://gorails.com/episodes/hotwire-rails). When does it go in a template vs. the model? Is it possible to update multiple turbo-frames if you make these calls from the model?
Hi Chris, I added the toast but seems not working:
connect() {
this.element.toast("show")
}
or trying to do this:
connect() {
$(this.element).toast("show")
}
based on your example the last one. but the toast not define. using bootstrap 5.
Uncaught ReferenceError: toast is not defined
here's is my toast:
seems not showing when refreshing. thanks in advance
Did you import it?:
import { Dropdown, Modal, Tabs, Popover, Toggle, Slideover, Alert } from "tailwindcss-stimulus-components"
application.register('alert', Alert)
Great Video. While implementing toast solution with Hotwire / rails 6.1, I am facing an issue.
after some create / destroy actions I am using redirect_to in my controller to go back on the index page.
So not using xxxxx.turbo_stream.erb template.
How can I append a toast in this situation ? (this scheme is working with notice:xxxx and standard notification process).
^ Second this, trying to display a toast notification after calling a create/destroy action which redirects to the index page, if anyone has a way of doing this please share, thanks