Reputation: 652
I have to following folder structure and I'm struggling to find the best way to provide my main layout with some props.
src/
└── routes/
└── (app)/
├── route1/
│ └── +page.svelte
├── route2/
│ └── +page.svelte
└── +layout.svelte
To have more context, the main layout has a Sidebar menu component that needs a list of elements to render based on the selected route. So I need to find a way to communicate and change the props of one component in the main layout from any route.
I tried using slots and send the complete Sidebar as a slot for the main layout using a route layout but it didn't work. As far as I later understood, each layout can only have one main slot. I also tried to investigate if I can use a Global State somehow for this implementation but it feels way too complicated for what I'm trying to do.
Upvotes: 1
Views: 1126
Reputation: 1
As of 2025, Svelte 5 and Kit 2.12, you can use page, from "$app/state" to do this.
In "route1/+page.js" return the data you want to display in your Sidebar component, for example:
export const load = (async () => {
return {
navItems: ["Home", "Profile", "Settings"],
};
}) satisfies PageLoad;
Then in "(app)/+layout.svelte" access the data via:
import { page } from '$app/state';
<Sidenav items={page.data.navItems} ></Sidenav>
This works wherever you can add data to a page, such as +page.server.js, and the layout variants and as they state in the docs, you can import from $app/state directly in a component as well, because it is independent of your folder structure. The available data depends on the inheritance logic of the current route of course.
Upvotes: 0
Reputation: 16451
If you only have to provide data and don't need to change anything while on the page you can also opt for using the load function.
in /route1/+page.ts
you would then have
export async function load() {
return {
sidebar: [1,2,3]
}
}
and in the layout.svelte
{#each $page.data.sidebar ?? [] as item}
<p>{item}</p>
{/each}
$page
is a store that holds among other things all the data returned from the load functions, so it will automatically update when going from one page to another, you could also do this in a Sidebar.svelte component instead of the layout of course.
Upvotes: 5
Reputation: 185280
Would possibly use a context for that, set it in the layout and interact with it in the route. Put in a store to make data reactive or a function that acts like a callback. E.g.
let selectedItem;
setContext('nav-context', {
setSelected(value) { selectedItem = value }
});
Upvotes: 1