Router API
Client-side routing for single-page applications.
Quick Reference
wildflower.createRouter()
Create and configure the application router.
Signature
wildflower.createRouter(config: RouterConfig): Router
Config Options
| Option | Type | Default | Description |
|---|---|---|---|
mode |
'hash' | 'history' |
'hash' |
URL handling mode |
routes |
RouteConfig[] |
[] |
Route definitions |
defaultRoute |
string |
'/' |
Fallback route path |
scrollBehavior |
function |
- | Custom scroll handling |
viewTransitions |
boolean |
false |
Enable View Transitions API for animated page changes |
Example
const router = wildflower.createRouter({
mode: 'history',
routes: [
{ path: '/', component: 'home-page' },
{ path: '/about', component: 'about-page' },
{ path: '/users/:id', component: 'user-profile' },
{ path: '/products', component: 'product-list' },
{ path: '*', component: 'not-found' }
]
});
// Router is automatically initialized: no separate init() call needed
Route Configuration
Each route is an object with these properties:
RouteConfig
| Property | Type | Description |
|---|---|---|
path |
string |
URL path pattern |
component |
string |
Component name to render |
name |
string |
Named route for programmatic navigation |
meta |
object |
Custom route metadata |
beforeEnter |
function |
Route-specific guard, runs before entering this route |
beforeLeave |
function |
Route-specific guard, runs before leaving this route |
children |
RouteConfig[] |
Nested route definitions |
Path Patterns
const routes = [
// Static path
{ path: '/about', component: 'about-page' },
// Dynamic parameter
{ path: '/users/:id', component: 'user-profile' },
// Multiple parameters
{ path: '/posts/:category/:slug', component: 'blog-post' },
// Optional parameter
{ path: '/search/:query?', component: 'search-results' },
// Wildcard (catch-all)
{ path: '*', component: 'not-found' }
];
History Modes
Hash Mode (Default)
Uses URL hash for navigation. Works without server configuration.
// URLs like: example.com/#/users/123
wildflower.createRouter({
mode: 'hash',
routes: [...]
});
History Mode
Uses real URLs via History API. Requires server-side fallback configuration.
// URLs like: example.com/users/123
wildflower.createRouter({
mode: 'history',
routes: [...]
});
Route Parameters
Access dynamic route parameters in your components.
Accessing Parameters
// Route: /users/:id
wildflower.component('user-profile', {
state: {
user: null,
loading: true
},
async init() {
// Access route params via the router
const params = window.router.currentRoute.params;
const userId = params.id;
// Fetch user data
const response = await fetch(`/api/users/${userId}`);
this.user = await response.json();
this.loading = false;
}
});
Multiple Parameters
// Route: /posts/:category/:slug
wildflower.component('blog-post', {
init() {
const { category, slug } = window.router.currentRoute.params;
console.log(`Loading post: ${category}/${slug}`);
}
});
Query Strings
Access and manipulate URL query parameters.
Reading Query Parameters
// URL: /search?q=wildflower&page=2
wildflower.component('search-results', {
init() {
const query = window.router.currentRoute.query;
console.log(query.q); // 'wildflower'
console.log(query.page); // '2'
this.searchTerm = query.q || '';
this.page = parseInt(query.page) || 1;
}
});
Navigating with Query Parameters
// Add query parameters to navigation
router.navigate('/search', {
query: {
q: 'framework',
category: 'javascript',
page: 1
}
});
// Results in: /search?q=framework&category=javascript&page=1
router.getRouteUrl()
Generate a URL string for a named route without navigating. Useful for building href attributes or constructing URLs programmatically.
Signature
router.getRouteUrl(name: string, params?: object, query?: object, hash?: string): string
Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
name |
string |
- | The name of the route (as defined in route configuration) |
params |
object |
{} |
Route parameters to fill in dynamic segments |
query |
object |
{} |
Query parameters to append as a query string |
hash |
string |
'' |
Hash fragment to append (with or without leading #) |
Returns
A URL string. Returns '/' if the named route is not found (and logs an error).
Example
const router = wildflower.createRouter({
routes: [
{ path: '/users/:id', name: 'user-profile', component: 'user-profile' },
{ path: '/search/:query?', name: 'search', component: 'search-results' }
]
});
// Basic URL generation
router.getRouteUrl('user-profile', { id: 42 });
// => '/users/42'
// With query parameters
router.getRouteUrl('search', { query: 'wildflower' }, { page: 2 });
// => '/search/wildflower?page=2'
// Optional parameters are omitted when not provided
router.getRouteUrl('search');
// => '/search'
// With hash fragment
router.getRouteUrl('user-profile', { id: 42 }, {}, 'bio');
// => '/users/42#bio'
Route Guards
Control navigation based on conditions (authentication, permissions, etc.). Guards use a return-based API: return a value to control navigation, no callback needed.
Global Guards
const router = wildflower.createRouter({
routes: [...]
});
// Before each route change: return-based
router.beforeEach(({ to, from }) => {
const isAuthenticated = wildflower.getStore('auth').isLoggedIn;
if (to.meta.requiresAuth && !isAuthenticated) {
return '/login'; // Redirect
}
// Return nothing = allow navigation
});
// After each route change
router.afterEach(({ to, from }) => {
// Analytics, scroll position, etc.
analytics.pageView(to.path);
});
Per-Route Guards
const routes = [
{
path: '/admin',
component: 'admin-dashboard',
meta: { requiresAuth: true, requiresAdmin: true },
beforeEnter: ({ to, from }) => {
const user = wildflower.getStore('auth').user;
if (!user || !user.isAdmin) {
return '/unauthorized'; // Redirect
}
// Return nothing = allow
}
},
{
path: '/editor',
component: 'document-editor',
beforeLeave: ({ to, from }) => {
const editor = wildflower.getStore('editor');
if (editor.hasUnsavedChanges) {
return false; // Cancel navigation
}
// Return nothing = allow
}
}
];
Guard Return Values
| Return Value | Effect |
|---|---|
undefined / true |
Allow navigation |
'/path' (string) |
Redirect to path |
{ path: '/path', query?: {...} } |
Redirect to path with optional query parameters |
false |
Cancel navigation |
Lifecycle Hooks
Hook into the navigation lifecycle.
Router Hooks
const router = wildflower.createRouter({ routes: [...] });
// Before navigation: return-based guard
router.beforeEach(({ to, from }) => {
console.log('Navigating from', from.path, 'to', to.path);
// Return nothing = allow
});
// After navigation completes
router.afterEach(({ to, from }) => {
console.log('Navigation complete');
});
// Navigation errors: listen via DOM event
document.addEventListener('route:error', (e) => {
console.error('Navigation failed:', e.detail.error);
});
Component Route Hook
Components can respond to route changes via onRouteChange:
wildflower.component('dashboard', {
// Called after navigation completes and this component is active
onRouteChange(to, from) {
console.log('Route changed to', to.path);
// Refresh data, update UI, etc.
}
});
DOM Events
The router dispatches CustomEvents on document for external integration:
| Event | When | Cancelable |
|---|---|---|
route:beforeChange | Before navigation starts | Yes |
route:afterChange | After navigation completes | No |
route:redirect | When a redirect occurs | No |
route:error | On navigation error | No |
route:notFound | When no route matches | No |
Nested Routes
Define child routes for nested views.
Configuration
const routes = [
{
path: '/users/:id',
component: 'user-layout',
children: [
// /users/:id/profile
{ path: 'profile', component: 'user-profile' },
// /users/:id/posts
{ path: 'posts', component: 'user-posts' },
// /users/:id/settings
{ path: 'settings', component: 'user-settings' }
]
}
];
Parent Component
<!-- user-layout component provides the wrapper -->
<div data-component="user-layout">
<nav>
<a href="/users/123/profile">Profile</a>
<a href="/users/123/posts">Posts</a>
<a href="/users/123/settings">Settings</a>
</nav>
<!-- Child route components render here -->
<div data-router-view></div>
</div>
Router Instance
Properties and methods available on the router instance.
| Property/Method | Type | Description |
|---|---|---|
router.currentRoute |
Route |
Current matched route object |
router.currentRoute.params |
object |
Current route parameters |
router.currentRoute.query |
object |
Current query parameters |
router.navigate(path, options?) |
function |
Navigate to path (or { name, params, query } for named routes) |
router.getRouteUrl(name, params?, query?, hash?) |
function |
Generate a URL string for a named route without navigating |
router.beforeEach(guard) |
function |
Register global before guard: ({ to, from }) => result |
router.afterEach(hook) |
function |
Register global after hook: ({ to, from }) => {} |
router.isActive(pattern, opts?) |
function |
Check if pattern matches current route. opts: { exact: true } |
router.abortNavigation() |
function |
Cancel an in-progress navigation |
router.destroy() |
function |
Tear down the router and remove event listeners |
router.viewTransitionsAvailable |
boolean |
Whether browser supports View Transitions API |
router.viewTransitionsEnabled |
boolean |
Whether transitions are enabled AND supported |
router.currentTransition |
ViewTransition | null |
Current active transition (during navigation) |
router.setViewTransitions(enabled) |
function |
Enable/disable view transitions at runtime |
router.on(event, callback) |
function |
Subscribe to router events (e.g., viewTransitionStart) |