Navigation
Most navigation is a plain link.
JAF intercepts links to your own pages and swaps the content in place, so nothing reloads:
<script>
let userId = 123
</script>
<a href="/">Home</a>
<a href="/about">About</a>
<a href="/users/{userId}">My profile</a>
Links JAF leaves alone
Anything that is not an internal page navigation goes to the browser
untouched: another origin, a mailto: or tel:, a
target, a download, or a click with Cmd, Ctrl, Shift
or Alt held.
Three attributes opt a link out by hand:
| Attribute | Why you would use it |
|---|---|
rel="external" |
A path on this domain that another application serves. The request has to reach the server. |
data-native |
The same thing, spelled JAF's way. |
download |
Already left alone - the browser saves the file. |
Links to other origins also get rel="noopener" added for you, so
the page you open cannot reach back through window.opener.
Highlighting the current link
You do not have to compare paths.
JAF puts aria-current="page" on every link whose
href is the current route, and takes it off again when you leave.
Style that:
<nav class="nav-demo">
<a href="/docs/routing/files">Files</a>
<a href="/docs/routing/navigation">Navigation</a>
<a href="/docs/routing/guards">Guards</a>
</nav>
<style>
.nav-demo {
display: flex;
gap: 1rem;
}
.nav-demo a {
color: var(--text-secondary);
text-decoration: none;
}
.nav-demo a[aria-current="page"] {
color: var(--accent);
font-weight: 600;
}
</style>
Add data-active-prefix to a link and it counts as current for
everything below it too, which is what a top-level nav item usually wants:
<a href="/docs" data-active-prefix> stays lit on
/docs/routing/files.
Navigating from code
navigate() lives on the jafjs/router subpath and
takes a path:
<script>
import { navigate } from 'jafjs/router'
async function save() {
await saveDraft()
navigate('/thanks')
}
function signIn() {
// replace: the Back button skips the sign-in page
navigate('/dashboard', { replace: true })
}
</script>
<button onclick="save()">Save</button>
Pass { replace: true } to overwrite the current history entry
instead of adding one.
To go back, use the platform: history.back().
Passing data to the next page
Hand navigate() a data payload:
<script>
import { navigate } from 'jafjs/router'
function viewUser(user) {
navigate('/users/' + user.id, { data: { user } })
}
</script>
<button onclick="viewUser({ id: 123, name: 'Alice' })">View Alice</button>
The destination reads it from window.route.data:
<!-- pages/users/[id].html -->
<script>
const user = window.route.data?.user
const userId = window.route.params.id
</script>
<h1>{user?.name}</h1>
<p>User {userId}</p>
route.data undefined. Treat it as a shortcut, and make sure the
page can still fetch what it needs from the URL.
Where you are now
window.route is reactive and holds path,
params, query, hash,
name and data:
<script>
// Visiting /users/123?tab=settings
const currentPath = window.route.path // '/users/123'
const userId = window.route.params.id // '123'
const tab = window.route.query.tab // 'settings'
</script>
<p>{currentPath} - user {userId}, tab {tab}</p>
ui.page is deprecated. It was a second
navigation API over this one and is removed in v0.2.
ui.page.open(path, data) becomes
navigate(path, { data }), and
ui.page.close() becomes history.back(). See
Overlays & UI State.
Related
-
Dynamic Routes - reading
route.params - Route Guards - redirecting a visitor who should not be here