⬡ Lacelium
⌘K
Version 2.x ▾
Seamless Interaction

SPA Experience

Lacelium features an integrated zero-configuration Single Page Application engine. By intercepting internal link clicks and form submissions, it provides instantaneous transitions without full page reloads, preserving DOM state and providing native browser history support.

How It Works

When an internal hyperlink is clicked, Lacelium's frontend router intercepts the event, triggers a top loading bar, and fetches the target HTML via an asynchronous request. It automatically extracts the dynamic container (#lacelium-main), performs an atomic DOM morph, and updates the URL using the HTML5 pushState API.

Zero Build Tools Required

Unlike heavy client-side frameworks (React, Vue, or Angular), Lacelium's SPA architecture requires no JavaScript build steps, bundlers, or hydration overhead. All rendering remains server-side in Twig.

Interactive Simulation

Test the transition lifecycle below to see how atomic DOM swapping and progress indicators operate:

Virtual Container (#lacelium-main) State: Idle
View: Dashboard Overview
Showing live analytics metrics for Q3 production deployment.

Fine-tune how individual links and forms behave directly from HTML data attributes:

Attribute Target Element Behavior Description
data-lacelium-refresh <a>, <form> Opt-out of SPA navigation. Triggers a full browser reload (useful for file exports or third-party OAuth links).
data-lacelium-redirect <button>, <div> Instructs the router to execute a programmatic client-side pushState redirect to the specified URL.
data-lacelium-target <a> Specifies a custom container selector to update instead of the default #lacelium-main.

Seamless Form Submissions

Forms submit asynchronously through Lacelium's SPA transport layer. When a controller action returns a JSON response containing a redirect key, the client automatically executes a smooth transition:

namespace App\Http\Controllers;

use Lacelium\Core\Http\Request;
use Lacelium\Core\Http\Response;

class SettingsController
{
    public function update(Request $request, Response $response): Response
    {
        // 1. Validate & persist changes...

        // 2. Return SPA redirect instruction
        return $response->json([
            'success'  => true,
            'message'  => 'Settings saved successfully',
            'redirect' => '/dashboard',
        ]);
    }
}

JavaScript Lifecycle Hooks

Listen for custom DOM events to re-initialize client-side libraries (like tooltips, popovers, syntax highlighters, or charts) whenever navigation occurs:

// Fired before an asynchronous navigation request starts
document.addEventListener('lacelium:before-load', function (event) {
    console.log('Navigating to:', event.detail.url);
});

// Fired immediately after the DOM container has been replaced
document.addEventListener('lacelium:content-replaced', function () {
    console.log('DOM swapped! Re-initializing dynamic widgets...');
    // Re-initialize tooltips or charts
    if (window.bootstrap && bootstrap.Tooltip) {
        document.querySelectorAll('[data-bs-toggle="tooltip"]').forEach(el => new bootstrap.Tooltip(el));
    }
});

// Fired after the transition is complete and progress bar ends
document.addEventListener('lacelium:after-load', function () {
    window.scrollTo({ top: 0, behavior: 'instant' });
});

Production Guidelines

  • Persistent Top Layout: Keep heavy dependencies (such as navigation bars, stylesheets, and global scripts) outside the dynamic dynamic target container so they remain in memory.
  • Memory Management: Disconnect any orphaned Nexify channel subscriptions or intervals inside the lacelium:before-load listener before switching views.
  • Progressive Enhancement: Always ensure hyperlinks point to genuine HTTP routes so search engine crawlers and users with JavaScript disabled experience zero breakage.

Next Steps