LitElement - Formulario de login reactivo con Lit, Fetch API y sin necesidad de hacer build

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