J'essayais de créer un composant d' Input
pour mon projet. Je souhaite définir l'attribut type de manière dynamique sur input
élément d' input
Mais lorsque je définis l'attribut type dynamiquement sur l' input
j'obtiens une erreur disant que 'type' attribute cannot be dynamic if input uses two-way binding
Existe-t-il donc une solution de contournement pour que je puisse définir l'attribut de type dynamiquement sans perdre la liaison bidirectionnelle
Input.svelte
<script> export let placeholder = ""; export let label = ""; export let description = ""; export let value = ""; export let type = "text"; </script> <div class="container"> <label>{label}</label> <input {type} bind:value {placeholder} /> <p>{description}</p> </div>
3 Réponses :
Le type
raison doit être statique avec une liaison bidirectionnelle est que le code généré par Svelte est différent pour différents types d'entrée. Par exemple, les entrées de number
et de range
doivent avoir leurs valeurs forcées à un nombre, certaines entrées nécessitent des écouteurs d'événement de change
au lieu d'événements d' input
ou vice versa, et ainsi de suite.
Mais vous pouvez faire manuellement la même chose que le code généré - en ajoutant un écouteur d'événement qui reflète l'état:
<script> export let placeholder = ""; export let label = ""; export let description = ""; export let value = ""; export let type = "text"; const handleInput = e => { // in here, you can switch on type and implement // whatever behaviour you need value = type.match(/^(number|range)$/) ? +e.target.value : e.target.value; }; </script> <div class="container"> <label>{label}</label> <input {type} {value} {placeholder} on:input={handleInput} /> <p>{description}</p> </div>
Salut Rich, la coercition de valeur ne fonctionne pas - j'obtiens toujours le type de chaîne au lieu du nombre pour les entrées [type = number]. J'ai utilisé console.log{ value: new FormData(form).get('inputname') }
dans l'événement <form on:submit>
. Merci pour ce merveilleux cadre Svelte btw!
MISE À JOUR: Rich, en fait votre solution semble fonctionner. Il semble que ce soit le comportement du formulaire qui convertit toutes les données du formulaire en types de chaîne lors de la soumission.
Une solution de contournement simple: obtenez l'élément par id et utilisez element.setAttribute(attributename, attributevalue)
pour définir le type
<script> export let id = ""; export let placeholder = ""; export let label = ""; export let description = ""; export let value = ""; export let type = "text"; </script> <div class="container"> <label>{label}</label> <input {type} bind:value {placeholder} on:focus="{() => { console.log(type) let inpt = document.getElementById(id) inpt.setAttribute("type", type) console.log(inpt) }}"/> <p>{description}</p> </div>
J'espère que cela aide :-)
<InputField type="email" bind:value={emailValue} />
Avec cette approche, la valeur sera toujours de type string, lorsque nous spécifions type=number
ou type=range
en svelte, nous nous attendons à ce que la valeur liée soit de type number. Dans cette approche, nous aurions également besoin de gérer le changement de type de chaîne en nombre