wire:navigate
The wire:navigate
directive provides SPA-like page navigation by intercepting link clicks and loading pages in the background. Instead of full page refreshes, Livewire fetches new content and swaps it seamlessly, resulting in faster navigation and a smoother user experience.
Basic Usage
This navigation example demonstrates wire:navigate
with hover prefetching and redirect functionality:
// wires/BlogPost.bx
class extends="cbwire.models.Component" {
data = {
"title": "",
"content": ""
};
function save() {
// Save blog post
redirect("/blog", true); // Navigate using wire:navigate
}
function cancel() {
redirect("/blog", true);
}
}
<!-- layouts/Main.bxm -->
<bx:output>
<nav>
<a href="/" wire:navigate>Dashboard</a>
<a href="/blog" wire:navigate.hover>Blog</a>
<a href="/users" wire:navigate>Users</a>
</nav>
<!-- Persisted audio player -->
<div x-persist="player">
<audio src="#episode.file#" controls></audio>
</div>
<main>
#wire("BlogPost")#
</main>
</bx:output>
What wire:navigate Does
When you add wire:navigate
to a link, CBWIRE automatically:
Intercepts Clicks: Prevents browser from performing full page visits
Background Fetching: Requests new page content via AJAX with loading indicator
Seamless Swapping: Replaces URL,
<title>
, and<body>
content without refreshPerformance Boost: Often achieves 2x faster page loads than traditional navigation
Available Modifiers
The wire:navigate
directive supports one modifier:
Hover:
.hover
- Prefetches page content when user hovers over link for 60ms
Example: wire:navigate.hover
improves perceived performance but increases server usage.
Navigation Process
Here's what happens during navigation:
User clicks a
wire:navigate
linkLivewire prevents default browser navigation
Loading bar appears at top of page
Page content is fetched in background
New content replaces current page seamlessly
Redirecting with Navigation
Use CBWIRE's redirect()
method with navigation enabled:
function submit() {
redirect("/thank-you", true); // Second parameter enables wire:navigate
}
Persisting Elements Across Pages
Use Alpine's x-persist
to maintain elements like audio/video players:
<!-- layouts/Main.bxm -->
<bx:output>
<div x-persist="player">
<audio src="#episode.file#" controls></audio>
</div>
<div x-persist="chat">
<div class="chat-widget">Live chat...</div>
</div>
</bx:output>
Preserving Scroll Position
Livewire preserves page scroll by default. For specific elements, use wire:scroll
:
<div x-persist="scrollbar">
<div class="overflow-y-scroll" wire:scroll>
<!-- Long scrollable content -->
</div>
</div>
JavaScript Hooks
Navigation triggers three lifecycle events:
document.addEventListener('livewire:navigate', (event) => {
// Triggered when navigation starts
// Can prevent navigation: event.preventDefault()
let context = event.detail;
context.url; // URL object of destination
context.history; // True if back/forward navigation
context.cached; // True if cached version exists
});
document.addEventListener('livewire:navigating', () => {
// Triggered before HTML swap
// Good place to mutate HTML before navigation
});
document.addEventListener('livewire:navigated', () => {
// Triggered after navigation completes
// Use instead of DOMContentLoaded
});
Manual Navigation
Trigger navigation programmatically:
Livewire.navigate('/new/url');
Event Listeners
Handle persistent event listeners properly:
// Run once per navigation
document.addEventListener('livewire:navigated', () => {
// Page-specific code
}, { once: true });
// Persistent across navigations
document.addEventListener('livewire:navigated', () => {
// Global code
});
Analytics Integration
Ensure analytics track navigation properly:
<script src="https://cdn.usefathom.com/script.js"
data-site="ABCDEFG"
data-spa="auto"
defer></script>
Script Handling
Control script execution across navigations:
<head>
<!-- Cache-busted scripts with tracking -->
<script src="/app.js?id=123" data-navigate-track></script>
</head>
<body>
<!-- Run only once -->
<script data-navigate-once>
console.log('Runs only on first evaluation');
</script>
</body>
Progress Bar Customization
Configure the loading indicator:
// config/ColdBox.bx
moduleSettings = {
"cbwire": {
"showProgressBar": true,
"progressBarColor": "##2299dd"
}
};
Custom Loader Example
Create a custom progress indicator:
<script>
document.addEventListener('livewire:navigate', (event) => {
if (!window.navigating) {
window.navigating = true;
event.preventDefault();
let target = event.detail;
// Show custom loader
let loader = document.createElement('div');
loader.className = 'spinner-border text-primary';
loader.setAttribute('role', 'status');
loader.innerHTML = '<span class="visually-hidden">Loading...</span>';
document.getElementById('content').appendChild(loader);
Livewire.navigate(target.url.pathname);
}
}, { once: true });
document.addEventListener('livewire:navigated', () => {
window.navigating = false;
});
</script>
wire:navigate
often provides 2x faster page loads and creates a JavaScript SPA-like experience while maintaining server-side rendering benefits.
Prefetching with .hover
increases server usage. Use judiciously on high-traffic sites.
Last updated
Was this helpful?