Ask A Question

Notifications

You’re not receiving notifications from this thread.

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.

Reply

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.

Reply

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.

Reply

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!

Reply

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.

Reply

So the format that Chris shows is what's encouraged by DHH, check here:

https://github.com/hotwired/turbo-rails/issues/77

Reply

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?

Reply

There may be two reasons for this.

  1. Setup your own show, hide with a timeout in stimulus.
  2. Stimulus isn't setup. Follow these instructions to set it up: https://stimulus.hotwired.dev/handbook/installing
Reply

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 %>
Reply

Thanks for the tip c:

Reply

Wow!!!!! This really works!!! Thanks!

Reply

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.

Reply
Reply

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.

Reply

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!

Reply

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?

Reply

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.

Reply

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?

Reply

Nice Video. Did you know how I can implement like notification, and call to multiple controller instead of every controller? thanks

Reply

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?

Reply

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:

Bootstrap 11 mins ago
Hello, world! This is a toast message.

seems not showing when refreshing. thanks in advance

Reply

Did you import it?:

import { Dropdown, Modal, Tabs, Popover, Toggle, Slideover, Alert } from "tailwindcss-stimulus-components"
application.register('alert', Alert)

Reply

@dan thank you. I forgot that one. I used to use the import of bootstrap. thanks again.

Reply

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).

Reply

^ 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

Reply

Just posting for those trying to use Bootstrap 5. Your connect function will work after you import Bootstrap and will look like so. Hope this helps:

new bootstrap.Toast(this.element).show();
Reply
Join the discussion
Create an account Log in

Want to stay up-to-date with Ruby on Rails?

Join 85,972+ developers who get early access to new tutorials, screencasts, articles, and more.

    We care about the protection of your data. Read our Privacy Policy.