Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

161
Views
Cómo manejar y pasar eventos al componente iluminado desde la definición del componente

Estoy tratando de diseñar componentes web usando el elemento iluminado y necesito ayuda con respecto a los eventos. Como podemos ver en el fragmento adjunto, podríamos usar @change="${this.handleEvent}" en la plantilla html y manejar la función handleEvent(e){} dentro del componente Element iluminado. Por esto, los eventos están limitados y controlados solo en los componentes web iluminados.

Sin embargo, cuando otras personas usan nuestros componentes web, no tienen mucho control o acceso a los valores sobre estos eventos en el componente de definición. Por ejemplo, si tenemos un archivo index.html y lo uso como <my-element onchange="handleEvent(e)"></my-element> , debería tener acceso al evento onchange y llamar a una función dentro el archivo de índice solamente.

Entonces, ¿hay alguna manera de lograr esto con el comportamiento similar de los eventos html regulares en lugar de escribir los eventos que están limitados en los componentes web de Element iluminados?

 <script src="https://unpkg.com/@webcomponents/webcomponentsjs@latest/webcomponents-loader.js"></script> <script type="module"> import { LitElement, html, css } from 'https://unpkg.com/lit-element/lit-element.js?module'; class MyElement extends LitElement { static get properties() { return { checked: { type: Boolean, attribute: true } }; } static get styles() { return [ css` div { padding: 10px; width: 90px; border: 2px solid orange; } ` ]; } render() { return html` <div> <input @change="${this.handleEvent}" ?checked="${this.checked}" type="checkbox" /> Checkbox </div> `; } handleEvent(e) { console.log(`Checkbox marked as: ${e.target.checked}`); } } customElements.define('my-element', MyElement); </script> // Index.html <my-element></my-element> // I am expecting to pass an event and handle it in the importing component. // Something like: **<my-element onchange="handleEvent(e)"}></my- element>**

about 4 years ago · Juan Pablo Isaza
3 answers
Answer question

0

Si desea escuchar eventos fuera de su elemento, debe enviar un evento como este:

 const event = new Event('my-event', {bubbles: true, composed: true}); myElement.dispatchEvent(event);

La documentación de Lit sobre eventos brinda una buena descripción general de cómo y cuándo enviar eventos https://lit.dev/docs/components/events/#dispatching-events

about 4 years ago · Juan Pablo Isaza Report

0

Por lo general, con sus propios elementos personalizados, probablemente también desee definir su propia API para ofrecerla a los consumidores de sus componentes. Eso a menudo también viene con la definición de sus propios eventos que emite su componente.

Vea este ejemplo simple (no iluminado, pero entiende la idea):

 customElements.define('foo-bar', class extends HTMLElement { input = document.createElement('input'); constructor() { super(); this.input.type = 'checkbox'; this.attachShadow({ mode: 'open' }); this.shadowRoot.appendChild(this.input); this.input.addEventListener('change', this.handleChange.bind(this)); } // replaces the internal change event with an event you publish to the outside world // this event is part of your defined API. handleChange(e) { e.stopPropagation(); const stateChange = new CustomEvent('state-change', { bubbles: true, composed: true, detail: { checked: this.input.checked } }); this.dispatchEvent(stateChange); } }); document.addEventListener('state-change', (e) => { console.log(e.detail); })
 <foo-bar></foo-bar>

Si también desea admitir el enlace de eventos declarativos como lo hacen los elementos HTML estándar (y su uso se considera una mala práctica), puede lograrlo utilizando los atributos observados:

 customElements.define('foo-bar', class extends HTMLElement { input = document.createElement('input'); constructor() { super(); this.input.type = 'checkbox'; this.attachShadow({ mode: 'open' }); this.shadowRoot.appendChild(this.input); this.input.addEventListener('change', this.handleChange.bind(this)); this.declarativeValueChangeListener = this.declarativeValueChangeListener.bind(this); } // replaces the internal change event with an event you publish to the outside world // this event is part of your defined API. handleChange(e) { e.stopPropagation(); const stateChange = new CustomEvent('state-change', { bubbles: true, composed: true, detail: { value: this.input.value } }); this.dispatchEvent(stateChange); } static get observedAttributes() { return [ 'onstatechange' ]; } attributeChangedCallback(attr, oldVal, newVal) { if (oldVal === newVal) return; // nothing changed, nothing to do here if (newVal === null) { // attribute was removed this.removeEventListener('state-change', this.declarativeValueChangeListener) } else { // attribute was added this.addEventListener('state-change', this.declarativeValueChangeListener) } } declarativeValueChangeListener() { const functionStr = this.getAttribute(this.constructor.observedAttributes[0]); eval(functionStr); } }); function baz() { console.log('baz executed through declarative binding of an outside handler!'); }
 <foo-bar onstatechange="baz()"></foo-bar>

about 4 years ago · Juan Pablo Isaza Report

0

No entiendo por qué necesitas Eventos,
cuando un clic en la input puede ejecutar funciones globales o métodos locales.

No hay necesidad de oldskool bind mumbo-jumbo, no hay necesidad de atributos observedAttributes

Puede usar el onchange predeterminado , porque todos los eventos existen en HTMLElement
Solo las entradas como textarea el evento de cambio

Usado en cualquier otro elemento HTML, no sucede nada, debe llamar a this.onchange() o document.querySelector("foo-bar").onchange() usted mismo.
No puede hacer eso con sus propios nombres de atributo, ya que esos valores siempre serán una cadena y el motor del navegador no los analizará como código JS.

Sin embargo, necesita eval(code) para ejecutar el código dentro del alcance del Componente y hacer que onchange="this.baz()" funcione.

 customElements.define('foo-bar', class extends HTMLElement { constructor() { let input = document.createElement("input"); input.type = "checkbox"; super() .attachShadow({mode: 'open'}) .append(input,"click me to execute ", this.getAttribute("onchange")); this.onclick = (evt) => { // maybe you only want input.onclick //evt.stopPropagation(); let code = this.getAttribute("onchange"); try { eval(code); // this.onchange() will only execute global functions } catch (e) { console.error(e,code); } } } baz() { console.log("Executed baz Method"); } }); function baz() { console.log("Executed baz Function"); }
 <foo-bar onchange="baz()"></foo-bar> <foo-bar onchange="this.baz()"></foo-bar> <style> foo-bar { display:block; zoom:2 } </style>

Nota IMPORTANTE

shadowDOM es lo que te salva el culo aquí.

El evento onchange de la input no escapa a shadowDOM
(Al igual que composed:true lo hace en eventos personalizados)

Sin onchange , todas las declaraciones de cambio en los elementos principales se activarán , porque el evento burbujea :

 <div onchange="console.log(666)"> <input onchange="console.log(this)" type="checkbox"> </div> <style> input { zoom:3 } </style>

Este es un buen ejemplo donde un shadowRoot en un HTMLElement regular puede tener valor, sin declarar un elemento personalizado

about 4 years ago · Juan Pablo Isaza Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!