The thing with flash messages is you have to consider 2 scenarios when using Livewire:
- One where you want instant notifications as soon as the button is clicked
- One where there is a redirect in the session
I like making my stuff custom so that I always have 100% control over it, and also from my experience you need separate handles for both. I have for example an instant flash notification that appears on a click of a button that I call via Livewire's dispatch().
However If I redirect it would disappear so I need a session flash for after the session has been redirected and depending on your scenario you need to use one of these options.
Lets say I have a Livewire Index component and within it, I have create modal. What I would do on submitting the form is show a flash notification and make the modal not show -> User clicks "Submit" modal closes, notification is shown with results success/fail. This creates a smooth UI experience. However If I were to want to redirect to the edit page after submitting the create form, I would need a session flash notification.
The instant notification banner I make like so:
- In my default app layout, I insert the livewire component:
@stack('modals')
@livewire('components.notification-manager')
Then my component is like:
class NotificationManager extends Component
{
public $banners = [];
public function render()
{
return view('livewire.components.notification-manager');
}
/**
* Appends a banner to banners[]
* @param string|null $message
* @param int $type Types:<br>0 - Error/Fail<br>1 - Success<br>2 - Info (Default)
* @param int $timeout Defaults to 3 (seconds)
* @return void
*/
#[On('show-banner')]
public function addBanner(?string $message, int $type = 2, int $timeout = 3): void
{
if(is_null($message) || empty(trim($message))) { $message = 'Failed to generate a message!'; $type = 0; }
$key = uniqid();
$timeout = $timeout *1000;
$this->banners[] = ['key' => $key, 'message' => $message, 'type' => $type, 'timeout' => $timeout];
}
public function removeBanner($key): void
{
$this->banners = array_filter($this->banners, function($banner) use ($key) {
return $banner['key'] !== $key;
});
}
}
This way I can have multiple notifications stack on each other, I can give custom timeouts, I set the type, etc
Now from anywhere in the Livewire Component I can call:
$this->dispatch('show-banner', message: 'Success message' , type: 1);
And this will make the notification appear
The frontend:
<div class="w-full fixed mx-auto top-2 right-4 flex flex-col space-y-2" style="z-index: 9999 !important;">
@foreach ($banners as $banner)
<div wire:key="banner-{{ $banner['key'] }}" x-data="{ show: true }" x-init="setTimeout(() => show = false, {{ $banner['timeout'] }})" x-show="show"
x-on:click="show = false"
...
You can use alpineJs to make it appear from top with smooth transitions and animations and you also need to display the $banner['message']
And depending on type I give it a different background color.
With session banner just make a blade component: , put it in your app layout, or the main html file you want it to be used, and have the html like so:
@props(['style' => session('flash.bannerStyle', 'success'), 'message' => session('flash.banner')])
<div x-data="{{ json_encode(['show' => true, 'style' => $style, 'message' => $message]) }}"
:class="{ 'bg-green-500': style == 'success', 'bg-red-700': style == 'danger', 'bg-yellow-500': style == 'warning', 'bg-gray-500': style != 'success' && style != 'danger' && style != 'warning'}"
style="display: none;"
x-show="show && message"
x-on:banner-message.window="
style = event.detail.style;
message = event.detail.message;
show = true;
">
...
Remember to use x-text="message" to display the message in a <p> or something, and don't forget the x-on:click="show = false" so that the notification can be closed.
Now anywhere in your livewire components you can do:
return redirect()->route('route.name')
->with('flash.banner', $message)
->with('flash.bannerStyle', 'success');
And when you return, the banner will pop out. I dont have full code for you, because mine has a lot more code in it and It took me a long time to figure it out. Im giving you an idea and more than a start to learn how the notifications should work