martes, 10 de diciembre de 2024

Python, fastHTML,htmx Actualizar un campo con una petición AJAX

 1. Introducción

Con htmx, es facil modificar un componente tipo <div> con la información devuelta por una petición ajax provocada por un elemento de un formulario. En este ejemplo llenamos el componente <div> con el string "Hola

<form>
  <input type="text" name="miCampo" 
     hx-get="/ruta-del-endpoint"
     hx-trigger="blur,change"
     hx-target="#resultado">
</form>

<div id="resultado"></div>
#Python y fastHTML
@app.get("/ruta-del-endpoint")
def getFieldEvent(request:Request):
  return "Hola!

Pero si queremos actualizar el valor de un element tipo input, no funciona.

2. Modificar el valor de elementos "input" 

Para ello tenemos que recurrir a javascript

Supongamos que tenemos 4 campos. De ellos 2 se encargan de modificar el conenido de los otros dos campos. En este ejemplo el campo1 modifica al campo2 y el campo3 modifica al campo4

<form>
  <input type="text" id="campo1" name="campo1" hx-get="/ruta-del-endpoint"
     hx-trigger="blur,change" hx-target="#campo2">
  <input type="text" id="campo2" name="campo2">
  <input type="text" id="campo3" name="campo3" hx-get="/ruta-del-endpoint"
     hx-trigger="blur,change" hx-target="#campo4">
<input type="text" id="campo4" name="campo4">
</form>

Supongamos que el código Python del endpoint es el mismo

Para ello vamos a crear un program Python con FastHTML que haga los siguientes pasos:

1. Crear un objeto que guarde los ids de los campos que lanzan el evento como nombre del campo y como valor que sea el id del campo a modificar. En Python sería:

strJs="var paramsChange={'campo1':'campo2', 'campo3':'campo4'}"

2. Creamos un fichero (static/js/fieldChange.js) con  el contenido de la función javascript que actualiza los campos: Para ello busca el evento "htmx:afterRequest" y filtra aquellos cuyo endpoint es "/ruta-del-endpoint" y si el campo que lanza el evento (event.target) se encuentra dentro de la variable paramsChange entonces actualiza el valor del campo con lo que retorno la llamada ajax

// Update an input element with the value of the request
document.addEventListener("htmx:afterRequest", (event) => {
    const hxget=event.target.getAttribute('hx-get');
	if (hxget) {
		const elemId=event.target.id;
		//Only for request type get to the url "/fieldEvent"
		if (hxget.startsWith("/ruta-del-endpoint") && elemId in paramsChange) {
const targetId=paramsChange[elemId]; const input = document.querySelector(targetId); input.value = event.detail.xhr.responseText; } } });

3. A la variable python "strJs" hay que añadirle el contenido de este fichero: que es javascript

with open('static/js/fieldChange.js', 'r') as file:
  content = file.read()
  strJs+="\n"+content

4. Para crear los campos con FastHTML podemos creatr un diccionario para cada campo con los atributos de cada "input". Podríamos haber creado un form , pero para simplificar meto el javascript y los 4 campos dentro de un <div> (fh.Div). A mi me encanta como resuelve fastHTML la creaciópn de campos. Ojo que utiliza guiones bajos "_" en vez de "-" cuando define los parámetros de htmx!

fieldDicts=[
	{'type':'text', 'id':'campo1', 'name':'campo1','hx_post':'/ruta-del-endpoint', 'hx_target':'#campo2', 'hx_trigger':'blur,change'},
	{'type':'text', 'id':'campo2', 'name':'campo2'},  
	{'type':'text', 'id':'campo3', 'name':'campo3','hx_post':'/ruta-del-endpoint', 'hx_target':'#campo4', 'hx_trigger':'blur,change'},  
	{'type':'text', 'id':'campo4', 'name':'campo4'}, 
]	 
return fh.Div(
	fh.Script(strJs),
	*[fh.Input(**fieldDict) for fieldDict in fieldDicts],
)











No hay comentarios :

Publicar un comentario