mirror of
https://0xacab.org/sutty/sutty
synced 2024-11-23 04:46:21 +00:00
feat: un potencial reemplazo de htmx en stimulus
htmx duplica mucho código y no hace monitoreo de modificaciones en el código sin grandes parches. con esto podemos ir reemplazando htmx por algo que nos resulta más cómodo y eventualmente pasar a turbo.
This commit is contained in:
parent
5b9cd27a79
commit
922fff29ea
1 changed files with 107 additions and 0 deletions
107
app/javascript/controllers/htmx_controller.js
Normal file
107
app/javascript/controllers/htmx_controller.js
Normal file
|
@ -0,0 +1,107 @@
|
|||
import { Controller } from "stimulus";
|
||||
|
||||
/*
|
||||
* Un controlador que imita a HTMX
|
||||
*/
|
||||
export default class extends Controller {
|
||||
connect() {
|
||||
// @todo Convertir en <template>
|
||||
this.placeholder = "<span class=\"placeholder w-100\" aria-hidden=\"true\"></span>";
|
||||
}
|
||||
|
||||
/*
|
||||
* Obtiene la URL y elimina la acción.
|
||||
*
|
||||
* @param event [Event]
|
||||
*/
|
||||
getUrlOnce(event) {
|
||||
this.getUrl(event);
|
||||
|
||||
event.target.dataset.action = event.target.dataset.action.replace("htmx#getUrlOnce", "").trim();
|
||||
}
|
||||
|
||||
/*
|
||||
* Lanza el evento que va a descargar la URL y agregarse en algún
|
||||
* lado.
|
||||
*
|
||||
* @param event [Event]
|
||||
*/
|
||||
getUrl(event) {
|
||||
// @todo Stimulus >1
|
||||
const value = event.target.dataset.htmxGetUrlParam;
|
||||
|
||||
if (value) {
|
||||
window.dispatchEvent(new CustomEvent("htmx:getUrl", { detail: { value } }));
|
||||
} else {
|
||||
console.error("Missing data-htmx-get-url-param attribute on element", event.target);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Realiza una petición.
|
||||
*
|
||||
* @param url [String]
|
||||
* @return [Promise<Response>]
|
||||
*/
|
||||
async request(url) {
|
||||
const headers = new Headers();
|
||||
const signal = window.abortController?.signal;
|
||||
|
||||
headers.set("HX-Request", "true");
|
||||
|
||||
return fetch(url, { headers, signal });
|
||||
}
|
||||
|
||||
/*
|
||||
* Obtiene la URL enviada por el evento y reemplaza el contenido del
|
||||
* elemento.
|
||||
*/
|
||||
async swap(event) {
|
||||
const response = await this.request(event.detail.value);
|
||||
|
||||
if (response.ok) {
|
||||
this.element.innerHTML = this.placeholder;
|
||||
this.element.innerHTML = await response.text();
|
||||
this.triggerEvents(response.headers);
|
||||
window.htmx.process(this.element);
|
||||
} else {
|
||||
console.error(response);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Agrega el resultado de la descarga al final del elemento.
|
||||
*/
|
||||
async beforeend(event) {
|
||||
const response = await this.request(event.detail.value);
|
||||
|
||||
if (response.ok) {
|
||||
this.element.insertAdjacentHTML("beforeend", this.placeholder);
|
||||
this.element.lastElementChild.outerHTML = await response.text();
|
||||
|
||||
this.triggerEvents(response.headers);
|
||||
|
||||
// @todo Asume que cada endpoint solo devuelve un elemento por vez
|
||||
window.htmx.process(this.element.lastElementChild);
|
||||
} else {
|
||||
console.error(response);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Lanza los eventos que vienen con la respuesta.
|
||||
*/
|
||||
triggerEvents(headers) {
|
||||
if (!headers.has("HX-Trigger")) return;
|
||||
|
||||
const events = JSON.parse(headers.get("HX-Trigger"));
|
||||
|
||||
setTimeout(() => {
|
||||
for (const event in events) {
|
||||
const detail = events[event];
|
||||
|
||||
window.dispatchEvent(new CustomEvent(event, { detail }));
|
||||
}
|
||||
}, 1);
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue