Flash Messages in Laravel Inertia
To make use of flash messages in Laravel Inertia, albeit from the controller, we can use the typical operations to set flash-type session messages:
$request->session()->flash('message', 'Message');
Or by redirection:
with('message','Message');
But, when using components in Vue and not blade views, we have to do an extra step to pass this data via flash session.
Inertia Request Middleware
In Inertia, we have a middleware that is responsible for intercepting user requests; from this middleware, we can set global data to components in Vue; therefore, if you want to pass global data to components from the database, files, configurations, session, etc:
return array_merge(parent::share($request), [
'appName' => config('app.name'),
'auth.user' => fn () => $request->user()
? $request->user()->only('id', 'name', 'email')
: null,
]);
You must use this middleware; for the case of flash messages, you can use a scheme like the following:
app/Http/Middleware/HandleInertiaRequests.php
public function share(Request $request): array
{
return array_merge(parent::share($request), [
'flash' => [
'message' => $request->session()->get('message')
]
]);
}
In the example above, we are assuming that we are going to use a single flash message classification, but you can use as many as you need; for example:
app/Http/Middleware/HandleInertiaRequests.php
public function share(Request $request): array
{
return array_merge(parent::share($request), [
'flash' => [
'message' => $request->session()->get('message'),
'status' => $request->session()->get('status')
***
'other' => $request->session()->get('other')
]
]);
}
In the example above, we used an array of arrays to organize the flash messages as it is considered a scalable and organized scheme to be able to define other schemes that you want to pass globally.
Objet $page
The $page object is a variable that can be accessed globally in all components in Vue, it has various data such as:
{
"component": "Dashboard/Post/Index",
"props": {
"jetstream": {
"canCreateTeams": true,
"canManageTwoFactorAuthentication": true,
"canUpdatePassword": true,
"canUpdateProfileInformation": true,
"hasEmailVerification": false,
"flash": [
],
"hasAccountDeletionFeatures": true,
"hasApiFeatures": true,
"hasTeamFeatures": true,
"hasTermsAndPrivacyPolicyFeature": true,
"managesProfilePhotos": true
},
"user": {
"id": 1,
"name": "andres",
"email": "admin@gmail.com",
"email_verified_at": null,
"two_factor_confirmed_at": null,
"current_team_id": 1,
"profile_photo_path": null,
"created_at": "2022-05-31T15:10:22.000000Z",
"updated_at": "2022-05-31T15:28:19.000000Z",
"profile_photo_url": "https://ui-avatars.com/api/?name=a&color=7F9CF5&background=EBF4FF",
"current_team": {
"id": 1,
"user_id": 1,
"name": "andres's Team",
"personal_team": true,
"created_at": "2022-05-31T15:10:22.000000Z",
"updated_at": "2022-05-31T15:10:22.000000Z"
},
"all_teams": [
{
"id": 1,
"user_id": 1,
"name": "andres's Team",
"personal_team": true,
"created_at": "2022-05-31T15:10:22.000000Z",
"updated_at": "2022-05-31T15:10:22.000000Z"
}
],
"two_factor_enabled": false
},
"errorBags": [
],
"errors": {
},
"data": ...
"url": "/post",
"version": "207fd484b7c2ceeff7800b8c8a11b3b6"
}
And of course, any data we set in the HandleInertiaRequests middleware is located here as well.
Case study
Let's set up confirmation flash messages on each of the redirects defined above:
app/Http/Controllers/Dashboard/CategoryController.php
class CategoryController extends Controller
{
public function store(Store $request)
{
Category::create($request->validated());
return to_route('category.index')->with('message',"Created category successfully");
}
public function update(Put $request, Category $category)
{
$category->update($request->validated());
return redirect()->route('category.index')->with('message',"Updated category successfully");
}
public function destroy(Category $category)
{
$category->delete();
return to_route('category.index')->with('message',"Deleted category successfully");
}
}
To use them from components in Vue, instead of defining them manually in each of the components that we want to have the confirmation message, we can place it in a global component like AppLayout:
resources/js/Layouts/AppLayout.vue
***
<main>
{{ $page.props.flash.message }}
<slot />
</main>
***
And when performing any delete, create or update operation in this case, we will have:
Updated category successfully
Style for flash message container
Let's style the above commit message; for that:
resources/js/Layouts/AppLayout.vue
<main>
<div
v-if="$page.props.flash.message"
class="
container my-2 bg-purple-300 text-purple-800 px-4 py-3 rounded shadow-sm"
>
{{ $page.props.flash.message }}
</div>
</main>
Video Transcript
The next operation that we are going to perform would be to show a confirmation message about the operation performed, so for this I am going to require these three files here to place the message here to configure something that I am going to explain to you and here also to see a very special object, so before going into detail we are going to come here and it is a little bit what I am going to want to explain to you, so usually we have an important change with basic Laravel in which we simply configure the flash message and then we use it through a function called flash, a help function or we can configure it as:
$request->session()->flash('message', 'Message');
When we do the redirection and here it is also important to do the redirection in inertia it changes a little since we have to define it through:
return to_route('category.index')->with('message',"Deleted category successfully");
This is a middleware with which we can manipulate the request, which is what we are doing, placing that additional Data so that Inertia can then automatically set it in a very special object to be able to manipulate it here. The important thing to notice is that we do not have for free or by default an object or a place that is automatically established, the Flash message is already established on the server, that is automatically established also on the client. If we do not have to do it ourselves, then here you have a possible implementation. And here you have another one in case you want to send multiple types of flash messages depending on some situation, if an error occurred, if the application was hacked or whatever. I usually use a plain message in my courses and that's it, but you can place others:
public function share(Request $request): array
{
return array_merge(parent::share($request), [
'flash' => [
'message' => $request->session()->get('message'),
'status' => $request->session()->get('status')
***
'other' => $request->session()->get('other')
]
]);
}
In case you require it as I indicated and as you can see here it would be an array of array, it is a bit of what I told you both here and below since we can establish multiple things and not only messages in session but well again anything else you want to establish there then after this we have a page object where this Data should be saved right now we are going to print it and we are going to see where it is and access it Well here we establish the messages there is nothing strange and then we can access the messages in the following way and finally finish this exercise:
public function share(Request $request): array
{
return array_merge(parent::share($request), [
'flash' => [
'message' => $request->session()->get('message')
]
]);
}
Create the container
Then we will place a nice container but we do that in the next class so that's why I asked you to open this one remember that up here you have the location in case you get lost resources js layo and here we have the App layout here we are going to print the page object which was the one I was telling you before that is a global object that has information about the page and here you can see everything it has in case you want to check something there including here we have the Data that we are passing as is you can see that I think is the largest part and here we also have information about the user to access it is a bit typical you simply go here browsing until you find the data that interests you but we are not going to spend much time analyzing the object since we are only interested in using it based on the changes that we are going to make so I am going to place here then I also place it:
resources/js/Layouts/AppLayout.vue
***
<main>
{{ $page.props.flash.message }}
<slot />
</main>
***
In the rest But at least to test and then replicate we put the name of the flash message Remember that this is to set the flash message as I told you before we put Wi here followed by the message Here I am going to place I am going to place record update or something like updated updated and with this you can start working next step establish or pass this Data to Vue.
Remember that it is the same joke that we have in basic Laravel and with this I mean that this Data only lasts one request therefore it is Establishing it by requests and now the second request no longer exists therefore we no longer have anything then as it says the simulated is not a it is not an assignment as is and then it is always maintained until the user reloads the page if it is not it will work in the equivalent way as we have in Laravel, that is, it will comply with its validity time So here define the structure that you want and here we have the first array So let's define the next one that would be for the Data here we place the message; We can establish multiple types of messages, although this organization depends on you. Well, I put the message here, which would be message, so it is clearly understood that it is a flash message, and here we put the request to access the message. Remember that we have the request up there, you can see it in the share session, and here we finally establish:
return to_route('category.index')->with('message',"Deleted category successfully");
We look for the message, we put get and here I put message So here we have it, I'm going to copy this name to look for it right now and Well here I leave you the code again in case you made a mistake like me here I put the little arrow, we save and I think that's all I go back here I go to [Music] reload okay perfect I'm going to edit something and here you can see if I reload the page we no longer have anything so there you can see how all this works of course you can put a conditional or something so that if it's null So I didn't put this anymore it depends on you if it works for me or for us it's not going to work based on this scheme, so what's the next step to show it on the screen So we're going to do it here quickly and then we'll set some style we're going to go back here and anywhere I placed it here was precisely in the Main to see where the... I can put it up here which is the usual thing I'm going to ask...
A style is applied that is completely free and depends on what you want to do So in my case I'm going to put it is a container so that it doesn't go away well take up the whole width here if you didn't put the Center on the sheet then you would have to put an auto margin...
In the end this doesn't work magically but works like an application in Vue and internally through navigating here requests are made to the server as you can see then the same scheme that we have of client server is still maintained Although for here client effects it seems that the page reloads automatically as if it were a local application But obviously We know that is not the case but all the Data is on the server And what I mean by this is that here the validity times are still met in which as I mentioned to you in the initial course of basic larabel as I also mentioned to you at this time this only lasts one request by definition of a flash type message therefore at the next request we no longer have that flash message and therefore what we are establishing here is that this is again executed for each request even if they are internal ones that you can see here at the next request at the second and this would be null as you could see previously and therefore we no longer have anything to show according to the conditional that we placed previously so well nothing now with this we established our flash message this was the part a little more complex to put it in some way since we do not have it as direct as the rest of the characteristics in inertia so with this we go to the next class.
- Andrés Cruz
This material is part of my complete course and book; You can purchase them from the books and/or courses section, Curso y Libro Laravel 11 con Tailwind Vue 3, introducción a Jetstream Livewire e Inerta desde cero - 2024.
Develop with Laravel, Django, Flask, CodeIgniter, HTML5, CSS3, MySQL, JavaScript, Vue, Android, iOS, Flutter