> ## Documentation Index
> Fetch the complete documentation index at: https://kawax.biz/llms.txt
> Use this file to discover all available pages before exploring further.

# ⚡Introducción a Livewire 4 — Crear UIs reactivas sin JavaScript

> Se explica cómo construir UIs interactivas sin escribir JavaScript utilizando Livewire 4, el paquete de primera parte de Laravel, desde la instalación hasta ejemplos de código prácticos.

## ¿Qué es Livewire?

Cuando intentabas crear UIs dinámicas en Laravel, antes no había más remedio que combinar frameworks JavaScript como Vue.js o React, o escribir tú mismo las peticiones AJAX.

**Livewire** es un paquete para Laravel que resuelve ese problema. Permite construir UIs reactivas solo con PHP y Blade. Puedes implementar en PHP funcionalidades que antes requerían JavaScript, como validación de formularios en tiempo real, búsqueda en vivo, contadores, etc.

<Info>
  Livewire 4 funciona con Laravel 10 o superior y PHP 8.1 o superior. La versión más reciente actualmente es Livewire 4.
</Info>

### Resumen del mecanismo

Un componente Livewire es la combinación de una clase PHP en el servidor y una plantilla Blade. Cuando el usuario hace clic en un botón o rellena un formulario, Livewire envía por debajo una petición AJAX, ejecuta PHP y refleja en la página solo la parte modificada. El desarrollador no tiene que ser consciente de este mecanismo y puede escribir todo solo con PHP.

***

## Instalación

Ejecuta el siguiente comando en la raíz de tu aplicación Laravel.

```shell theme={null}
composer require livewire/livewire
```

Como el autodescubrimiento de paquetes de Laravel está activo, no se necesita configuración adicional.

### Creación del archivo de layout

Si vas a usarlo como componente de página completa, necesitas un archivo de layout. Puedes generarlo con el siguiente comando Artisan.

```shell theme={null}
php artisan livewire:layout
```

Se genera `resources/views/layouts/app.blade.php`.

```blade theme={null}
<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
    <head>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">

        <title>{{ $title ?? config('app.name') }}</title>

        @vite(['resources/css/app.css', 'resources/js/app.js'])

        @livewireStyles
    </head>
    <body>
        {{ $slot }}

        @livewireScripts
    </body>
</html>
```

`@livewireStyles` y `@livewireScripts` cargan automáticamente los assets de Livewire y Alpine.js.

***

## Tu primer componente

Existe un comando Artisan para generar componentes Livewire. Vamos a crear un contador simple.

```shell theme={null}
php artisan make:livewire Counter
```

Con este comando se genera un componente de archivo único llamado `resources/views/components/⚡counter.blade.php`.

<Tip>
  El ⚡ en el nombre del archivo sirve para identificar a simple vista los componentes Livewire. Mejora la visibilidad en el editor. Si no lo necesitas, puedes desactivarlo en la configuración.
</Tip>

Edita el archivo generado de la siguiente manera.

```blade theme={null}
<?php

use Livewire\Component;

new class extends Component {
    public int $count = 0;

    public function increment(): void
    {
        $this->count++;
    }

    public function decrement(): void
    {
        $this->count--;
    }
};
?>

<div>
    <h1>Contador: {{ $count }}</h1>

    <button wire:click="increment">+1</button>
    <button wire:click="decrement">-1</button>
</div>
```

Para incrustar este componente en una plantilla Blade, se usa la sintaxis normal de componentes Blade.

```blade theme={null}
<livewire:counter />
```

Cada vez que se hace clic en un botón, el contador se actualiza sin recargar la página. `wire:click` es el mecanismo para invocar un método PHP en lugar de JavaScript.

***

## Propiedades y acciones

### Propiedades — `wire:model`

Con la directiva `wire:model` puedes vincular bidireccionalmente un elemento de entrada con una propiedad del componente.

```blade theme={null}
<?php

use Livewire\Component;

new class extends Component {
    public string $name = '';
    public string $email = '';
};
?>

<div>
    <input type="text" wire:model="name" placeholder="Nombre">
    <input type="email" wire:model="email" placeholder="Email">

    <p>Hola, {{ $name }} ({{ $email }})</p>
</div>
```

Por defecto, `wire:model` sincroniza con el servidor solo cuando se ejecuta una acción (por ejemplo, el envío del formulario). Si quieres que se sincronice a cada entrada, añade el modificador `.live`.

