4

How to pass data (ex: Navbar Title) to a component used in the parent element?

<!-- _layout.svelte -->
<script>
  import Nav from "../components/Nav.svelte";
  let navTitle = "MyApp";
</script>

<Nav {navTitle}/>
<slot />
<!-- Nav.svelte -->
<script>
  export let navTitle = "";
</script>
<h1>{navTitle}</h1>
<!-- Login.svelte -->
How to pass navTitle value from here to Nav.svelte?

To clarify, this needs to be scalable and to work on page load/transition for all routes of an SPA using Routify, preferably providing a default value and be able to have HTML value:

<!-- Article.svelte -->
<!-- User.svelte -->
navTitle is '<a href="/user">My Account </a>'
<!-- Comment.svelte -->
user2670914
  • 45
  • 1
  • 4

3 Answers3

7

The easiest way to share data across components is to use stores as described in the docs

Your setup for that would be

<!-- Nav.svelte -->
<script>
  import { navTitle } from './store.js'
</script>
<h1>{$navTitle}</h1>
<!-- Login.svelte -->
<script>
  import { navTitle } from './store.js'

  navTitle.set('...')
</script>
<!-- store.js -->
import { writable } from 'svelte/store'

export const navTitle = writable('')
user2670914
  • 45
  • 1
  • 4
Stephane Vanraes
  • 14,343
  • 2
  • 23
  • 41
  • Thank you for the answer, @stephane. I updated the question to clarify scalability and default values issues. Would you make any updates to your suggestion? For example, Routify allows to set metatag.title on pages by simply using `$: metatags.title = "Log in";` – user2670914 Aug 30 '20 at 14:30
  • You can import _navTitle_ wherever in your app you want to be able to set it and then set it similar to how you set it in Routify – Stephane Vanraes Aug 30 '20 at 15:23
  • $navTitle seems to be escaping HTML and only showing text. Is there a way to pass HTML to it? – user2670914 Aug 30 '20 at 15:50
  • Svelte automatically escapes texts, if you want to override this you can use `{@html $navTitle}` but when doing that you have to make sure it is always safe to do so (outputting unescaped html can be a source for XSS) – Stephane Vanraes Aug 30 '20 at 15:53
0

You can pass a function to Login.svelte component

<script>
  import Nav from "./Nav.svelte";
  import Login from "./Login.svelte"
  let navTitle = "MyApp";
  const onlogin= (v)=>navTitle = v
</script>
<Login {onlogin}/>
<Nav {navTitle}/>

And call the passed function in the Login.svelte

<script>
export let onlogin
</script>

<p on:click={()=>onlogin("Logged in")}>
  click me to login
</p>

Here is the REPL: https://svelte.dev/repl/f1c8777df93f414ab26734013f2c4789?version=3

There are other (better) ways to do this like:

  • Custom events with createEventDispatcher
  • Stores
  • Context (setContext, getContext)
  • Multiple Redux-adaptations for svelte
grohjy
  • 2,059
  • 1
  • 18
  • 19
  • You can use also two-way binding for this, but it should be avoided (you’ll mess your dataflow pretty quickly). In App.svelte `` and in Login.svelte `export let navTitle` and `

    navTitle=("Logged in")}>` Key-word is `bind:`, which makes two-way binding to `navTitle` variable ie. when variable changes in one place, it’ll change also other places.

    – grohjy Aug 30 '20 at 04:49
0

Check out this example in case you need to communicate between sibling elements but you need the shared data to be specific to each group of sibling components.

Ac Hybl
  • 397
  • 3
  • 10