Buy Access to Course
16.

Notificaciones Toast

|

Share this awesome video!

|

Keep on Learning!

With a Subscription, click any sentence in the script to jump to that part of the video!

Login Subscribe

Una parte importante de cualquier sitio bonito y funcional es un sistema de notificaciones. En Symfony, a menudo pensamos en mensajes flash: mensajes que mostramos cerca de la parte superior de la página, por ejemplo, después de que el usuario envíe un formulario. Y sí, a eso me refiero. Pero no nos basta con mostrarlos en la parte superior de la página. En lugar de eso, quiero mostrarlas como notificaciones ricas de estilo tostado en la parte superior derecha, que desaparezcan automáticamente con transiciones CSS y que puedan atarme los zapatos por mí.

Representación de mensajes Flash

En nuestros controladores CRUD, ya estoy configurando un mensaje flash success... pero no lo estoy renderizando en ninguna parte. En el directorio templates/, crea un nuevo _flashes.html.twig. Para empezar, simplemente haz un bucle sobre los mensajes de éxito con for message inapp.flashes('success') ... y endfor:

6 lines | templates/_flashes.html.twig
{% for message in app.flashes('success') %}
// ... lines 2 - 4
{% endfor %}

Dentro, pegaré un mensaje flash muy sencillo, que empezará a fijarse en la parte inferior de la página:

{% for message in app.flashes('success') %}
<div class="fixed bottom-0 right-0 m-4 p-4 bg-green-500 text-white rounded shadow">
{{ message }}
</div>
{% endfor %}

A continuación, en base.html.twig, en lugar de poner los flashes en algún lugar cerca de la parte superior del cuerpo, ponlos en la parte inferior. Digamos <div id="flash-container"> y luego{{ include('_flashes.html.twig') }}:

57 lines | templates/base.html.twig
<!DOCTYPE html>
<html>
// ... lines 3 - 15
<body class="bg-black text-white font-mono">
// ... lines 17 - 51
<div id="flash-container">
{{ include('_flashes.html.twig') }}
</div>
</body>
</html>

El id="flash-container" no es importante todavía, pero será útil más adelante cuando hablemos de los flujos Turbo.

Veamos si funciona Pulsa "Guardar" y... ¡ya está! Está en un sitio raro, pero aparece.

Hacer bonita la notificación

Para que quede más bonito, vamos a Flowbite. Busca "tostada". Ah, esto tiene algunos ejemplos geniales de diferentes estilos de notificaciones tostadas. ¡Esto me hace sentir peligroso!

Tip

También recomiendo añadir un atributo data-turbo-temporary a la raíz <div>. Esto eliminará el mensaje flash antes de que Turbo tome su "instantánea" para el almacenamiento en caché, Esto significa que si el usuario hace clic en "Volver" a una página, el brindis no seguirá siendo visible.

De vuelta en _flashes.html.twig, pegaré algo de contenido:

{% for message in app.flashes('success') %}
<div
class="fixed top-5 right-5 flex items-center w-full max-w-xs p-4 mb-4 text-gray-500 bg-white rounded-lg shadow dark:text-gray-400 dark:bg-gray-800"
role="alert"
>
<div class="inline-flex items-center justify-center flex-shrink-0 w-8 h-8 text-green-500 bg-green-100 rounded-lg dark:bg-green-800 dark:text-green-200">
<svg class="w-5 h-5" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="currentColor" viewBox="0 0 20 20">
<path d="M10 .5a9.5 9.5 0 1 0 9.5 9.5A9.51 9.51 0 0 0 10 .5Zm3.707 8.207-4 4a1 1 0 0 1-1.414 0l-2-2a1 1 0 0 1 1.414-1.414L9 10.586l3.293-3.293a1 1 0 0 1 1.414 1.414Z"/>
</svg>
<span class="sr-only">Check icon</span>
</div>
<div class="ms-3 text-sm font-normal">{{ message }}</div>
<button
type="button"
class="ms-auto -mx-1.5 -my-1.5 bg-white text-gray-400 hover:text-gray-900 rounded-lg focus:ring-2 focus:ring-gray-300 p-1.5 hover:bg-gray-100 inline-flex items-center justify-center h-8 w-8 dark:text-gray-500 dark:hover:text-white dark:bg-gray-800 dark:hover:bg-gray-700"
aria-label="Close"
>
<span class="sr-only">Close</span>
<svg class="w-3 h-3" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 14 14">
<path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="m1 1 6 6m0 0 6 6M7 7l6-6M7 7l-6 6"/>
</svg>
</button>
</div>
{% endfor %}

Esto está muy inspirado en los ejemplos de Flowbite. Pero en realidad no ha cambiado nada: seguimos haciendo bucles sobre la misma colección y seguimos volcando el mensaje. Sólo tenemos un bonito marcado alrededor de esto.

¡Y no puedo querer verlo! Voy a editar y a "Guardar". Qué maravilla! En la parte superior derecha, donde yo quiero, y todo hecho con CSS.

Hacer que la tostada se pueda cerrar

Aunque todavía no se cierra automáticamente. Demonios, ¡no se cierra en absoluto! Como "cerrar" cosas será un problema común, vamos a crear un controlador Stimulus reutilizable que pueda hacerlo.

En assets/controller/, añade un nuevo closeable_controller.js. Haré trampas y cogeré el código de otro controlador... límpialo... y luego añade un método close(). Cuando se llame a éste, eliminará todo el elemento al que está unido el controlador:

import { Controller } from '@hotwired/stimulus';
export default class extends Controller {
close() {
this.element.remove();
}
}

Para utilizar esto, en _flashes.html.twig, adjunta el controlador al elemento de nivel superior, porque eso es lo que debe eliminarse al cerrarse. A continuación, en el botóndata-action="closeable#close":

27 lines | templates/_flashes.html.twig
{% for message in app.flashes('success') %}
<div
// ... lines 3 - 4
data-controller="closeable"
>
// ... lines 7 - 13
<button
// ... lines 15 - 17
data-action="closeable#close"
>
// ... lines 20 - 23
</button>
</div>
{% endfor %}

No necesitamos el click porque esto es un button, así que Stimulus ya sabe que queremos que esto se active en el evento click.

¡Vamos a probarlo! Pulsa editar y Guardar. Ya está... ha desaparecido.

En sólo unos minutos de trabajo, ¡hemos creado un bonito y funcional sistema de notificación de tostadas! Pero, ¡maldita sea, esto no es lo suficientemente guay para nuestra misión 30 Días de LAST Stack! Así que mañana lo mejoraremos con autocierre, transiciones CSS y una barra de temporizador animada.