reload:fragment

Desde que agarré una filosofía servidor-céntrica para mis proyectos, he estado construyendo web apps con muy poco javascript, pero manteniendo experiencias de usuario dinámicas y fluídas

Una de las estrategias que más me gusta, es la que tienen herramientas como HTMX o Alpine AJAX; Le llaman Hypermedia-Driven Application (HDA), que es como el punto intermedio entre una Multi-page Application (MPA) y una Single-Page Application (SPA)

En ésta arquitectura la aplicación usa patrones que van de actualizar fragmentos específicos del DOM con llamadas AJAX a través de enlaces y formularios html, sin recargar la pagina completa, pero tampoco delegando logica al frontend

DHH (el creador de Ruby on Rails) lo llamó HTML over the wire y es la misma filosofía detrás de soluciones más chonchas como Hotwire y Livewire

El punto es que no siempre es necesario instalar el set completo de utilidades de un framework en tu proyecto para aplicar el concepto fundamental de ésta estrategia

A veces solo necesitas "refrescar" un fragmento del DOM sin recargar la página

Para esos casos sencillos, escribí éste script; Un event listener que aplica el concepto principal de HTML over the wire, sin implementar toda la arquitectura

window.addEventListener('reload:fragment', async function (event) {
    const { element_id, url } = event.detail;

    const oldElement = document.getElementById(element_id);
    if (!oldElement) {
        return;
    }

    try {
        const response = await fetch(url);
        if (!response.ok) throw new Error(response.status);

        const html = await response.text();

        const parser = new DOMParser();
        const newDocument = parser.parseFromString(html, 'text/html');
        const newElement = newDocument.getElementById(element_id);

        if (newElement && oldElement) {
            oldElement.replaceWith(newElement);
        }
    } catch (error) {
        console.error(error);
    }
});

El event listener recibe en el evento los parámetros element_id y url, realiza una llamada HTTP y parsea la respuesta como un documento html; Extrae el elemento que necesitamos "recargar" y lo reemplaza en el DOM

El "reload" del fragmento se ejecuta despachando el evento reload:fragment

window.dispatchEvent(new CustomEvent('reload:fragment', {
    detail: { 
        element_id: 'product_index_table', 
        url: '/products/3429'
    }
}));

O también desde un componente Livewire, que se ve así

$this->dispatch('reload:fragment', [
    'element_id' => 'product_index_table',
    'url' => route('products.index', $id)
]);