Contenido del curso

Formulario de respuestas anidadas en Livewire

Resumen

Construir un foro con respuestas anidadas en Laravel Livewire requiere algo más que un formulario extra: necesitas validar la jerarquía, refrescar el componente y controlar la visibilidad del botón con un toggle. Aquí verás cómo lograrlo paso a paso, ideal para desarrolladores que ya manejan componentes Livewire y quieren añadir interacción dinámica sin recargar la página.

¿Cómo armar el formulario de respuesta hija dentro del componente?

Lo primero es duplicar la estructura visual del formulario de respuestas principales y llevarla al componente de respuesta. En recursos/vistas/componente, abres el archivo de pregunta, copias el bloque del formulario y lo pegas justo debajo del body del componente de respuesta.

Un detalle visual importante: agrega una clase de borde con color para que el formulario no se confunda con el fondo. Pequeño cambio, gran diferencia para la experiencia de usuario.

¿Qué hace un componente Livewire? Es una clase PHP acoplada a una vista Blade que reacciona a eventos del navegador sin recargar la página. Cada propiedad pública se sincroniza automáticamente con el HTML.

¿Cómo validar y guardar la respuesta hija con su relación padre?

Reutiliza el método salvar del componente de pregunta. Cópialo al componente de respuesta y ajústalo: ahora la creación incluye el ID de la respuesta padre, el ID de la pregunta a la que pertenece, el contenido y el ID del usuario autenticado.

Para que el ID de la pregunta esté disponible, accede a él a través de la relación de la respuesta. En el modelo Respuesta debes registrar dos relaciones:

  • Una respuesta pertenece a un usuario.
  • Una respuesta pertenece a una pregunta.
  • Una respuesta puede tener una respuesta padre mediante el campo respuesta_id.

No olvides agregar el nuevo campo al arreglo $fillable del modelo. Si el campo no está registrado allí, Laravel lo ignora y no se guarda en la base de datos. Es el clásico error que te hace perder veinte minutos buscando qué pasó.

¿Por qué el componente no se actualiza tras crear la respuesta?

Al principio, después de presionar enter, la nueva respuesta hija se guarda pero no aparece hasta refrescar manualmente el navegador. Para resolverlo, registra un listener en el componente que escuche un evento personalizado y ejecute $refresh.

Dentro del método salvar, después de validar y crear, emites ese mismo evento. La lógica queda así: valida, crea, refresca el campo de input y emite el evento que dispara el refresco visual del componente.

¿Qué es $refresh en Livewire? Es un método mágico que vuelve a renderizar el componente sin cambiar su estado. Útil cuando el DOM necesita reflejar nuevos datos cargados desde la base.

¿Cómo mostrar y ocultar el formulario con un toggle?

Aquí entra la parte interactiva. Declara una propiedad booleana, por ejemplo creando, inicializada en false. En la vista, envuelve el formulario con una directiva Blade que lo muestre solo cuando esa propiedad sea verdadera.

En el botón "Responder", usa el evento wire:click.prevent para invocar un toggle de la propiedad. El modificador prevent evita que el navegador siga el enlace y recargue la página.

¿Qué significa toggle en JavaScript y Livewire?

La palabra toggle se traduce como palanca, switch o conmutador. Aplicada a una variable booleana, invierte su valor: si está en false pasa a true, y viceversa. Es la forma más limpia de mostrar y ocultar elementos sin escribir condicionales largos.

Después de crear la respuesta, devuelve la propiedad a false para que el formulario se cierre solo. Detalle pequeño, pero hace que la interfaz se sienta pulida.

¿Cómo limitar la jerarquía a un solo nivel de respuestas anidadas?

Permitir respuestas infinitamente anidadas suele ser un dolor de cabeza visual y lógico. La regla aquí es clara: solo las respuestas principales (las que tienen respuesta_id en null) pueden recibir respuestas hijas.

Esta restricción se aplica en dos capas:

  • En PHP, al inicio del método salvar, agrega una condición: si respuesta_id no es nulo, retorna inmediatamente sin crear nada.
  • En la vista Blade, envuelve el botón "Responder" en un if que verifique si el campo respuesta_id es nulo. Si no lo es, el botón ni siquiera se renderiza.

Primero validas en el backend, luego ajustas la vista. Ese orden importa: si la lógica de PHP es correcta, los cambios visuales son cosmética encima de una base sólida.

¿Para qué sirve .prevent en wire:click? Cancela el comportamiento por defecto del navegador, como recargar al hacer clic en un enlace. Equivale a event.preventDefault() en JavaScript puro.

¿Qué piezas necesitas tocar en total para que funcione?

Resumiendo el flujo de cambios concretos:

  1. Vista Blade del componente respuesta con el formulario condicionado a la propiedad creando.
  2. Botón con wire:click.prevent que ejecuta el toggle y un if que lo oculta cuando ya es respuesta hija.
  3. Método salvar con validación de jerarquía, creación incluyendo respuesta_id, reseteo del campo y emisión del evento de refresco.
  4. Listener registrado en el componente que escucha ese evento y llama a $refresh.
  5. Modelo Respuesta con el campo añadido al $fillable y la relación pertenece a una pregunta declarada.

Con estas piezas en su lugar, tu foro acepta respuestas a respuestas, refresca la interfaz al instante y mantiene la jerarquía controlada en un único nivel. ¿Te animas a extenderlo con notificaciones cuando alguien responda? Cuéntame en los comentarios cómo te fue con tu implementación.