1
votes

Comment envelopper un champ de saisie dans un élément personnalisé?

J'essaye d'encapsuler un champ de saisie dans un élément personnalisé.

L'élément personnalisé DOM ressemble à ceci:

<custom-input id="test"></custom-input>

<script>
let test = document.getElementById('test')
console.log(test.value); //  should return 4 (value of inner input)

test.onkeydown = function(e){
    console.log(e.target.value); // should the new value of the inner input
};
</script>

Alors que l'élément devrait fonctionner comme ceci:

<custom-element>
  <div class="fancy-wrapper">
     <input value="4">
  </div>
<custom-element>

Existe-t-il un moyen de rediriger les attributs vers les attributs à l'intérieur sans tout connecter à la main?


0 commentaires

4 Réponses :


0
votes

Vous pouvez ajouter à la balise innerHTML de la balise d'élément personnalisé

<custom-input id="test">dd</custom-input>
var string="<input type='text' ";
document.getElementById('test').onclick = function(e){
var attr=[...document.querySelector('#test').attributes].map(attr => attr.nodeName);
attr.forEach((e)=>{
var val=document.getElementById('test').getAttribute(e);
string+=e+"="+val + " ";
})
document.getElementById("test").innerHTML+=string + '//>' ;
console.log(document.getElementById("test").outerHTML)
};


1 commentaires

J'ai édité la question pour clarifier un peu ce que je veux faire. Ma question ne concerne pas l'attribution d'un élément à l'élément personnalisé, je souhaite essentiellement avoir un HTMLInputElement personnalisé, mais avec d'autres éléments autour de l'entrée réelle.



0
votes

Si j'ai bien compris votre question, vous souhaitez copier tous les attributs de custom-element dans la balise input .

Ce que vous pouvez faire, c'est

//get all attributes of custom element
var el = document.getElementById ('test');

// get all attributes
var attrs = el.getAttributeNames(); // returns an array

// loop over attrs array and append the attribute and value in the input,
// I am assuming, you will not add copy id attribute here.

var input = el.getElementsByTagName ('input')[0];
for (var index = 0; index < attrs.length; index++) {
  if (attrs[index] !== 'id') {

    // set attribute of input with attribute name from the array,
    // and get the value from from input.

    input.setAttribute (attrs[index], el.getAttribute (attrs[index]));
  }
}

C'est une idée, vous pouvez faire autre chose.


0 commentaires

0
votes

HTML:

class CustomElement extends HTMLElement {
  constructor() {
    super();
    const currentDocument = document.currentScript.ownerDocument;
    this.template = currentDocument.querySelector('input');
  }
  get value() {
    return this.template.getAttribute('value');
  }
  set onkeydown(cb) {
    return this.template.addEventListener('keydown', cb);
  }
}

window.customElements.define('custom-element', CustomElement);

let test = document.getElementById('test');
console.log(test.value);
test.onkeydown = function(e) {
  console.log(e.target.value);
};

JavaScript:

<custom-element id="test">
  <div><input value="43" /></div>
</custom-element> 

Peut jeter un oeil à démo


2 commentaires

Je sais comment créer un élément personnalisé, la question est de savoir comment créer un wrapper autour de l'élément d'entrée, sans en perdre l'accès direct.


La question n'était pas claire désolé pour cela. Refactorisé selon la question @Daveman



2
votes

Non, ce n'est pas différent d'avoir un DIV et un autre DIV enfant

Vous devez établir vous-même la connexion entre le CustomElement et le contenu.

Une façon est de définir une fonction Get / Set sur votre Custom-Element qui récupère la valeur d'une entrée enfant

Au lieu de déclarer manuellement Get / Set Vous pouvez bien sûr boucler n'importe quel enfant et attribuez-le au CustomElement avec defineProperty a> ou Proxies

L'exemple ci-dessous crée 2 champs INPUT et un tableau this.input :

<body>
<h3>Custom Element : Connected INPUT and Range slider</h3>
Please enter a number between 20 and 50, or use the range slider
<p>
<number-and-range></number-and-range>
</p>
</body>

Et connecte (GET / SET) .valeur à this.input[0ITED

customElements.define('number-and-range', class extends HTMLElement {
  get value() {
    return this.input[0].value;
  }

  set value(val) {
    //input validation should go here
    this.input[0].value = val;
    console.clear();
    console.log('new value:',val);
  }
  connectedCallback() {
    this.input = ['number', 'range'] //create [0] and [1] values in array
      .map((type, idx) => Object.assign(
        this.appendChild(document.createElement('input')), {
          type,
          min: 20,
          max: 50,
          oninput: _ => this.value = this.input[~~!idx].value = this.input[idx].value //toggle [0] and [1]
        }));
    this.value = 42;//default value
  }
});

let el=document.querySelector('number-and-range');
console.log(el.value);
el.value=99;
    <number-and-range>
       <input type="number"> // this.input[0]
       <input type="range">  // this.input[1]
    </number-and-range>


0 commentaires