romroms
romroms

Reputation: 15

How to change data from layout in page in Svelte 5?

I'm trying to make a login in Svelte 5. I have the request then I redirect to another page, /dashboard.

The problem is: I wanted to show my user data from the login on my navbar above, which is in +layout.svelte.

My last approach was to pass a variable from layout.ts (loggedUser) that in blank initially, and then access it in routes/login/+page.svelte through $bindable, but occurs that the console says

data.loggedUser.username is unreactive

When I put it in a <input bind:value={data.loggedUser.username}>.

And it actually is, debugging with $inspect() the "data" received doesn't change.

<!-- +layout.svelte -->
<script lang="ts">
    import { goto } from "$app/navigation";
    import { jwtDecode } from "jwt-decode";
    import "../app.css";
    import type { Snippet } from "svelte";
    let { data, children }: any = $props();

    function logout() {
        localStorage.setItem("token", " ");
        goto("/")
    }

    //export const ssr = false;
</script>

<nav>
    <a href="/">home</a>
    <span>logado como {data}</span>
    <button onclick={()=>{logout()}}>logout</button>
</nav>

{@render children()}
// +layout.ts (consider `colaboradorLogado` is `loggedUser`)
import type { PageLoad } from "./dashboard/$types";
import type { Colaborador } from "../interfaces/colaborador";
import type { LayoutLoad } from "./$types";

export const ssr = false;

export const load: LayoutLoad = async () =>{
    return {
        colaboradorLogado: {}
    }
}
<!-- routes/login/+page.svelte -->
<script lang="ts">
    import { deserialize } from '$app/forms';
    import { goto } from '$app/navigation';
    import { jwtDecode } from "jwt-decode";
    import type { Colaborador } from '../../interfaces/colaborador';
    import type { JWTToken } from '../../interfaces/jwttoken';

    let {data = $bindable()}: any = $props();
    $inspect(data);
    let formUsername = $state('');
    let formPassword = $state('');

    async function handleSubmit(event: SubmitEvent & { currentTarget: EventTarget & HTMLFormElement}) {
        event.preventDefault();
        const formData = new FormData(event.currentTarget);

        var init = {
            'method':'POST',
            'body':formData
        }
        const response = await fetch('http://localhost:8000/auth/login/', init)

        const result: any = deserialize(await response.text());
        let token = result.access;
        localStorage.setItem("token", token);
        

        let tokenDecoded: JWTToken = jwtDecode(token);
        const colaborador: Colaborador = tokenDecoded.colaborador;
        data.colaboradorLogado = tokenDecoded.colaborador;

        goto("/dashboard");
    }
</script>

<h1>Entrar</h1>
<form onsubmit={handleSubmit}>
    <input type="text" bind:value="{formUsername}" name="username" placeholder="Nome de usuário"><br>
    <input type="password" bind:value="{formPassword}" name="password" id="" placeholder="Senha"><br>
        <button type="submit">Entrar</button>
</form>

<input bind:value={data.colaboradorLogado} type="text" placeholder="colaboradorLogado">

I did read the documentation about $props, layout and so, but didn't find a solution. Maybe it was on my face, maybe there is a simpler way to do what I am trying to.

Upvotes: 0

Views: 53

Answers (0)

Related Questions