8
votes

erreur: l'attribut 'type' ne peut pas être dynamique si l'entrée utilise une liaison bidirectionnelle

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>


0 commentaires

3 Réponses :


26
votes

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>


2 commentaires

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.



0
votes

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 :-)


0 commentaires

0
votes
<InputField type="email" bind:value={emailValue} />

1 commentaires

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