| Notación               | Comportamiento                                                                         |
| ---------------------- | -------------------------------------------------------------------------------------- |
| `wire:model`           | Sincroniza solo cuando se ejecuta una acción (envío de formulario, etc.) (por defecto) |
| `wire:model.live`      | Envía una petición a cada entrada                                                      |
| `wire:model.blur`      | Sincroniza al perder el foco (no se genera petición)                                   |
| `wire:model.live.blur` | Envía una petición al perder el foco                                                   |

### Acciones — `wire:click`, `wire:submit`

`wire:click` liga un método al evento de clic, y `wire:submit` al evento de envío de formulario.

```blade theme={null}
<?php

use Livewire\Component;
use App\Models\Task;

new class extends Component {
    public string $taskName = '';

    public function addTask(): void
    {
        Task::create(['name' => $this->taskName]);
        $this->taskName = '';
    }

    public function render()
    {
        return $this->view([
            'tasks' => Task::latest()->get(),
        ]);
    }
};
?>

<div>
    <form wire:submit="addTask">
        <input type="text" wire:model="taskName" placeholder="Nombre de la tarea">
        <button type="submit">Añadir</button>
    </form>

    <ul>
        @foreach ($tasks as $task)
            <li>{{ $task->name }}</li>
        @endforeach
    </ul>
</div>
```

***

## Validación en tiempo real

En Livewire 4 puedes definir reglas de validación directamente en las propiedades con el atributo `#[Validate]`.

```blade theme={null}
<?php

use Livewire\Attributes\Validate;
use Livewire\Component;
use App\Models\Post;

new class extends Component {
    #[Validate('required|min:3')]
    public string $title = '';

    #[Validate('required|min:10')]
    public string $content = '';

    public function save(): void
    {
        $this->validate();

        Post::create([
            'title' => $this->title,
            'content' => $this->content,
        ]);

        $this->reset(['title', 'content']);

        session()->flash('message', 'Se ha guardado el artículo.');
    }
};
?>

<div>
    @if (session('message'))
        <div>{{ session('message') }}</div>
    @endif

    <form wire:submit="save">
        <div>
            <input type="text" wire:model.live.blur="title" placeholder="Título">
            @error('title') <span style="color: red;">{{ $message }}</span> @enderror
        </div>

        <div>
            <textarea wire:model.live.blur="content" placeholder="Contenido"></textarea>
            @error('content') <span style="color: red;">{{ $message }}</span> @enderror
        </div>

        <button type="submit">Guardar</button>
    </form>
</div>
```

Las propiedades con `#[Validate]` disparan una validación automática en cada actualización. Al combinarlas con `wire:model.live.blur`, logras una experiencia de validación en tiempo real en la que aparece el mensaje de error justo al perder el foco.

<Info>
  `$this->validate()` verifica todas las propiedades a la vez al enviar el formulario. El patrón recomendado es usarlo en dos niveles junto con la validación automática mediante `#[Validate]`.
</Info>

***

## Hooks del ciclo de vida

Los componentes Livewire tienen varios hooks de ciclo de vida.

| Hook                          | Momento                                                           |
| ----------------------------- | ----------------------------------------------------------------- |
| `mount()`                     | Cuando el componente se crea por primera vez (una sola vez)       |
| `boot()`                      | Al inicio de cada petición (tanto la primera como las siguientes) |
| `updating($property, $value)` | Justo antes de actualizar la propiedad                            |
| `updated($property)`          | Justo después de actualizar la propiedad                          |
| `rendering()`                 | Antes de renderizar la vista                                      |
| `rendered()`                  | Después de renderizar la vista                                    |
| `dehydrate()`                 | Al finalizar cada petición                                        |

### `mount()` — Inicialización

`mount()` se usa para inicializar el componente. Es el equivalente al constructor.

```blade theme={null}
<?php

use Illuminate\Support\Facades\Auth;
use Livewire\Component;

new class extends Component {
    public string $name = '';
    public string $email = '';

    public function mount(): void
    {
        $this->name = Auth::user()->name;
        $this->email = Auth::user()->email;
    }
};
?>

<div>
    <p>Nombre: {{ $name }}</p>
    <p>Email: {{ $email }}</p>
</div>
```

### `updated()` — Procesamiento tras cambiar propiedad

Si quieres insertar procesamiento después de que se actualice una propiedad, usa `updated()`. Si quieres acotarlo a una propiedad concreta, inclúyela en el nombre del método.

