Alex
Alex

Reputation: 71

What is the right way for passing data between 2 child components in svelte

What is the right way for me to pass data between 2 child components? What I have is a pretty straightforward structure:

APP.svelte

<script>
        import Carmaterial from "./Carmaterial.svelte";
        import Carcolor from "./Carcolor.svelte";

        const carMaterial = {
            title: 'Please select car material',
            property: 'carMaterial',
            options: [
                {id: 0, name: 'Gold'},
                {id: 1, name: 'Titanium'},
                {id: 2, name: 'Silver'}
            ],
        };
    
        const carColor = {
            title: 'Please select car color',
            property: 'carColor',
            options: [
                {id: 0, name: 'Black'},
                {id: 1, name: 'Blue'},
                {id: 2, name: 'Orange'},
                {id: 3, name: 'White'},
                {id: 4, name: 'Yellow'},
                {id: 5, name: 'Green'},
            ],
        };
            
    </script>
    
    //here im passing all of the data to the components itself

    <Carmaterial {...carMaterial} />
    <Carcolor {...carColor}/>
    
    
    <style>
    
    </style>

The components are basically 2 sets of radio inputs:

Carmaterial.svelte

<script>

export let property;
export let title;
export let options;

//im using this in order to predefine value
export let selected = options[1];

</script>
<h3>{title}</h3>
<ul>
{#each options as option (option.id)}

    <li>
        <label>
            <input 
                value={option.id} 
                bind:group={selected.id} 
                type="radio" 
                name={property}>
            {option.name}
        </label>
        
    </li>

{/each}
</ul>

<style lang="scss">

</style>

Carcolor.svelte

<script>
export let property;
export let title;
export let options;

//im using this in order to predefine value
export let selected = options[2];

</script>
<h3>{title}</h3>
<ul>
{#each options as option (option.id)}

    <li>
        <label>
            <input 
                value={option.id} 
                bind:group={selected.id} 
                type="radio" 
                name={property}>
            {option.name}
        </label>
        
    </li>

{/each}
</ul>
<style lang="scss"></style>

in the end my output looks like

h3 with Title
ul li with material options
h3 with Title
ul li with color options

What im trying to achieve is -> I need somehow to disable "Orange" and "White" radio buttons (from carColor group) when "Titanium" material (from carMaterial group) is selected.

Is this possible without using Shop? And if yes, what would be the best solution in case I don't want to messed up my data flow..

Upvotes: 1

Views: 1642

Answers (1)

Stephane Vanraes
Stephane Vanraes

Reputation: 16411

There are basically two ways:

  1. use a store, this would provide a 'shared' place for the components to get their data

  2. move the data to the parent component and pass it on to the children:

<script>
 let selectedMaterial = 'paper';
 let selectedColor = 'orange';
</script>

<Carmaterial {...carMaterial} {selectedColor} bind:selectedMaterial />
<Carcolor {...carColor} {selectedMaterial} bind:selectedColor />

Note that instead of using selected I would be using selectedMaterial and selectedColor in the respective component just to keep it shorter.

The basic principle is easy to understand though: bind the selection from 1 component to the parent, pass this selection to the other component.

You are already keeping the possible data in the parent, this seems like a natural thing to do.

Upvotes: 3

Related Questions