16

I have a page that has a nav bar with a "Quarters" link. Under the Quarters link, when the user is on the /quarters route, a list of quarters will be shown, like 2019Q2 etc. The url will be /quarters/2019q2.

I want to make a component that show shows a hyperlink that will have the selected class if the current url matches the href of the link. Here's the closest I can get:

<script> import { afterUpdate } from 'svelte'; export let segment; export let text = 'text here'; export let link; let isCurrentPath = false; console.log(segment, link, text); afterUpdate(() => { if (window.location.pathname.includes(link)) { isCurrentPath = true; debugger; } console.log('HL afterUpdate ', window.location); }); </script> <style> /* omitted */ </style> <a class:selected={segment && isCurrentPath} href={link}>{text}</a> 

That works fine for the first load, but when the user navigates to a different data page the selection is not updated. How do I get some code to only run on the client-side? If I access the window object outside of afterUpdate I will get an null ref error from the server-side code.

ETA: Tried this too:

 let isCurrentPath = false; let path = typeof window === 'undefined' ? '' : window.location.pathname; $: if (path) isCurrentPath = window.location.pathname.includes(link); 

That code doesn't fire when the user clicks one of the data links. Tried onMount as well with no positive result.

0

3 Answers 3

14

For people using SvelteKit, the given answers still apply. Take a look at the docs for the page store: https://svelte.dev/docs/kit/$app-stores#page

EDIT: There were breaking changes in a new SvelteKit update. You still access the current url from the page store like this:

<script> import { page } from '$app/stores'; </script> <h1>{$page.url.pathname}</h1> 

EDIT 2: $app/stores is deprecated since SvelteKit 2.12 (Svelte 5) and subject to be removed in SvelteKit 3, use $app/state instead:

<script> import { page } from '$app/state'; // replace $app/stores with $app/state let longTitle = $derived(page.url.pathname.length > 20 ? true : false); // remove $ from $page </script> 
Sign up to request clarification or add additional context in comments.

2 Comments

can you provide example? the docs are useless.
@chovy Actually I think they're pretty good. But here you go: Import the store this way: import { page } from '$app/stores'; and then use it like this: {#if $page.path == '/some/route'}
12

The trick is to create a reactive statement based on a value in the page store.

<!-- This is used to have a link on the page that will show highlighted if the url meets the criteria. You might want to adjust the logic on line 19. usage: <HighlightedLink bind:segment highlight="faq" rel="prefetch" link="/faq" text="FAQ" /> --> <script> import { stores } from '@sapper/app'; const { page } = stores(); export let highlight; export let segment; export let text = 'text here'; export let link; export let target; let highlightPath = false; $: highlightPath = $page.path && highlight && ($page.path.includes(highlight) || $page.path.includes(link)); </script> <style> .selected { position: relative; display: inline-block; } .selected::after { position: absolute; content: ''; width: calc(100% - 1em); height: 2px; background-color: rgb(255, 62, 0); display: block; bottom: -1px; } a { padding-left: 10px; } </style> <a class:selected={highlightPath} href={link}>{text}</a> 

Comments

1

instead of using afterUpdate I believe you should look in to writing something with onMount and use reactive statements https://svelte.dev/examples#reactive-statements to let svelte know that you want to recalculate isCurrentPath whenever location changes.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.