So I can't figure a way to pass a variable up in my __layout
variable from the component displayed in the <slot>
.
I tried a few things, using bind:
or let:
on the slot but it doesn't work. I get 'myvar' is not a valid binding
or <slot> cannot have directives
.
I also tried to export or not the variable on the layout, but I really cannot make it work...
Here is what I have:
<!-- __layout.svelte -->
<script>
export let myvar = undefined;
</script>
<main>
<slot myvar={myvar}></slot>
<p>Layout myvar: {myvar}</p> <!-- << This will stay undefined -->
</main>
<!-- mypage.svelte -->
<script>
import MyComponent from "$lib/my_component.svelte";
export let myvar;
let a_list_of_things = [1,2,3,4]
</script>
<main>
{#each a_list_of_things as thing}
<MyComponent bind:myvar={myvar} thing={thing}/> <!-- The variable is binded here -->
{/each}
<p>mypage myvar: {myvar}</p> <!-- << This will get the good value -->
</main>
<!-- my_component.svelte -->
<script>
import IconButton from '@smui/icon-button'
export let myvar;
export let thing;
</script>
<div>
<IconButton class="material-icons" on:click={() => myvar='something'} >
autorenew
</IconButton> <!-- << We change the value on:click here -->
</div>
So the main goal is to have an equivalent to bind:myvar=myvar
on the layout level (for the <slot></slot>
.
I tried understanding the documentation about it without much success, it seems to be more about the component slot than the layout one.
I found this other question which advise to use a store in sapper (the old name for sveltekit) not sure it is up to date with the last version of sveltekit, is this the way to go ? Or is there another way ?
Someone else advise using a context. What do you think ?
Why do i need this ?
So I have the structure of my app like this:
__layout
├─ header (menu)
├─ my_page (<slot>)
│ └ my_component (many)
└ interactive banner
That display it like so:
[ Header Menu ]
Content of the page
- component 1
- component 2
- component n
[ Current component: 2 ] << Updated when click on an elem in the component
The component
define what the interactive banner should display. Also clicking on the interactive banner
can change the state displayed in the components
Since this banner message seems to be a piece of global state, a store would be a good solution here. Context would only be necessary if you need to have different banners for different component trees on the page.
Something like this would work:
// src/lib/message.js
import { writable } from 'svelte/store';
export default writable('Default message');
<!-- src/routes/__layout.svelte -->
<script>
import message from '$lib/message';
</script>
<slot />
<p>{$message}</p>
<!-- src/routes/index.svelte -->
<script>
import message from '$lib/message';
function update() {
$message = 'New message';
}
</script>
<h1>Hello World</h1>
<button on:click={update}>Update message</button>