Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
<script>
let { children } = $props();
</script>

<nav>
<a href="/">home</a>
<a href="/about">about</a>
</nav>

<slot />
{@render children()}
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,20 @@ src/routes/
└ +page.svelte
```

...and move the duplicated content from the `+page.svelte` files into the new `+layout.svelte` file. The `<slot></slot>` element is where the page content will be rendered:
...and move the duplicated content from the `+page.svelte` files into the new `+layout.svelte` file. The `{@render children()}` tag is where the page content will be rendered:

```svelte
/// file: src/routes/+layout.svelte
<script>
let { children } = $props();
</script>

<nav>
<a href="/">home</a>
<a href="/about">about</a>
</nav>

<slot></slot>
{@render children()}
```

A `+layout.svelte` file applies to every child route, including the sibling `+page.svelte` (if it exists). You can nest layouts to arbitrary depth.
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
<script>
let { children } = $props();
</script>

<nav>
<a href="/">home</a>
<a href="/blog">blog</a>
</nav>

<slot />
{@render children()}
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
<script>
let { children } = $props();
</script>

<nav>
<a href="/">home</a>
<a href="/blog">blog</a>
</nav>

<slot />
{@render children()}
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
<script>
export let data;
let { data, children } = $props();
</script>

<div class="layout">
<main>
<slot />
{@render children()}
</main>
</div>

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<script>
export let data;
let { data } = $props();
</script>

<h1>blog</h1>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { posts } from '../data.js';
export function load({ params }) {
const post = posts.find((post) => post.slug === params.slug);

if (!post) throw error(404);
if (!post) error(404);

return {
post
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<script>
export let data;
let { data } = $props();
</script>

<h1>{data.post.title}</h1>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ We can access this data in `src/routes/blog/+page.svelte` via the `data` prop:
```svelte
/// file: src/routes/blog/+page.svelte
+++<script>
export let data;
let { data } = $props();
</script>+++

<h1>blog</h1>
Expand Down Expand Up @@ -67,7 +67,7 @@ export function load({ params }) {
```svelte
/// file: src/routes/blog/[slug]/+page.svelte
+++<script>
export let data;
let { data } = $props();
</script>+++

---<h1>blog post</h1>---
Expand All @@ -85,7 +85,7 @@ import { posts } from '../data.js';
export function load({ params }) {
const post = posts.find((post) => post.slug === params.slug);

+++if (!post) throw error(404);+++
+++if (!post) error(404);+++

return {
post
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
<script>
export let data;
let { data, children } = $props();
</script>

<div class="layout">
<main>
<slot />
{@render children()}
</main>

<aside>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,12 @@ Now, add a sidebar in the layout for the post page:
```svelte
/// file: src/routes/blog/[slug]/+layout.svelte
<script>
export let data;
let { data, children } = $props();
</script>

<div class="layout">
<main>
<slot></slot>
{@render children()}
</main>

+++ <aside>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<script>
export let data;
let { data } = $props();
</script>

<h1>Hello {data.visited ? 'friend' : 'stranger'}!</h1>
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
<script>
let { children } = $props();
</script>

<nav>
<a href="/">home</a>
<a href="/a/deeply/nested/route">a deeply nested route</a>
</nav>

<slot />
{@render children()}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<script>
export let data;
let { data } = $props();
</script>

<div class="centered">
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<script>
export let data;
let { data } = $props();
</script>

<div class="centered">
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<script>
export let data;
let { data } = $props();
</script>

<div class="centered">
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
<script>
export let data;
export let form;
let { data, form } = $props();
</script>

<div class="centered">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,8 +78,7 @@ In `src/routes/+page.svelte`, we can access the returned value via the `form` pr
```svelte
/// file: src/routes/+page.svelte
<script>
export let data;
+++export let form;+++
let { data, +++form+++ } = $props();
</script>

<div class="centered">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,7 @@
import { fly, slide } from 'svelte/transition';
import { enhance } from '$app/forms';

export let data;
export let form;
let { data, form } = $props();
</script>

<div class="centered">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,7 @@ Import the `enhance` function from `$app/forms`...
<script>
+++import { enhance } from '$app/forms';+++

export let data;
export let form;
let { data, form } = $props();
</script>
```

Expand Down Expand Up @@ -45,8 +44,7 @@ Now that we're updating the page rather than reloading it, we can get fancy with
+++import { fly, slide } from 'svelte/transition';+++
import { enhance } from '$app/forms';

export let data;
export let form;
let { data, form } = $props();
</script>
```

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,10 @@
import { fly, slide } from 'svelte/transition';
import { enhance } from '$app/forms';

export let data;
export let form;
let { data, form } = $props();

let creating = false;
let deleting = [];
let creating = $state(false);
let deleting = $state([]);
</script>

<div class="centered">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,10 @@ When we create or delete items, it now takes a full second before the UI updates
import { fly, slide } from 'svelte/transition';
import { enhance } from '$app/forms';

export let data;
export let form;
let { data, form } = $props();

+++ let creating = false;
let deleting = [];+++
+++ let creating = $state(false);
let deleting = $state([]);+++
</script>
```

Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
<script>
/** @type {number} */
let number;
let number = $state();

async function roll() {
const response = await fetch('/roll');
number = await response.json();
}
</script>

<button on:click={roll}>Roll the dice</button>
<button onclick={roll}>Roll the dice</button>

{#if number !== undefined}
<p>You rolled a {number}</p>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<script>
export let data;
let { data } = $props();
</script>

<div class="centered">
Expand All @@ -10,7 +10,7 @@
<input
type="text"
autocomplete="off"
on:keydown={async (e) => {
onkeydown={async (e) => {
if (e.key !== 'Enter') return;

const input = e.currentTarget;
Expand All @@ -30,7 +30,7 @@
<input
type="checkbox"
checked={todo.done}
on:change={async (e) => {
onchange={async (e) => {
const done = e.currentTarget.checked;

// TODO handle change
Expand All @@ -39,7 +39,7 @@
<span>{todo.description}</span>
<button
aria-label="Mark as complete"
on:click={async (e) => {
onclick={async (e) => {
// TODO handle delete
}}
></button>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<script>
export let data;
let { data = $bindable() } = $props();
</script>

<div class="centered">
Expand All @@ -10,7 +10,7 @@
<input
type="text"
autocomplete="off"
on:keydown={async (e) => {
onkeydown={async (e) => {
if (e.key !== 'Enter') return;

const input = e.currentTarget;
Expand Down Expand Up @@ -43,7 +43,7 @@
<input
type="checkbox"
checked={todo.done}
on:change={async (e) => {
onchange={async (e) => {
const done = e.currentTarget.checked;

// TODO handle change
Expand All @@ -52,7 +52,7 @@
<span>{todo.description}</span>
<button
aria-label="Mark as complete"
on:click={async (e) => {
onclick={async (e) => {
// TODO handle delete
}}
></button>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ Inside the `keydown` event handler of the 'add a todo' `<input>`, let's post som
<input
type="text"
autocomplete="off"
on:keydown={async (e) => {
onkeydown={async (e) => {
if (e.key !== 'Enter') return;

const input = e.currentTarget;
Expand Down Expand Up @@ -58,7 +58,7 @@ We're returning a response with a [201 Created](https://http.dog/201) status and
<input
type="text"
autocomplete="off"
on:keydown={async (e) => {
onkeydown={async (e) => {
if (e.key !== 'Enter') return;

const input = e.currentTarget;
Expand Down
Loading
Loading