Mensajes Flash en Laravel Inertia

Para hacer el uso de los mensajes flash en Laravel Inertia, aunque desde el controlador, podemos usar las operaciones típicas para establecer los mensajes de sesión tipo flash:

$request->session()->flash('message', 'Message');

O mediante la redirección:

with('message','Message');

Pero, al usar componentes en Vue y no vistas de blade, tenemos que hacer un paso extra para pasar estos datos vía sesión flash.

Middleware de peticiones de Inertia

En Inertia, tenemos un middleware que se encarga de interceptar las peticiones del usuario; desde este middleware, podemos establecer datos globales a los componentes en Vue; por lo tanto, si quieres pasar datos globales a los componentes desde la base de datos, archivos, configuraciones, sesión, etc:

return array_merge(parent::share($request), [

'appName' => config('app.name'),

'auth.user' => fn () => $request->user()
    ? $request->user()->only('id', 'name', 'email')
    : null,
]);

Debes de usar este middleware; para el caso de los mensajes flash; puedes usar un esquema como el siguiente:

app/Http/Middleware/HandleInertiaRequests.php

 public function share(Request $request): array
    {
        return array_merge(parent::share($request), [
            'flash' => [
                'message' => $request->session()->get('message')
            ]
        ]);
    }

En el ejemplo anterior, estamos suponiendo que vamos a usar una sola clasificación de mensajes flash, pero, puedes usar cuantos necesites; por ejemplo:

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')
            ]
        ]);
    }

En el ejemplo anterior, usamos un array de array para organizar los mensajes flash al considerar que es un esquema escalable y organizado para poder definir otros esquemas que quieras pasar de manera global.

Objeto $page

El objeto $page es una variable que se puede acceder de manera global en todos los componentes en Vue, tiene datos variados como:

{
  "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"
}

Y por supuesto, los datos que establezcamos en el middleware de HandleInertiaRequests se encuentran aquí también.

Caso práctico

Vamos a establecer los mensajes flash de confirmación en cada una de las redirecciones definidas anteriormente:

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");
    }
}

Para usarlos desde los componentes en Vue, en vez definirlos manualmente en cada uno de los componentes que queramos que tengan el mensaje de confirmación, lo podemos colocar en un componente global como el de AppLayout:

resources/js/Layouts/AppLayout.vue

***
<main>
  {{ $page.props.flash.message }}
  <slot />
</main>
***

Y al realizar cualquier operación de eliminación, creación o actualización en este caso, tendremos:

Updated category successfully

Estilo para el contenedor del mensaje flash

Vamos a dar un estilo para el mensaje de confirmación anterior; para eso:

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>

Transcripción del vídeo

La siguiente operación que vamos a realizar sería Mostrar algún mensaje de confirmación sobre la operación realizada entonces para esto voy a requerir estos tres archivos aquí para colocar el mensaje aquí para bueno configurar una cosita que ya te voy a explicar y por aquí también para ver un objeto muy especial entonces antes de entrar en detalle vamos a venir aquí y es un poco lo que te voy a querer explicar entonces usualmente tenemos un cambio importante con laravel básico en el cual simplemente configuramos el mensaje flash y luego lo utilizamos mediante una función llamada flash una función de ayuda o lo podemos configurar como:

$request->session()->flash('message', 'Message');

Cuando hacemos la redirección y aquí también lo importante es hacer la redirección en inertia cambia un poquito ya que tenemos que definir mediante en:

return to_route('category.index')->with('message',"Deleted category successfully");

Esto es un middleware con el cual nosotros podemos manipular el request que es lo que estamos haciendo colocar esa Data adicional para que luego automáticamente inertia la establezca en un objeto muy especial para poder manipularla aquí. Lo importante es notar que no tenemos de manera gratuita o por defecto un objeto o un lugar que se establezca automáticamente ya establecida el mensaje Flash en el servidor que se establezca de manera automática también en el cliente si no lo tenemos que hacer nosotros entonces aquí tienes una posible implementación Y aquí tienes otra en caso de que quieras enviar múltiples tipos de mensaje flash según alguna situación si ocurrió algún error si hackearon la aplicación o qué sé yo yo usualmente en mis cursos empleo es un mensaje a secas y listo pero bueno puedes colocar otros:

 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')
            ]
        ]);
    }

En caso de que lo requieras como te indicaba y tal cual puedes ver aquí sería un array de array, es un poco lo que te comento tanto aquí como abajo ya que podemos establecer múltiples cosas y no solamente mensajes en sesión sino bueno otra vez cualquier otra cosa que quieras establecer por ahí entonces luego de esto tenemos un objeto page en donde se debería de guardar esta Data ahorita la vamos a imprimir y vamos a ver dónde está y acceder la Bueno aquí establecemos los mensajes no tiene nada de raro y luego podemos acceder a los mensajes de la siguiente forma y finalmente terminar este ejercicio:

 public function share(Request $request): array
    {
        return array_merge(parent::share($request), [
            'flash' => [
                'message' => $request->session()->get('message')
            ]
        ]);
    }

Crear el contenedor

