2 ways to pass data into Svelte slots
Tags: svelte, slot, tutorial, beginners
Published: 2021-05-12 06:50:55

---
title: "2 ways to pass data into Svelte slots"
published: true
description: Let's see how we can pass dynamic data to the slotted contents
tags: svelte,slot,tutorial,beginners
series: "Svelte for Beginners"
//cover_image: https://direct_url_to_image.jpg
---

We've learned how to use slot in @sveltejs , now let's see how we can pass dynamic data to the slotted contents

```html
<Component>
  <div>i want {dynamic} {data}!</div>
</Component>
```

---

This article is a summary from my video from the "Svelte 101" series, "Passing data across slot"

If you prefer video, check it out for a detailed walkthrough!

[Watch on YouTube](https://www.youtube.com/watch?v=nm1TW__oFS8)

---

When you use a slot, data in the slotted content can come from 2 components:

1. the current component (A)
2. the component we are using (B)

```html
<!-- filename: A.svelte -->
<B>
  <div>i want {dynamic} {data}!</div>
</B>
```

## 1. Passing data from the current component

Passing data from the current component (A) is what we've always do:

- define the variable in the script tag
- use it

```html
<!-- filename: A.svelte -->
<script>
  let dataFromA = 'dynamic';
</script>

<B>
  <div>i want {dataFromA} {data}!</div>
</B>
```

## 2. Passing data from the component you are using

Passing data from the component (B) however, require us to pass the data as props to the slot

```html
<!-- filename: B.svelte -->
<script>
  let dataFromB = 'data';
</script>

<slot dataFromB={dataFromB} />

<!-- or using shorthand: -->
<slot {dataFromB} />
```

And to receives it, you create what we called a `let:` binding

```html
<!-- filename: A.svelte -->
<script>
  let dataFromA = 'dynamic';
</script>

<B let:dataFromB>
  <div>i want {dataFromA} {dataFromB}!</div>
</B>
```

- You starts with `let:` + props name passed to the slot
- The props name variable will then be available to your slotted content
- The let binding creates a new scope to the elements beneath to access the props variable

You can rename the props name as you need

```html
<!-- filename: A.svelte -->
<script>
  let dataFromA = 'dynamic';
</script>

<B let:dataFromB={somethingElse}>
  <div>i want {dataFromA} {somethingElse}!</div>
</B>
```

This is especially useful when the prop name shadows the variable from the outer scope, and you want to access both the variables:


```html
<!-- filename: A.svelte -->
<script>
  let data = 'from a';
</script>

<B let:data={dataFromB}>
  <div>data from A: {data}</div>
  <div>data from B: {dataFromB}</div>
</B>
```

## Slot props for named slots

Remember named slots?

You can choose to pass different data for different slotted content!

```html
<!-- filename: B.svelte -->
<script>
  let title = "Passing data to slot";
  let content = "Svelte is fun!";
</script>

<slot name="header" {title}  />
<slot name="body" {content} />
```

```html
<!-- filename: A.svelte -->
<B>
  <svelte:fragment slot="header" let:title>
    <h1>{title}</h1>
  </svelte:fragment>
  
  <svelte:fragment slot="body" let:content>
    <div>{content}</div>
  </svelte:fragment>
</B>
```

## Reactive data

Well, the `let:` binding is not 2-way, (not for now 😓)

To pass data back to the component B, you'll need a callback function

```html
<!-- filename: B.svelte -->
<script>
  let dataFromB = 'data';
  
  function updateData(newData) {
    dataFromB = newData;
  }
</script>

<slot {dataFromB} {updateData} />
```

```html
<!-- filename: A.svelte -->
<B let:dataFromB let:updateData>
  <div>i want {dataFromB}!</div>
  <button on:click={() => {
    updateData(123);
  }}>Click Me</button>
</B>
```

Well, an alternative to callback function would be using a store, however using `$` for a store that is not declared at the top-level of the script is not supported yet!

...and the workaround doesn't seem better to me 😓

```html
<!-- filename: A.svelte -->
<B let:dataFromB>
  <!-- ⚠️ Stores must be declared at the top level of the component (this may change in a future version of Svelte) -->
  <div>i want {$dataFromB}!</div>
  <button on:click={() => { $dataFromB = 123; }}>
    Click Me
  </button>
</B>

<!-- Workaround -->
<script>
  import { get } from 'svelte/store';
</script>

<B let:dataFromB>
  <div>i want {get(dataFromB)}!</div>
  <button on:click={() => { dataFromB.set(123); }}>
    Click Me
  </button>
</B>
```

## Reference
- Svelte tutorial: Slot props https://svelte.dev/tutorial/slot-props