```blade theme={null}
<?php

use Livewire\Component;

new class extends Component {
    public string $username = '';

    public function updatedUsername(): void
    {
        $this->username = strtolower($this->username);
    }
};
?>

<div>
    <input type="text" wire:model.live="username">
    <p>Nombre de usuario: {{ $username }}</p>
</div>
```

A cada entrada, se convierte automáticamente a minúsculas.

***

## Integración con Laravel

### Uso de modelos Eloquent

Livewire puede mantener modelos Eloquent directamente como propiedades.

```blade theme={null}
<?php

use Livewire\Attributes\Validate;
use Livewire\Component;
use App\Models\User;

new class extends Component {
    public User $user;

    public function mount(User $user): void
    {
        $this->user = $user;
    }

    #[Validate('required|min:2')]
    public string $name = '';

    public function save(): void
    {
        $this->validate();
        $this->user->update(['name' => $this->name]);
        session()->flash('message', 'Se ha actualizado el perfil.');
    }

    public function render()
    {
        return $this->view();
    }
};
?>

<div>
    @if (session('message'))
        <div>{{ session('message') }}</div>
    @endif

    <form wire:submit="save">
        <input type="text" wire:model="name" placeholder="Nombre">
        @error('name') <span style="color: red;">{{ $message }}</span> @enderror
        <button type="submit">Actualizar</button>
    </form>
</div>
```

### Objetos de formulario

Los formularios complejos se pueden extraer a objetos de formulario para mantener el componente sencillo.

```shell theme={null}
php artisan livewire:form PostForm
```

```php theme={null}
namespace App\Livewire\Forms;

use Livewire\Attributes\Validate;
use Livewire\Form;
use App\Models\Post;

class PostForm extends Form
{
    #[Validate('required|min:3')]
    public string $title = '';

    #[Validate('required|min:10')]
    public string $content = '';

    public function store(): void
    {
        Post::create($this->only(['title', 'content']));
    }
}
```

Usa el objeto de formulario desde el componente.

```blade theme={null}
<?php

use App\Livewire\Forms\PostForm;
use Livewire\Component;

new class extends Component {
    public PostForm $form;

    public function save(): void
    {
        $this->form->validate();
        $this->form->store();
        $this->form->reset();
        session()->flash('message', 'Se ha creado la publicación.');
    }
};
?>

<div>
    <form wire:submit="save">
        <input type="text" wire:model="form.title" placeholder="Título">
        @error('form.title') <span style="color: red;">{{ $message }}</span> @enderror

        <textarea wire:model="form.content" placeholder="Contenido"></textarea>
        @error('form.content') <span style="color: red;">{{ $message }}</span> @enderror

        <button type="submit">Publicar</button>
    </form>
</div>
```

***

## Conclusión

Resumen de los casos de uso en los que Livewire encaja especialmente bien.

| Caso de uso                  | Lo que Livewire puede lograr                   |
| ---------------------------- | ---------------------------------------------- |
| Procesamiento de formularios | Validación en tiempo real y muestra de errores |
| Listados de datos            | Búsqueda en vivo, ordenación y paginación      |
| Contadores y toggles         | Actualizar UI sin recargar la página           |
| Panel de administración      | CRUD con integración directa con Eloquent      |
| Formularios tipo wizard      | Gestión de pasos implementada en PHP           |

Livewire lo pueden empezar a usar hoy mismo los ingenieros Laravel "que hayan usado Blade". Su mayor fortaleza es que permite lograr UIs interactivas sin el coste de aprendizaje de un framework JavaScript.

Cuando se necesitan interacciones avanzadas al nivel de una SPA, Inertia.js encaja mejor, pero para formularios, paneles de administración o tablas de datos, en muchos casos Livewire permite implementarlo de manera más simple. Empieza probando con un componente pequeño.

<Card title="Documentación oficial de Livewire" icon="book-open" href="https://livewire.laravel.com/docs">
  Consulta la documentación oficial para todas las funcionalidades de Livewire (subida de archivos, paginación, testing, etc.).
</Card>


## Related topics

- [Introducción a la autenticación](/es/authentication.md)
- [Frontend](/es/frontend.md)
- [Conocimientos necesarios antes de empezar con Laravel](/es/true-tutorial.md)
- [Introducción a React — Fundamentos para usarlo con Inertia × Laravel](/es/blog/react-introduction.md)
- [Estructura de directorios](/es/directory-structure.md)
