Search code examples
inputbindsveltereactive

Svelte: Reactive computed variable bind to input


I have a reactive computed variable that is dependant to svelte store and gets initialized by making an API call when the page refreshes. I want to bind this value to an input. With this code my input doesn't work (nothing can be typed in it)

Please see this REPL and here is the code: This is App.svelte

    <script>
    import {loggedInUserProfile} from './store.js'  
    import { onMount } from 'svelte'
    import {update} from './util.js'
    
    let loggedInUserInfo
  loggedInUserProfile.subscribe((value) => (loggedInUserInfo = value))
    
    onMount(() => {
    console.log('App onMount called')
    update()        
  })
    
    const capitalizeFirstLetter = (string) => {
  return string?.charAt(0).toUpperCase() + string?.slice(1);
}
    
    
    
    $: name = loggedInUserInfo?.name
    $: lastName = loggedInUserInfo?.lastName
</script>

<div style="display:flex; flex-direction: column;">
    <div>
        <span>Name: </span><input label="name" bind:value={name}>
    </div>
    <div>
        <span>Last Name: </span><input bind:value={lastName}>
    </div>
    
</div>

And this is update in util mimicking an API call:

export const update = () => {
    setTimeout(() => {
            loggedInUserProfile.set({name: 'updated name', lastName: 'updated last name'})
        }, 1000)
}

If I change the $ to let, the input will work, but I cannot have the updated value in the input. What is the solution here?


Solution

    1. You should not use subscribe like that. For every manual subscribe you should call the returned function to unsubscribe. If you just want to get the value once outside a Svelte component, use get which can be imported from 'svelte/store'.
    2. Just bind directly to the store value via $ syntax. You do not need any of the other script stuff. Using it like that the binding works both ways.
      <input bind:value={$loggedInUserProfile.name} />
      <input bind:value={$loggedInUserProfile.lastName} />