diff --git a/src/components/index.js b/src/components/index.js index d90825d..bba4dfb 100644 --- a/src/components/index.js +++ b/src/components/index.js @@ -3,3 +3,4 @@ import "./pr2/Card.js"; import "./pr3/Dynamic.js"; import "./pr5/Button.js"; import "./pr6/Template.js"; +import "./pr7/CustomForm.js"; diff --git a/src/components/pr7/CustomForm.js b/src/components/pr7/CustomForm.js new file mode 100644 index 0000000..ec95f6a --- /dev/null +++ b/src/components/pr7/CustomForm.js @@ -0,0 +1,42 @@ +import Templates from "./Template.js"; +import fields from "./Fields.js"; +import WebComponents from "./WebComponents.js"; + +class CustomForm extends WebComponents(fields)(HTMLElement) { + + connectedCallback() { + this.render(); + const form = this.shadowRoot.querySelector("form"); + const input = this.shadowRoot.querySelector("input[type='text']"); + form.addEventListener('submit', (event) => { + // 1. Evita la recarga nativa de la página + event.preventDefault(); + + // 2. Obtiene el valor ingresado + const usernameValue = input.value; + + // 3. Crea el evento personalizado con la configuración solicitada + const customEvent = new CustomEvent('form-submitted', { + detail: { username: usernameValue }, + bubbles: true, // Permite que el evento suba por el árbol del DOM + composed: true // Permite que el evento atraviese la frontera del Shadow DOM + }); + + // 4. Emite el evento desde el propio componente + this.dispatchEvent(customEvent); + }); + } + + render() { + const props = this.getProps(); + const template = Templates(props); + this.shadowRoot.innerHTML = ""; + this.shadowRoot.appendChild(template.content.cloneNode(true)); + } +} + +window.customElements.define("wc-form", CustomForm); + +document.addEventListener('form-submitted', (e) => { + console.log('Datos recibidos del componente:', e.detail.username); +}); diff --git a/src/components/pr7/Fields.js b/src/components/pr7/Fields.js new file mode 100644 index 0000000..94591ed --- /dev/null +++ b/src/components/pr7/Fields.js @@ -0,0 +1,11 @@ +const Fields = { + id: "id", + label: "label", + type: "text", + name: "name", + placeholder: "placeholder", + buttonText: "buttonText" +}; + +export default Fields; + diff --git a/src/components/pr7/Styles.js b/src/components/pr7/Styles.js new file mode 100644 index 0000000..e47c20a --- /dev/null +++ b/src/components/pr7/Styles.js @@ -0,0 +1,11 @@ +const Styles = ` + +`; + +export default Styles; diff --git a/src/components/pr7/Template.js b/src/components/pr7/Template.js new file mode 100644 index 0000000..39e22d9 --- /dev/null +++ b/src/components/pr7/Template.js @@ -0,0 +1,16 @@ +import Styles from './Styles.js'; + +const Template = (attributes) => { + const $HTML = document.createElement('template'); + $HTML.innerHTML = ` + ${Styles} +
+ `; + return $HTML; +}; + +export default Template; diff --git a/src/components/pr7/WebComponents.js b/src/components/pr7/WebComponents.js new file mode 100644 index 0000000..4c15271 --- /dev/null +++ b/src/components/pr7/WebComponents.js @@ -0,0 +1,38 @@ +/* Mixin */ +const WebComponents = (fields = {}) => SuperClass => class extends SuperClass { + #FIELDS = fields; + + constructor() { + super(); + this.attachShadow({ mode: 'open' }); + } + + static get observedAttributes() { + return Object.keys(fields); + } + + connectedCallback() { + this.render(); + } + + attributeChangedCallback(name, oldValue, newValue) { + if (oldValue !== newValue) { + this.render(); + } + } + + + getProps() { + const props = {}; + for (const [key, defaultValue] of Object.entries(this.#FIELDS)) { + if (typeof defaultValue === "boolean") { + props[key] = this.hasAttribute(key); + } else { + props[key] = this.getAttribute(key) || defaultValue; + } + } + return props; + } +} + +export default WebComponents; diff --git a/src/index.html b/src/index.html index d233611..5283baa 100644 --- a/src/index.html +++ b/src/index.html @@ -13,11 +13,27 @@