Mark
Mark

Reputation: 7635

Svelte does not update value in one if branch

I am trying to implement some currency input in Svelte.

Almost everything works as excepted, but if I remove the input in the field with Backspace, I can see the log message, but the value is not set to '0.00'.

I have prepared a REPL for this: https://svelte.dev/repl/2b83934eff9747a1a1c7a15c976be316?version=3.31.2

<script>
  let amountFormatted = '0.00';
  let currencyInput;
 
  $: console.log('amountFormatted: ' + amountFormatted);

   const handleChange = () => {
     console.log('currentInput: ' + currencyInput.value);

     let cleanedInput = currencyInput.value
      .replace(/\D*/gm, '') // remove non digits
      .replace(/^0+/gm, ''); // remove leading zeros 
     console.log('cleanedInput.length: ' + cleanedInput.length);

    if (cleanedInput.length === 0 ) {
      console.log('setting amountFormatted to 0.00 --- BUT IT does not work ');
      amountFormatted = '0.00'; // ERROR this never works
    } else {
      amountFormatted = (parseInt(cleanedInput, 10) / 100).toString();
    }
  };
</script>

<input
    type="tel"
    value={amountFormatted}
    bind:this={currencyInput}
    on:input={handleChange}
/>

I almost spend the whole day to get this working as wanted. I tried things like tick() and a lot of other stuff, but it seems that amountFormatted = '0.00'; never triggers a reactive change.

Upvotes: 1

Views: 453

Answers (2)

bztes
bztes

Reputation: 150

In case some is interested for an answer one year later:

Entering the if-block several times in a row won't trigger an update for amountFormatted because the value hasn't changed. It is already 0.00 from the previous call. You can test it by adding amountFormatted = 'foo' one line before to force an update.

Upvotes: 1

Naren
Naren

Reputation: 4480

One way is doing with bind works

<input
    type="tel"
    bind:value={amountFormatted} // Not sure why without bind is not working, need to explore
    bind:this={currencyInput}
    on:input={handleChange}
/>

Or Second:

   if (cleanedInput.length === 0 ) {
      console.log('setting amountFormatted to 0.00 --- BUT IT does not work ');
      currencyInput.value = '0.00'; // this works
    } else {
      amountFormatted = (parseInt(cleanedInput, 10) / 100).toString();
    }

<input
    type="tel"
    value={amountFormatted}
    bind:this={currencyInput}
    on:input={handleChange}
/>

As per Svelte REPL I understood that for numeric inputs,

value={somevaribale} is one way binding

bind:value={somevaribale} is two way binding.

Upvotes: 1

Related Questions