LitElement - Formulario de login reactivo con Lit, Fetch API y sin necesidad de hacer build
Ejemplo de Web Component reactivo con LitElement
Antes de nada comentar que el archivo lit-bundle.js y todas sus dependencias lo he extraido de este CDN
"https://cdn.skypack.dev/pin/lit@v2.0.0-rc.2-TSkkpP2AxiJKOJvPcy1M/mode=imports,min/optimized/lit.js"
Mi intención era migrar un formulario que tengo en Vue3 a Lit siempre y cuando no tenga que hacer build.
Viendo este video de Escuela IT (DesarrolloWeb.com) Miguel me dejó un enlace de
stackoverflow (https://stackoverflow.com/questions/68614776/using-lit-with-javascript-and-no-build-tools) que me ayudó a resolver este problema.
El ejemplo muestra la ejecución del componente web directamente del CDN. En mi caso he volcado uno a uno estos archivos en esta
carpeta lit.dev-v2
La parte de la reacividad se puede ver en el cambio de literal del botón enviando, el bloqueo del mismo ?disabled y si se está haciendo el post, la visualización del icono loading.png
El código HTML
<h·>Template formulario login en LitElement</h3>
<!-- incluyo sweet alert 2 (Swal) -->
<script src="//cdn.jsdelivr.net/npm/sweetalert2@11"></script>
<div id="app">
<!-- como el back está en php le incluyo el tocken CSRF por medio de una propiedad-->
<form-login csrf="<?=$csrf?>" />
</div>
<script type="module">
// este código lo dejo más abajo
</script>
El código en JS con LitElement
import {html, LitElement} from "/lit.dev/lit-bundle.js"
//set cookie guarda el idioma por defecto
import set_cookie from "/assets/js/common/cookie.js"
const URL_LOGIN = "/login/access"
const URL_ON_ACCESS = "/admin/dashboard"
export class FormLogin extends LitElement {
//propiedades reactivas
static properties = {
csrf: {type: String},
issending: {type: Boolean},
btnsend: {type: String},
}
constructor() {
super()
this.email = ""
this.password = ""
this.issending = false
this.btnsend = "Enviar"
}
//helper selector de shadow dom
$get = sel => this.shadowRoot.querySelector(sel)
submitForm(e) {
e.preventDefault();
this.issending = true
this.btnsend = "...enviando"
fetch(URL_LOGIN, {
method: "post",
headers: {
"Accept": "application/json, text/plain, */*",
"Content-Type": "application/json"
},
body: JSON.stringify({
_csrf: this.csrf,
email: this.$get("#email").value,
password: this.$get("#password").value,
})
})
.then(response => response.json())
.then(response => {
if(response?.errors?.length){
console.error(response.errors)
return Swal.fire({
icon: "warning",
title: "Errores",
html: response.errors.join("<br/>"),
})
}
set_cookie("lang", response.data.lang)
Swal.fire({
icon: "success",
title: "Acceso concedido",
showConfirmButton: false,
html: "...redirigiendo al panel de control",
})
setTimeout(() => window.location = URL_ON_ACCESS, 1000)
})
.catch(error => {
Swal.fire({
icon: "error",
title: "Vaya! Algo ha ido mal",
html: `<b>${error}</b>`,
})
})
.finally(()=>{
this.issending = false
this.btnsend = "Enviar"
})
}//submit
render() {
return html`
<form @submit=${this.submitForm}>
<div>
<label for="email">Email</label>
<input type="email" id="email" .value=${this.email} />
</div>
<div>
<label for="password">Password</label>
<input type="password" id="password" .value=${this.password} />
</div>
<button type="submit" ?disabled=${this.issending}>
${this.btnsend}
${this.issending ? html`<img src="/images/loading.png" width="25" height="25"/>`: html``}
</button>
</form>
`
}// render()
}//FormLogin
customElements.define("form-login", FormLogin)
Autor: Eduardo A. F.
Publicado: 28-11-2021 22:17
Actualizado: 05-03-2022 12:19