Reputation: 510
I am trying to implement in Sapper what is done in the next.js
example called with-route-as-modal.
What it does is that when clicking on a link, the new page is shown in a modal instead of replacing the current page, and the URL is updated, reflecting current modal page. It is implemented in several social networks, such as instagram.
In the next.js
example, it is done by using a dynamic href, like this :
<Link href={`/?postId=${id}`} as={`/post/${id}`}>
How can I implement it in Sapper ?
Thanks for your time.
Upvotes: 6
Views: 820
Reputation: 510
I managed to do it in this way :
<script>
import { prefetch } from '@sapper/app'
import { onMount, onDestroy } from 'svelte'
import Post from '../components/Post.svelte'
let props
onMount(() => {
window.onpopstate = function (event) {
if (document.location.pathname === '/about') {
props = null
} else {
const regex = /\/blog\/([\w-]+)/
if (regex.test(document.location.pathname)) {
handlePrefetch(document.location.pathname)
}
}
}
return () => {
window.onpopstate = null
}
})
function handleClick(event) {
event.preventDefault()
const clickedHref = event.currentTarget.href
if (clickedHref === location.href) return
const pathname = clickedHref.replace(location.origin, '').substring(1)
history.pushState(null, '', pathname)
handlePrefetch(pathname)
}
async function handlePrefetch(url) {
const res = await prefetch(url)
const { branch } = res
props = branch[1].props.post
}
function handleClose() {
history.pushState(null, '', 'about')
props = null
}
</script>
<svelte:head>
<title>About</title>
</svelte:head>
<h1>About this site</h1>
<p>This is the 'about' page. There's not much here.</p>
<a href="/blog/what-is-sapper" on:click="{handleClick}">lien ici</a>
{#if props}
<Post title="{props.title}" html="{props.html}"></Post>
<button on:click="{handleClose}"></button>
{/if}
I had to handle the pop state event manually (so that back button still works). I then used sapper prefetch
function and inject resulting props as local props. Then I check if any props are set, and then inject custom HTML depending on it.
The "real page" is just a sapper component that contains <Post title={post.title} html={post.html} />
Upvotes: 1