Luego lo colocaremos un contenedor bonito pero eso lo hacemos ya la siguiente clase entonces por eso te pedí que abrieras este recuerda que aquí arriba tienes la ubicación en caso de que te pierdas resources js layo y aquí tenemos el de App layout por aquí vamos a imprimir el objeto page que era el que te comentaba antes que es un objeto global que tiene información de la página y por aquí puedes ver todo lo que tiene en caso de que bueno quieras consultar alguna cosita por ahí inclusive aquí tenemos la Data que le estamos pasando tal cual puede ver que creo que es la parte más grande y aquí también tenemos información sobre el usuario para acceder es un poco lo típico simplemente vas aquí navegando hasta que encuentres el dato que te interese pero no nos vamos a poner mucho a analizar el objeto ya que solamente nos interesa emplearlo en base a la a los cambios que vamos a realizar entonces voy a colocar aquí luego lo también lo coloco:

resources/js/Layouts/AppLayout.vue

***
<main>
  {{ $page.props.flash.message }}
  <slot />
</main>
***

En el resto Pero al menos para probar y luego replico colocamos el nombre del mensaje flash Recuerda que esto es para establecer el mensaje flash tal cual te comenté antes colocamos aquí Wi seguido del mensaje Aquí voy a colocar voy a colocar record update o algo por el estilo updated actualizado y ya con esto puede empezar a trabajar siguiente paso establecer o pasar esta Data A Vue.
Recuerda que es el mismo chiste que tenemos en laravel básico y con esto me refiero a que esta Data solamente dura una petición por lo tanto lo va Estableciendo por peticiones y ya la segunda petición ya no existe por lo tanto ya no tenemos nada entonces como que dice el simulado no es un no es una asignación a secas y luego siempre se mantiene hasta que el usuario recargue la página si no es va a funcionar de la manera equivalente como tenemos en laravel es decir, va a cumplir con su tiempo de vigencia Entonces por aquí define la estructura que tú quieras y aquí tenemos el primer array Así que vamos a definir el siguiente que sería para la Data aquí colocamos el message; podemos establecer múltiples tipos de mensajes aunque está organización ya depende de ti y Bueno coloco aquí el mensaje que sería message así se entiende clarito que es un mensaje flash y por aquí colocamos el request para acceder al mensaje recuerda que el request lo tenemos allí arriba lo puedes ver en el share sesión y aquí finalmente establecemos:

return to_route('category.index')->with('message',"Deleted category successfully");

Buscamos el mensaje colocamos get y aquí coloco message Entonces ya aquí lo tenemos voy a copiar este nombre para buscarlo ahorita y Bueno aquí te dejo el código otra vez en caso de que bueno te hayas equivocado como yo aquí coloco flechita guardamos y creo que es todo regreso acá voy a [Música] recargar okay perfecto voy a editar algo y aquí lo puedes ver si recargo la página ya no tenemos nada entonces ahí puedes ver cómo funciona todo esto claro puedes colocar un condicional o algo para que si es nulo Entonces no coloque esto ya depende de ti si te funciona a mí o a nosotros no va a funcionar en base a este esquema, entonces cuál es el siguiente paso mostrarlo por pantalla Entonces vamos a hacerlo aquí rapidito y luego le establecemos algún estilo vamos a regresar aquí y en cualquier parte yo aquí lo coloqué fue justamente en el Main para ver dónde está el … puedo colocar por aquí arriba que es lo usual voy a preguntar…
Se aplica un estilo que es completamente libre y depende de lo que quieras realizar Así que en mi caso voy a colocar es un container para que no se vaya bueno ocupe todo el ancho aquí si no colocaste el Center en la hoja entonces tuvieras que colocar un margin auto …
Al final esto no funciona de manera mágica sino funciona como una aplicación en Vue e internamente mediante vamos navegando por aquí se van haciendo peticiones al servidor tal cual puedes ver entonces se sigue manteniendo el mismo esquema que tenemos de cliente servidor Aunque para aquí efectos del cliente pareciera que la página recarga que automáticamente como si fuera una aplicación local Pero obviamente Nosotros sabemos que no es así sino toda la Data está en el servidor Y a lo que me refiero con esto es que aquí todavía se cumplen los tiempos de vigencias en los cuales como te mencioné en el curso inicial de larabel básico como también te mencioné en estos momentos esto solamente dura un request por definición de un mensaje de tipo flash por lo tanto a la siguiente petición ya no tenemos ese mensaje flash y por lo tanto lo que estamos Estableciendo aquí que esto otra vez se ejecuta por cada petición aunque sean internas que las puedes ver por acá a la siguiente petición a la segunda y esto sería nulo tal cual pudiste ver anteriormente y por lo tanto ya no tenemos nada que Mostrar según el condicional que colocamos anteriormente así que pues nada ya con esto establecimos nuestro mensaje flash este si fue la parte un poquito más compleja por decirlo de alguna manera ya que no lo tenemos tan directo como el resto de las características en inertia así que ya con esto vamos a la siguiente clase.

- Andrés Cruz

In english

Este material forma parte de mi curso y libro completo; puedes adquirirlos desde el apartado de libros y/o cursos Curso y Libro Laravel 11 con Tailwind Vue 3, introducción a Jetstream Livewire e Inerta desde cero - 2024.

Andrés Cruz

Desarrollo con Laravel, Django, Flask, CodeIgniter, HTML5, CSS3, MySQL, JavaScript, Vue, Android, iOS, Flutter

Andrés Cruz En Udemy

Acepto recibir anuncios de interes sobre este Blog.

!Cursos desde!

10$

En Udemy

Quedan 3d 10:52!


Udemy

!Cursos desde!

4$

En Academia

Ver los cursos

!Libros desde!

1$

Ver los libros
¡Hazte afiliado en Gumroad!