Improving Flash/Toast Messages
The video begins by addressing persistent flash messages that require a page refresh to disappear. The goal is to implement auto-closing behavior and support multiple simultaneous messages for better UX.
Integrating Datastar Locally
Instead of using a CDN, Datastar (v1 RC6) is downloaded and hosted locally for better control and performance. The script is added to the base layout so it loads across all views.
Configuring Auto-Close with Signals
A unique signal is created for each flash message using data-signals. A countdown value is initialized and decreased every second using data-on-interval, enabling automatic removal after five seconds.
Generating Safe Unique IDs with XID
UUIDs caused syntax issues due to dashes, so the Go library :contentReference[oaicite:0]{index=0} repository for XID is used to generate web-friendly unique IDs. This ensures compatibility with Datastar’s signal naming requirements.
Controlling Visibility with Data Attributes
The data-show attribute conditionally renders messages while the countdown is above zero. A correction is made to properly reference signals using the required syntax.
Displaying a Countdown Timer
A visual countdown is added using data-text, dynamically showing remaining seconds before dismissal. This enhances user feedback and demonstrates reactive UI updates.
Backend-Driven UI Updates
The video concludes by highlighting Datastar’s ability to update UI state from the backend without full page refreshes. This enables precise, surgical updates while keeping application state centralized on the server.
The first UI element I want to tackle is our flash slash toast messages, because you might have noticed that if we go into the UI and we do something like edit, and let's just delete this article, this thing stays forever until we change the page, or change the page so we can refresh here and it goes away. It would be nice if that would auto close or auto remove itself.
It would also be nice if we could have more showing at the same time so the user can kind of, or the user ourselves can follow what has been happening. So the first thing we're going to do to start working with the data star is we need to go here to the website. We can click get started. And we could just add this module to our
base layout and we could be working with Datastar instantly. However, we already have set up for this so we can host our own JavaScript files and this will be faster than using the CDN for most cases, right? Because we are shipping directly with the binary and we will, before we go to production, add some caching both to assets and pages so that
We will still have quick delivery of these type of files. And we don't rely on our third party provider to deliver our asset like JS Deliverer. I'm sure they are great, but I prefer to do this myself. So what we need is we're gonna grab data star V1, release candidate six at the time of recording. This might change.
This will change, sorry, this will change and probably to update the course at that point. But for now, we're gonna be using RC6. Then we jump into assets. We have the JS bold already. Let's just create one here called data star. Let's say data star underscore V1, or let's do dash instead dash V1. And then we can do zero, zero, zero.
and then do rc-riskand-6-min.js. Then we need to grab all of this text and paste it in here. Give that a save, jump in, jump out, go to top, and you can see we have rc-6. Great. Then to include this, we need
to go into our base layout here, and we're just going to include it at the bottom of the base layout, because we want this to be available on all of our pages or all of our views. So just like we did with the ECMDE, we're going to say script source. And then we want to say type. It's going to be module again. And then in here, we're going to say strings, replace, routes, Java,
Let's import. No, it doesn't want to import. Let's import strings first. There we go. And then we import routes. Let me say java script. And we want to replace the file param with data star dash v1 underscore zero zero dash rc6 min
and we will replace the first instance. We give that a save. Let's just jump back into the browser, go into our admin, open the development tools, and then in network, if we give it a refresh now, we should see this being imported. We can see data star here is the response that we expect. So it's being loaded and we're actually ready to deal with our
toast slash flash messages. What we want to do is that as soon as our toast message is loaded into the UI, we want it to be shown for let's say five seconds. So we have a chance to read it. And then after five seconds, we want to remove it. I'm on the attributes page here of Datastar. And you can see we have something like data show, which will show a higher element. So we probably need something like that. We also have this data on interval that runs an expression.
at a regular interval and we can add some modifiers like the duration of the interval. If you just start executing immediately and so on and so forth. Right. In flash messages dot temple, I wanna begin by on the outer diff, the main diff, we're gonna say data, gonna say data signals.
And in here, we will create a signal that is going to be unique to our name, that is going to be unique to each flash message. So what we want to do is say FMT, Sprint F. And here we want to have count. We could also call it, maybe let's call it a flash. And then we're going to provide an ID. And we're going to set this to five.
And we want to close it, and then we need to provide an ID. Currently, we are using a UID that we could turn into a string. But this breaks the syntax because we have a lot of dashes, and we need just a bunch of some amount of characters that we can use as an ID that will not break how Datastar expects us to define names.
So what I want to do is I want to still grab flashID.string here. Give that a save. And now this will be added, but it will be broken because the UID will have the four numbers, a dash, four numbers, so on and so forth. So we can jump into flash messages. And then we can change this UID to use something else called an XID. And if you look here, I'm in the GitHub in XID.
in the XID repository, and XID is simply a global unique ID generator for the web. And if you scroll down, you see we get something like this, which is perfect for our needs. It's fast, and it doesn't have any dashes. So it's also web-friendly, or at least for our use cases here. It's actually the type of ID we are going to be needing. So grab this. We're going to jump out really quick. Run Go Get.
great. And then in cookies and flash messages, we can now change this to be XID. No, it should be XID. Okay, let's just try and import it to see if I can get some
Some LSP completion. Oh, we have GitHub twice. We don't want that. Like this. Can we now get ID? We don't need a comma. We just need to go down here and say, XID. Do we need to change it? No, we do not need to change it in any other place. And we can now go back to flash messages, and this will now be equal to
what we see here. So we have a unique ID. Doing this means that we can create this interval counter that will hit on every duration. And then it will just decrease this count because increase whatever you want, but we can just gonna decrease from five down to zero. And then we can add this data show that will evaluate to true when, or sorry, evaluate to false whenever count is below
zero or equal to zero. And I guess we also have to touch upon data signals. Let's just quickly look at that. So it's just a signal, right, that we can interact with that we can add, remove, or add updates or remove. We can do specify values in here, right, that we can then use to do things in the UI with. Great.
Let's define this data on data-interval and we want a duration. So we need to do this double underscore here and then specify one second, set that equal to, and then let's just grab what we have here. Great. And then instead of doing
setting equal to a value we're just going to do minus minus so we decrease the value of this signal on every second on each ping for every second. Finally we're going to say data show and again let's just grab everything in here paste it and then we say data show as long as this value this signal here is above zero. Now if I go in
here. And let's just delete another article. We still see it, but in a couple of seconds, hopefully this one goes away. And it did not go away. And that's because I have an error here. We don't need to wrap this in parentheses anymore. This is also a note on how naming works because we can define signals like data signals. And we could do something like this and say flash message.
and then set that to five. But we need this to be unique. And we actually need to do it like this because the default is to use camel case. So this one actually gets turned into this when we actually have to interact with it down in these ones here. So we are wrapping it in brackets here so we can have this naming. And this is also what broke it because I do need to add
dollar sign, dollar sign to interact with the signal. And now we should be able to go back, give it a refresh. And let's let's hope it works now. Come on. There we go. Five seconds and it's gone. Right. We can do even more here because this signal
gets updated so we could show like a countdown that says like this is also closing or disappearing in and then provide the amounts of second that is out there that is disappearing or when it will disappear. So for example, if we say span here at a class, say text base content, let's just do 60, text SM, MG1, close it.
And then do something like auto closing in, provide another span where we will use this attribute called data text. And this will simply just show the text of a signal. And we can use this to say data dash text equals two. And let's just
everything we have here. And say we don't wanna, actually we just want to show the value. Are we good? I believe we are good. Let's try and delete another article. As you can see, auto closing in four, three, two, one, and we've disappeared. Just make this a,
flex and then flex call and then I guess let's just add flex. Should we? No, let me wrap this in a diff. Then in here we say class flex justify between text
base content. Do we need this? No, we have this. Let's just say flex and justify between. Give it a save, hit it, delete, and now we have them next to each other. So you can discuss whether or not this UI looks pretty right, but you can see how we can very easily start to add some modern UI or UX features to our applications by not really doing a lot here.
Of course, all of this FMT Sprint here can be a bit verbose. This is mainly because we're dealing with a lot of elements that we don't know upfront. And the great, the really cool thing about the data styles, we can both do this from the front end. So we can do what we do here, but we can also interact with these signals on the back end. And this is one of the things we're going to be dealing with next, because we no longer need to do full page refreshes. So every time we do our next page here,
We update the entire page. And we only really need to update this. So in the next episode, we are going to be updating our latest article. We will show which page we are currently on. And I'll also show you how you can start to use the back end to send signals to the UI or the front end state, which will do a little simplified version. But hopefully it also shows that you can do a lot of things because you can just send a bunch of signals so you can basically update.
the entire UI in a very surgical manner. And it enables a lot of powerful pictures without having to deal with, sorry, without having to deal with an SPA, a single-base application framework, and all the logic, all the state will stay in one place, which is the back end.