Route Guards SPA+

Per-route leave guards, metadata inheritance, and navigation cancellation. For basic guard setup with beforeEnter and beforeEach, see Route Management.

beforeLeave Guards

Per-route leave guards run when navigating away from a route. Use them to protect against accidental data loss.

Basic Usage

router.onRoute('/editor', {
    handler: () => showEditor(),
    beforeLeave: ({ to, from }) => {
        if (hasUnsavedChanges()) {
            return false;  // Block navigation
        }
        return true;  // Allow navigation
    }
});

Redirect on Leave

router.onRoute('/checkout', {
    handler: () => showCheckout(),
    beforeLeave: ({ to }) => {
        // Must confirm before leaving checkout
        if (!orderConfirmed && to.path !== '/confirm-leave') {
            return '/confirm-leave';  // Redirect instead
        }
        return true;
    }
});

Guard Return Values

Return Value Effect
true / undefinedAllow leaving the route
falseBlock navigation, stay on current route
'/path'Redirect to a different path
Router Example beforeLeave Guard: Unsaved Changes Open Full Example
Try it: Navigate to "Edit Form", then try to leave. The guard blocks you until you check "Mark changes as saved".

Route Metadata Inheritance

Child routes inherit their parent's meta properties. Child values override parent values on collision.

const router = wildflower.createRouter({
    routes: [
        {
            path: '/admin',
            meta: { requiresAuth: true, layout: 'admin' },
            handler: showAdminHome,
            children: [
                {
                    path: '/users',
                    meta: { requiresAdmin: true },
                    handler: showAdminUsers
                    // Effective meta: { requiresAuth: true, layout: 'admin', requiresAdmin: true }
                },
                {
                    path: '/settings',
                    meta: { layout: 'settings' },  // Overrides parent layout
                    handler: showSettings
                    // Effective meta: { requiresAuth: true, layout: 'settings' }
                }
            ]
        }
    ]
});

// Use in a global guard
router.beforeEach(({ to }) => {
    if (to.meta.requiresAuth && !isLoggedIn()) {
        return '/login';
    }
    if (to.meta.requiresAdmin && !isAdmin()) {
        return '/unauthorized';
    }
    return true;
});

Navigation Cancellation

Cancel an in-progress navigation from outside the guard chain using abortNavigation():

// Start a navigation
router.navigate('/slow-page');

// Cancel it before it completes
router.abortNavigation();

// Practical example: timeout protection
router.navigate('/api-data');
const timeout = setTimeout(() => {
    if (router.isNavigating) {
        router.abortNavigation();
        showTimeoutError();
    }
}, 5000);
Timing: abortNavigation() only works while router.isNavigating is true. It has no effect after navigation completes.
SPA E-commerce Store

A checkout flow that refuses to advance past an empty cart, guarded at the route.