svelte icon indicating copy to clipboard operation
svelte copied to clipboard

Text input not updating when only the case changes

Open johnnysprinkles opened this issue 1 year ago • 3 comments

Describe the bug

If you change only the case of the first letter of the value of a textbox, it fails to update. For example if you have "Bob" and you manually type "bob" but programmatically change back to Bob, the change never appears.

Reproduction

https://svelte.dev/repl/bdb30ab3c1dd4e0bb3afd97265a03e68?version=3.49.0

Logs

No response

System Info

System:
    OS: macOS 12.4
    CPU: (16) x64 Intel(R) Core(TM) i9-9880H CPU @ 2.30GHz
    Memory: 3.41 GB / 32.00 GB
    Shell: 5.8.1 - /bin/zsh
  Binaries:
    Node: 16.14.0 - ~/.nvm/versions/node/v16.14.0/bin/node
    Yarn: 1.22.17 - /opt/brew/bin/yarn
    npm: 8.3.1 - ~/.nvm/versions/node/v16.14.0/bin/npm
  Browsers:
    Chrome: 103.0.5060.114
    Firefox: 99.0.1
    Safari: 15.5
    Safari Technology Preview: 15.4
  npmPackages:
    svelte: ^3.44.0 => 3.48.0

Severity

annoyance

johnnysprinkles avatar Jul 18 '22 20:07 johnnysprinkles

In your exemple you capitalise the first letter on every change so the value won't update if you upper/lower the first letter in the input.

Jonathan-J8 avatar Jul 18 '22 20:07 Jonathan-J8

I see what's happening, it's setting to the same value it already is, so the input.value = gets optimized away. One workaround is to set to raw updated value first, then the programmatically altered value, as in:

https://svelte.dev/repl/435add48355b45ecba561fc9440e60c5?version=3.49.0

I guess this isn't actually a bug. Let me resolve.

johnnysprinkles avatar Jul 18 '22 20:07 johnnysprinkles

You are right this is not a bug as name never changes, you can also add a $: console.log(name) in the script to make it even more obvious (it will only log once).

Unsetting the value first is a workaround but it will trigger unnecessary rerenders where you use that variable, it is likely better to force the input element's value itself:

<script>
  let name = 'World';

  function capitalize(e) {
    let newName = e.currentTarget.value;
    e.currentTarget.value = name = newName.slice(0, 1).toUpperCase() + newName.slice(1);
  }
</script>

<h1>Hello {name}!</h1>
<input value={name} on:change|preventDefault={capitalize}>

stephane-vanraes avatar Jul 19 '22 05:07 stephane-vanraes