Svelte - Input value doesn't always update

Viewed 1477

I'm trying to create an input component in Svelte where the value is updated by a JavaScript function. However, if the new value is the same as the old value, Svelte will not update the input element.

For instance, this component should restrict input to only numbers. If you were to type "123abc", the input will then display "123abc" while the value variable is just "123".

<script>
    let value = ''
    
    const handleInput = (event) => {
        value = event.currentTarget.value.replace(/[^\d]/gu, '')
    }
</script>

<input {value} type='text' on:input={handleInput} />

<p>
    Value: "{value}"
</p>

Is there way to always make the input value to equal the value variable?

Attempted solutions

  • Use the HTML pattern attribute. While it works for this example, it will not work for the general case I'm trying to solve
  • Could just say event.currentTarget.value = value. This works perfectly, but it doesn't seem Svelte-like.
  • bind:value has the same issues as the event listener (e.g., $: value = value.replace(/[^\d]/gu, '')). Also, in the general case, bind:value won't work for me as I'm comparing the previous and updated value.

Related

3 Answers

There is nothing wrong with doing event.currentTarget.value = value it might not seem Svelte like but it's perfectly acceptable.

In your example, you have not used bind:value and declares the value to its input but instead, you could use this method

REPL

<script>
    let value = ''
    
    $: sanitized = value.replace(/[^\d]/gu, '')
</script>


<input bind:value />

<p>
    display value: {value}
</p>

<p>
    display value: {sanitized}
</p>

If you don't want to update event.currentTarget.value directly, this will also work.

const handleInput = (event) => {
    value = event.currentTarget.value;
    value = value.replace(/[^\d]/gu, '');
}
Related