Eventos
Livewire ofrece un robusto sistema de eventos que puede utilizar para comunicarse entre los diferentes componentes de la página. Debido a que utiliza los eventos del navegador, también puede utilizar el sistema de eventos de Livewire para comunicarse con los componentes Alpine o incluso con JavaScript.
Para activar un evento, puede utilizar el método dispatch() desde cualquier lugar dentro de su componente y escuchar ese evento desde cualquier otro componente en la página.
Enviando(dispatching) Eventos
Para enviar un evento desde un componente Livewire, puede llamar al método dispatch(), pasándole el nombre del evento y cualquier dato adicional que desee enviar junto con el evento.
A continuación se muestra un ejemplo de envío de un evento post-creado desde un componente CrearPublicacion:
<?php
namespace App\Livewire;
use Livewire\Component;
class CrearPublicacion extends Component{ public $titulo = '';
public $contenido = '';
public function guardar() { // ...
$this->dispatch('publicacion-creada'); }
}En este ejemplo, cuando el método dispatch() es llamado, el evento publicacion-creada será enviado, y cada otro componente en la página que está escuchando este evento será notificado.
Puedes pasar datos adicionales con el evento pasando los datos como segundo parámetro al método dispatch():
$this->dispatch('publicacion-creada', title: $publicacion->titulo);Escuchando Eventos
Para escuchar un evento en un componente Livewire, añada el atributo #[On] encima del método que desea que sea llamado cuando se envíe un evento determinado:
use Livewire\Component;use Livewire\Attributes\On;
class Panel extends Component{ #[On('publicacion-creada')] public function actualizarListaDePublicaciones($titulo) { // ... }}Ahora, cuando el evento publicacion-creada es despachado desde CrearPublicacion, una petición de red será disparada y la acción actualizarListaDePublicaciones() será invocada.
Como puedes ver, los datos adicionales enviados con el evento serán proporcionados a la acción como su primer argumento.
Escuchando nombres de eventos dinámicos
Ocasionalmente, puedes querer generar dinámicamente nombres de eventos en tiempo de ejecución usando datos de tu componente.
Por ejemplo, si quieres que un evento escuche un modelo específico de Eloquent, puedes añadir el ID del modelo al nombre del evento cuando se envíe de esta manera:
use Livewire\Component;
class ActualizarPublicacion extends Component{ public function actualizar() { // ...
$this->dispatch("publicacion-actualizada.{$publicacion->id}"); }}Y luego escucha ese modelo específico:
use Livewire\Component;use App\Models\Publicacion;use Livewire\Attributes\On;
class MostrarPublicacion extends Component{ public Publicacion $publicacion;
#[On('publicacion-actualizada.{publicacion.id}')] public function refrescarPublicacion() { // ... }}Si el modelo $publicacion anterior tuviera un ID de 3, el método refrescarPublicacion() sólo se activaría por un evento llamado: publicacion-actualizada.3.
Escuchando eventos de componentes hijos específicos
Livewire le permite escuchar eventos directamente en componentes hijos individuales en su plantilla Blade de esta manera:
<div> <livewire:editar-publicacion @saved="$refresh">
<!-- ... --></div>En el escenario anterior, si el componente hijo editar-publicacion envía un evento guardado, el $refresh del padre será llamado y el padre será refrescado.
En lugar de pasar $refresh, puedes pasar cualquier método que normalmente pasarías a algo como wire:click. Aquí hay un ejemplo de llamada a un método close() que podría hacer algo como cerrar un diálogo modal:
<div><livewire:editar-publicacion @saved="close"></div>Si el método hijo envió parámetros junto con la petición, por ejemplo $this->dispatch('saved', publicacionId: 1), puede reenviar esos valores al método padre usando la siguiente sintaxis:
<livewire:edit-post @saved="close($event.detail.publicacionId)">Usando JavaScript para interactuar con eventos
El sistema de eventos de Livewire se vuelve mucho más poderoso cuando interactúas con él desde JavaScript dentro de tu aplicación. Esto desbloquea la capacidad de cualquier otro JavaScript en su aplicación para comunicarse con los componentes de Livewire en la página.
Escuchar eventos dentro de scripts de componentes
Puedes escuchar fácilmente el evento publicacion-creada dentro de la plantilla de tu componente desde una directiva @script de la siguiente manera:
@script<script> $wire.on('publicacion-creada', () => { // });</script>@endscriptEl fragmento anterior escucharía el evento publicacion-creada del componente en el que está registrado. Si el componente ya no está en la página, el receptor de eventos ya no se activará.
Más información sobre el uso de JavaScript dentro de sus componentes Livewire →
Envío de eventos desde scripts de componentes
Además, puedes enviar eventos desde el @script de un componente de la siguiente manera:
@script<script> $wire.dispatch('publicacion-creada');</script>@endscriptCuando se ejecuta el @script anterior, el evento publicacion-creada se enviará al componente en el que está definido.
Para enviar el evento sólo al componente donde reside el script y no a otros componentes de la página (evitando que el evento “burbujee” hacia arriba), puede utilizar dispatchSelf():
$wire.dispatchSelf('publicacion-creada');Puede pasar cualquier parámetro adicional al evento pasando un objeto como segundo argumento a dispatch():
@script<script> $wire.dispatch('publicacion-creada', { refrescarPublicaciones: true });</script>@endscriptAhora puede acceder a esos parámetros de evento tanto desde su clase Livewire como desde otros escuchadores de eventos JavaScript.
He aquí un ejemplo de recepción del parámetro refrescarPublicaciones dentro de una clase Livewire:
use Livewire\Attributes\On;
// ...
#[On('publicacion-creada')]public function manejarNuevaPublicacion($refrescarPublicaciones = false){ //}También puede acceder al parámetro refrescarPublicaciones desde un receptor de eventos JavaScript desde la propiedad detail del evento:
@script<script> $wire.on('publicacion-creada', (event) => { let refrescarPublicaciones = event.detail.refrescarPublicaciones
// ... });</script>@endscriptMás información sobre el uso de JavaScript dentro de sus componentes Livewire →
Escuchar eventos Livewire desde JavaScript global
Alternativamente, puedes escuchar eventos Livewire globalmente usando Livewire.on desde cualquier script en tu aplicación:
<script> document.addEventListener('livewire:init', () => { Livewire.on('publicacion-creada', (event) => { // }); });</script>El fragmento anterior escucharía el evento de publicacion-creada enviado desde cualquier componente de la página.
Si desea eliminar este receptor de eventos por cualquier motivo, puede hacerlo utilizando la función cleanup:
<script> document.addEventListener('livewire:init', () => { let cleanup = Livewire.on('publicacion-creada', (event) => { // });
// Llamando a "cleanup()" se anulará el registro del receptor de eventos anterior... cleanup(); });</script>Eventos en Alpine JS
Debido a que los eventos Livewire son simples eventos del navegador bajo el capó, puede utilizar Alpine para escucharlos o incluso enviarlos.
Escuchando eventos Livewire en Alpine
Por ejemplo, podemos fácilmente escuchar el evento publicacion-creada usando Alpine:
<div x-on:publicacion-creada="..."></div>El fragmento anterior escucharía el evento publicacion-creada de cualquier componente Livewire que sea hijo del elemento HTML al que está asignada la directiva x-on.
Para escuchar el evento de cualquier componente Livewire de la página, puede añadir .window al listener:
<div x-on:publicacion-creada.window="..."></div>Si quieres acceder a datos adicionales que se enviaron con el evento, puedes hacerlo utilizando $event.detail:
<div x-on:publicacion-creada="notify('Nueva Publicación: ' + $event.detail.titulo)"></div>La documentación de Alpine proporciona más información sobre la escucha de eventos.
Envío de eventos Livewire desde Alpine
Cualquier evento despachado desde Alpine es capaz de ser interceptado por un componente Livewire.
Por ejemplo, podemos fácilmente enviar el evento publicacion-creada desde Alpine:
<button @click="$dispatch('publicacion-creada')">...</button>Al igual que el método dispatch() de Livewire, puedes pasar datos adicionales junto con el evento pasando los datos como segundo parámetro al método:
<button @click="$dispatch('publicacion-creada', { titulo: 'Título de la Publicación' })">...</button>Para más información sobre el envío de eventos con Alpine, consulte la documentación de Alpine.
Enviar directamente a otro componente
Si deseas utilizar eventos para comunicarse directamente entre dos componentes de la página, puedes utilizar el modificador dispatch()->to().
A continuación se muestra un ejemplo en el que el componente CreatePost envía el evento publicacion-creada directamente al componente Dashboard, omitiendo cualquier otro componente que esté escuchando ese evento específico:
use Livewire\Component;
class CrearPublicacion extends Component{ public function guardar() { // ...
$this->dispatch('publicacion-creada')->to(Dashboard::class); }}Enviar un evento de un componente a sí mismo
Usando el modificador dispatch()->self(), puedes restringir un evento para que sólo sea interceptado por el componente desde el que se disparó:
use Livewire\Component;
class CrearPublicacion extends Component{ public function guardar() { // ...
$this->dispatch('publicacion-creada')->self(); }}Envío de eventos desde plantillas Blade
Puede enviar eventos directamente desde sus plantillas Blade utilizando la función JavaScript $dispatch. Esto resulta útil cuando se desea desencadenar un evento a partir de una interacción del usuario, como el clic de un botón:
<button wire:click="$dispatch('mostrar-modal-publicacion', { id: {{ $publicacion->id }} })"> Editar Publicación</button>En este ejemplo, cuando se pulse el botón, se enviará el evento mostrar-modal-publicacion con los datos especificados.
Si desea enviar un evento directamente a otro componente, puede utilizar la función JavaScript $dispatchTo()
<button wire:click="$dispatchTo('publicacion', 'mostrar-modal-publicacion', { id: {{ $publicacion->id }} })"> Editar Publicación</button>En este ejemplo, cuando el botón es presionado, el evento mostrar-modal-publicacion será enviado directamente al componente Publicacion.
Testing de eventos enviados
Para probar los eventos enviados por su componente, utilice el método assertDispatched() en su prueba Livewire. Este método comprueba que un evento específico ha sido enviado durante el ciclo de vida del componente:
<?php
namespace Tests\Feature;
use Illuminate\Foundation\Testing\RefreshDatabase;use App\Livewire\CrearPublicacion;use Livewire\Livewire;
class CrearPublicacionTest extends TestCase{ use RefreshDatabase;
/** @test */ public function it_dispatches_publicacion_creada_event() { Livewire::test(CrearPublicacion::class) ->call('guardar') ->assertDispatched('publicacion-creada'); }}En este ejemplo, la prueba garantiza que el evento publicacion-creada se envía con los datos especificados cuando se llama al método guardar() en el componente CrearPublicacion.
Testing Listeners de eventos
Para probar los receptores de eventos, puedes enviar eventos desde el entorno de pruebas y comprobar que se realizan las acciones esperadas en respuesta al evento:
<?php
namespace Tests\Feature;
use Illuminate\Foundation\Testing\RefreshDatabase;use App\Livewire\Dashboard;use Livewire\Livewire;
class DashboardTest extends TestCase{ use RefreshDatabase;
/** @test */ public function it_updates_post_count_when_a_post_is_created() { Livewire::test(Dashboard::class) ->assertSee('Publicaciones Creadas: 0') ->dispatch('publicacion-creada') ->assertSee('Publicaciones Creadas: 1'); }}En este ejemplo, la prueba envía el evento publicacion-creada a la creación y, a continuación, comprueba que el componente Dashboard gestiona correctamente el evento y muestra el recuento actualizado.
Eventos en tiempo real con Laravel Echo
Livewire se empareja muy bien con Laravel Echo para proporcionar funcionalidad en tiempo real en sus páginas web utilizando WebSockets.
Escuchando eventos Echo
Imagina que tienes un evento en tu aplicación Laravel llamado PedidoEnviado:
<?php
namespace App\Events;
use App\Models\Pedido;use Illuminate\Broadcasting\Channel;use Illuminate\Broadcasting\InteractsWithSockets;use Illuminate\Contracts\Broadcasting\ShouldBroadcast;use Illuminate\Foundation\Events\Dispatchable;use Illuminate\Queue\SerializesModels;
class PedidoEnviado implements ShouldBroadcast{ use Dispatchable, InteractsWithSockets, SerializesModels;
public Pedido $pedido;
public function broadcastOn() { return new Channel('pedidos'); }}Puedes enviar este evento desde otra parte de tu aplicación de esta manera:
use App\Events\PedidoEnviado;
PedidoEnviado::dispatch();Si fueras a escuchar este evento en JavaScript usando sólo Laravel Echo, se vería algo como esto:
Echo.channel('pedidos') .listen('PedidoEnviado', e => { console.log(e.order) })Asumiendo que tienes Laravel Echo instalado y configurado, puedes escuchar este evento desde dentro de un componente Livewire.
A continuación se muestra un ejemplo de un componente SeguimientoPedido que está escuchando el evento PedidoEnviado con el fin de mostrar a los usuarios una indicación visual de un nuevo pedido:
<?php
namespace App\Livewire;
use Livewire\Attributes\On;use Livewire\Component;
class SeguimientoPedido extends Component{ public $mostrarNotificacionPedido = false;
#[On('echo:pedidos,PedidoEnviado')] public function notificarNuevoPedido() { $this->mostrarNotificacionPedido = true; }
// ...}Si tiene canales Eco con variables incrustadas en ellos (como un ID de Pedido), puede definir escuchas a través del método getListeners() en lugar del atributo #[On]:
<?php
namespace App\Livewire;
use Livewire\Attributes\On;use Livewire\Component;use App\Models\Pedido;
class SeguimientoPedido extends Component{ public Pedido $pedido;
public $mostrarNotificacionPedido = false;
public function getListeners() { return [ "echo:pedidos.{$this->pedido->id},PedidoEnviado" => 'notificarEnviado', ]; }
public function notificarEnviado() { $this->mostrarNotificacionPedido = true; }
// ...}O, si lo prefiere, puede utilizar la sintaxis de nombres de eventos dinámicos:
#[On('echo:pedidos.{pedido.id},PedidoEnviado')]public function notificarNuevoPedido(){ $this->mostrarNotificacionPedido = true;}Si necesita acceder a la carga útil del evento, puede hacerlo a través del parámetro $event pasado:
#[On('echo:pedidos.{pedido.id},PedidoEnviado')]public function notificarNuevoEnvio($event){ $order = Pedido::find($event['pedidoId']);
//}Canales privados y de presencia
También puede escuchar los eventos retransmitidos a canales privados y de presencia:
<?php
namespace App\Livewire;
use Livewire\Component;
class SegumientoPedido extends Component{ public $mostrarNotificacionNuevoPedido = false;
public function getListeners() { return [ // Public Channel "echo:pedidos,PedidoEnviado" => 'notificarNuevoPedido',
// Private Channel "echo-private:pedidos,PedidoEnviado" => 'notificarNuevoPedido',
// Presence Channel "echo-presence:pedidos,PedidoEnviado" => 'notificarNuevoPedido', "echo-presence:pedidos,aqui" => 'notificarNuevoPedido', "echo-presence:pedidos,entrando" => 'notificarNuevoPedido', "echo-presence:pedidos,saliendo" => 'notificarNuevoPedido', ]; }
public function notificarNuevoPedido() { $this->mostrarNotificacionNuevoPedido = true; }}