How to attach a keyup event to Custom Element shadowRoot

只愿长相守 提交于 2019-12-23 06:05:38

问题


I have searched for some time; but only find Polymer answers;
or answers where EventListeners are put on DOM elements inside the shadowRoot.

The effect I am trying to achieve with native Custom Elements:

  • Only the focussed element should accept (and display) a keypress

It is possible to attach a click event to the shadowRoot, it seems I am doing something wrong for the 'keyup' event.

If I put the EventListener on the window all elements (of course) update with the same key info.

window.customElements.define('game-toes', class extends HTMLElement {
  constructor() {
    super();
    let shadowRoot=this.attachShadow({mode: 'open'});
    shadowRoot.innerHTML = this.tabIndex;
    shadowRoot.addEventListener('keyup',evt=>this.shadowRoot.innerHTML = 'key:'+evt.key);        
  }
});
game-toes{
  display:inline-block;
  height:auto;
  width:100px;
  padding:1em;
  border:10px solid green;
}
game-toes:focus { 
  background-color: lightgreen;
}
<game-toes tabindex=1></game-toes>
<game-toes tabindex=2></game-toes>
<game-toes tabindex=3></game-toes>

回答1:


You can do it like you were but you need to add some extra code to make it work:

function on(el, evt, cb) {
  el.addEventListener(evt, cb);
  return () => {
    el.removeEventListener(evt, cb);
  }
}


window.customElements.define('game-toes', class extends HTMLElement {
  constructor() {
    super();
    let shadowRoot=this.attachShadow({mode: 'open'});
    shadowRoot.innerHTML = this.tabIndex;
  }
  
  connectedCallback() {
    this._offKeyup = on(this, 'keyup', evt => {
      this.shadowRoot.innerHTML = evt.key;
      evt.stopPropagation(); // Prevent the event from leaving this element
    });
  }
  
  disconnectedCallback() {
    this._offKeyup();
  }
});
game-toes{
  display:inline-block;
  height:auto;
  width:100px;
  padding:1em;
  border:10px solid green;
}
game-toes:focus { 
  background-color: lightgreen;
}
<game-toes tabindex=1></game-toes>
<game-toes tabindex=2></game-toes>
<game-toes tabindex=3></game-toes>

1) You may want to use evt.stopPropagation() to stop the event from leaving the component. 2) You either need to add your eventListener on the component itself OR, create an element in the shadowRoot with the ability to take focus and then set focus on the inner element when the component gets focus. And then you should be able to add the keyup event on that internal element. 3) It is safest to add the eventListener in connectedCallback and release them in the disconnectedCallback unless you never plan to remove your component.




回答2:


In your example, the tabindex attribute is set to the custom element <game-toes>, and not to its Shadow DOM.

As a consequence, you should instead listen to the keyup event on the custom element itself :

this.addEventListener('keyup',evt=>this.shadowRoot.innerHTML = 'key:'+evt.key);

window.customElements.define('game-toes', class extends HTMLElement {
  constructor() {
    super();
    let shadowRoot=this.attachShadow({mode: 'open'});
    shadowRoot.innerHTML = this.tabIndex;
    this.addEventListener('keyup',evt=>this.shadowRoot.innerHTML = 'key:'+evt.key);        
  }
});
game-toes{
  display:inline-block;
  height:auto;
  width:100px;
  padding:1em;
  border:10px solid green;
}
game-toes:focus { 
  background-color: lightgreen;
}
<game-toes tabindex=1></game-toes>
<game-toes tabindex=2></game-toes>
<game-toes tabindex=3></game-toes>

Alternately, if you want to listen the keyup event at the Shadow DOM level, you should set the tabindex attribute in an element inside the Shadow DOM.



来源:https://stackoverflow.com/questions/52330155/how-to-attach-a-keyup-event-to-custom-element-shadowroot

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!