web-dev-qa-db-fra.com

Créer un élément d'entrée personnalisé

J'essaie de créer un composant personnalisé qui étend le composant HTMLInputElement, mais rien ne s'affiche.

class myInput extends HTMLInputElement {};

customElements.define('my-input', myInput, {
  extends: 'input'
});
<my-input type="text"></my-input>

Qu'est-ce que j'oublie ici?

10
dutzi

Ce que vous attendez ne se produit pas car ce n'est pas la bonne façon d'étendre un élément déjà intégré.

Comme l'indique la documentation MDN, vous devez conserver la balise intégrée dans votre DOM et lui affecter un attribut is .

Regardez l'extrait ci-dessous en vous concentrant sur l'entrée spot .

class spotInput extends HTMLInputElement {
  constructor(...args) {
    super(...args);
    
    this.addEventListener('focus', () => {
      console.log('Focus on spotinput');
    });
  }
};

customElements.define('spot-input', spotInput, {
  extends: 'input',
});
<input type="text" placeholder="simple input">
<input is="spot-input" type="text" placeholder="spot input">

Mais je suppose que vous voulez être autorisé à utiliser un <spot-input> tag. Vous pouvez le faire en attachant n DOM fantôme , en créant n élément autonome et en lui ajoutant un <input>.

class spotInput extends HTMLElement {
  constructor(...args) {
    super(...args);
    
    // Attaches a shadow root to your custom element.
    const shadowRoot = this.attachShadow({mode: 'open'});
    
    // Defines the "real" input element.
    let inputElement = document.createElement('input');
    inputElement.setAttribute('type', this.getAttribute('type'));
    
    inputElement.addEventListener('focus', () => {
      console.log('focus on spot input');
    });
    
    // Appends the input into the shadow root.
    shadowRoot.appendChild(inputElement);
  }
};

customElements.define('spot-input', spotInput);
<input type="number">
<spot-input type="number"></spot-input>

Ensuite, si vous vérifiez l'arborescence DOM, vous devriez avoir:

<input type="number">

<spot-input type="number">
    #shadow-root (open)
        <input type="number">
</spot-input>
25
Kévin Bibollet