2

Greetings to anyone that reads this. I want to preface this by saying that I'm very new to Svelte and to Component Frameworks as a whole. This is actually the first framework that I have started to learn.

I've been going through a tutorial and at certain parts of the tutorial I like to make something small that encompasses what I've just learned to further familiarize myself with the material.

Recently I started learning about Components and Component Props and decided to make an application that took in various inputs within a form and then would submit that form by logging it to the console.

It was in doing so that I noticed some interesting behavior that I managed to replicate in a separate application I made for the purpose of writing this question.

App.svelte

<script>
  import Name1 from "./lib/Name1.svelte";
  import Name2 from "./lib/Name2.svelte";

  const obj = {
    fullname: {
      fName: '',
      lName: ''
    },

    fName: '',
    lName: ''
  }
</script>

<main>
  <Name1 fullName = {obj.fullname} />
  <br><br>
  <Name2 fName = {obj.fName} lName = {obj.lName} />
  <br><br>
  <button on:click={() => (console.log(obj))}>Log Data</button>
</main>

<style>
  :root {
    font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen,
      Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
  }

  main {
    text-align: center;
    padding: 1em;
    margin: 0 auto;
  }
</style>

Name1.svelte

<script>
  export let fullName = {
      fName: '',
      lName: ''
    }
</script>

<label for="">First Name</label>
<input type="text" bind:value={fullName.fName}>

<label for="">Last Name</label>
<input type="text" bind:value={fullName.lName}>

Name2.svelte

<script>
  export let fName
  export let lName
</script>

<label for="">First Name</label>
<input type="text" bind:value={fName}>

<label for="">Last Name</label>
<input type="text" bind:value={lName}>

As you can see, I created an object (obj) and passed the various properties within that object as attributes to the components within the application. The behavior I noticed is that upon clicking the button and logging the object to the console, only the property that was an object (fullName) had data within it, but anything else did not.

enter image description here enter image description here

This was also the case with my previously application. I had text inputs and checkbox inputs that that ended up being blank when logging the object to the console, but any property that was an object had data within it.

What I tried doing to resolve this was passing the entire object, instead of just the properties within the object, to the component and entering the respective data. This actually worked and when I logged the object to the console, every field had data within it.

I'm very interested in knowing what the reason is for this behavior, and if there is any solution besides passing the entire object to each component.

Thank you in advanced to whoever reads this and presents a solution/explanation.

1 Answers1

4

The problem is how you pass the properties:

  <Name1 fullName = {obj.fullname} />
  <Name2 fName = {obj.fName} lName = {obj.lName} />

These are one-way inputs: The values are passed in but not back from within the component. This still "works" for Name1, because you pass an object, which is passed by reference, i.e. the same object will be modified by the component, while for Name2 copies of the values are passed in and then the copies are modified (or rather replaced). This does not affect the source object.

You need to use bind at the very least when using primitive values as with Name2:

  <Name1 bind:fullName = {obj.fullname} />
  <Name2 bind:fName = {obj.fName} bind:lName = {obj.lName} />

(If Name1 were to overwrite its fullName as a whole, you also need the bind there.)

H.B.
  • 166,899
  • 29
  • 327
  • 400
  • Thank you so much! You mentioning passed by reference really opened my eyes because it was something I completely forgot about. Once again, thank you. – Tchaly Leandre Jr. Jul 08 '22 at 01:10
  • Glad it helped; if this sufficiently answered the question you accept the answer using the checkmark to its left. – H.B. Jul 08 '22 at 10:01