I have a +layout.server.ts
that performs an API request and returns the data to its sibling +layout.svelte
. Since this request can take a second or two, it's value is inside an await
block in my Svelte code so I can display a loading indicator.
This all works fine, however I am now trying to set the title of the page to a value contained in the resolved promise and am hitting a wall. I cannot place await
blocks in the <title>
tag and I cannot modify state from within Svelte code directly so is there a possible way of achieving this?
My code for reference:
+layout.server.ts
:
import type { LayoutServerLoad } from "./$types";
import { getPlayer } from "$lib/utils";
export const load: LayoutServerLoad = async ({ params }) => {
return {
streamed: {
player: getPlayer(params.username)
}
};
}
+layout.svelte
(this is where I am hitting the wall the wall)
<script lang="ts">
import Header from "$lib/blocks/Header.svelte";
import type { LayoutProps } from "./$types";
let { data, children }: LayoutProps = $props();
let title = $state("Loading...");
function setTitle(newTitle: string) { title = newTitle; console.log(newTitle); }
</script>
<svelte:head>
<title>{title}</title>
</svelte:head>
<div>
<Header />
<div>
{#await data.streamed.player}
<p>Loading...</p>
{:then player}
{setTitle(player?.username || "Player not found!")}
<p>{player?.username}</p>
{:catch error}
{setTitle("Player not found!")}
<p>Problem loading player data!</p>
{/await}
</div>
{@render children()}
</div>
I might have misunderstood, but can't you simple use {#await}
two times on the same promise?
<svelte:head>
{#await data.streamed.player}
<title>Loading...</title>
{:then player}
<title>{player?.username ?? "Player not found!"}</title>
{:catch error}
<title>Player not found!</title>
{/await}
</svelte:head>
<div>
<Header />
<div>
{#await data.streamed.player}
<p>Loading...</p>
{:then player}
<p>{player?.username}</p>
{:catch error}
<p>Problem loading player data!</p>
{/await}
</div>
{@render children()}
</div>