Add SPA dispatch events and auto-close modals on navigation
🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -577,6 +577,10 @@ class Spa {
|
|||||||
// (Browser refresh scroll is handled separately by Rsx._restore_scroll_on_refresh)
|
// (Browser refresh scroll is handled separately by Rsx._restore_scroll_on_refresh)
|
||||||
Rsx.reset_pending_scroll();
|
Rsx.reset_pending_scroll();
|
||||||
|
|
||||||
|
// Trigger spa_dispatch_start event - allows cleanup before navigation
|
||||||
|
// Use case: close modals, cancel pending operations, etc.
|
||||||
|
Rsx.trigger('spa_dispatch_start', { url });
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const opts = {
|
const opts = {
|
||||||
history: options.history || 'auto',
|
history: options.history || 'auto',
|
||||||
@@ -943,10 +947,13 @@ class Spa {
|
|||||||
// This is the action - set reference but don't wait
|
// This is the action - set reference but don't wait
|
||||||
Spa._action = component;
|
Spa._action = component;
|
||||||
|
|
||||||
// After action is fully ready (on_load + on_ready complete), retry scroll restoration
|
// After action is fully ready (on_load + on_ready complete)
|
||||||
// This handles cases where on_load fetches data that increases page height
|
|
||||||
component.ready().then(() => {
|
component.ready().then(() => {
|
||||||
|
// Retry scroll restoration - handles cases where on_load fetches data that increases page height
|
||||||
Rsx.try_restore_scroll();
|
Rsx.try_restore_scroll();
|
||||||
|
|
||||||
|
// Trigger spa_dispatch_ready event - action is fully loaded and rendered
|
||||||
|
Rsx.trigger('spa_dispatch_ready', { url, action: component });
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
// This is a layout
|
// This is a layout
|
||||||
|
|||||||
@@ -692,6 +692,29 @@ Returns: void (does not wait for close)
|
|||||||
|
|
||||||
Note: Call Modal.close() to dismiss the modal programmatically.
|
Note: Call Modal.close() to dismiss the modal programmatically.
|
||||||
|
|
||||||
|
================================================================================
|
||||||
|
SPA INTEGRATION
|
||||||
|
================================================================================
|
||||||
|
|
||||||
|
The Modal system automatically integrates with SPA navigation:
|
||||||
|
|
||||||
|
Auto-Close on Navigation
|
||||||
|
When SPA navigation begins (spa_dispatch_start event), any open modal
|
||||||
|
is automatically closed. This prevents stale modals from persisting
|
||||||
|
across page transitions.
|
||||||
|
|
||||||
|
This behavior is automatic - no configuration required.
|
||||||
|
|
||||||
|
Modal Flow and Navigation
|
||||||
|
If you need to navigate after a modal action, use Spa.dispatch():
|
||||||
|
|
||||||
|
const result = await Modal.form({...});
|
||||||
|
if (result) {
|
||||||
|
Spa.dispatch(Rsx.Route('Target_Action'));
|
||||||
|
}
|
||||||
|
|
||||||
|
The modal closes first, then navigation proceeds.
|
||||||
|
|
||||||
================================================================================
|
================================================================================
|
||||||
MODAL STATE MANAGEMENT
|
MODAL STATE MANAGEMENT
|
||||||
================================================================================
|
================================================================================
|
||||||
|
|||||||
@@ -580,6 +580,60 @@ NAVIGATION
|
|||||||
generated by Rsx.Route(), so it never appears in the browser address
|
generated by Rsx.Route(), so it never appears in the browser address
|
||||||
bar or generated links.
|
bar or generated links.
|
||||||
|
|
||||||
|
SPA EVENTS
|
||||||
|
The SPA system fires global events that can be used to hook into the
|
||||||
|
navigation lifecycle. Register handlers using Rsx.on():
|
||||||
|
|
||||||
|
spa_dispatch_start
|
||||||
|
Fired at the beginning of navigation, before the old action is destroyed.
|
||||||
|
Use for cleanup before page transition.
|
||||||
|
|
||||||
|
Rsx.on('spa_dispatch_start', (data) => {
|
||||||
|
console.log('Navigating to:', data.url);
|
||||||
|
// Close modals, cancel pending operations, etc.
|
||||||
|
});
|
||||||
|
|
||||||
|
Data payload:
|
||||||
|
url: Target URL being navigated to
|
||||||
|
|
||||||
|
Common uses:
|
||||||
|
- Close open modals (Modal system does this automatically)
|
||||||
|
- Cancel pending Ajax requests
|
||||||
|
- Save unsaved form state
|
||||||
|
- Stop video/audio playback
|
||||||
|
|
||||||
|
spa_dispatch_ready
|
||||||
|
Fired after the new action has fully loaded (on_ready complete).
|
||||||
|
Use for post-navigation setup that needs the action to be ready.
|
||||||
|
|
||||||
|
Rsx.on('spa_dispatch_ready', (data) => {
|
||||||
|
console.log('Action ready:', data.action.constructor.name);
|
||||||
|
// Perform post-navigation actions
|
||||||
|
});
|
||||||
|
|
||||||
|
Data payload:
|
||||||
|
url: Current URL
|
||||||
|
action: The action component instance (fully loaded)
|
||||||
|
|
||||||
|
Common uses:
|
||||||
|
- Analytics page view tracking
|
||||||
|
- Focus management after navigation
|
||||||
|
- Lazy-load additional resources
|
||||||
|
|
||||||
|
Example: Custom navigation tracking
|
||||||
|
|
||||||
|
class Analytics_Tracker {
|
||||||
|
static on_app_modules_init() {
|
||||||
|
Rsx.on('spa_dispatch_start', () => {
|
||||||
|
Analytics.track_page_exit();
|
||||||
|
});
|
||||||
|
|
||||||
|
Rsx.on('spa_dispatch_ready', (data) => {
|
||||||
|
Analytics.track_page_view(data.url);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
SESSION VALIDATION
|
SESSION VALIDATION
|
||||||
After each SPA navigation (except initial load and back/forward), the client
|
After each SPA navigation (except initial load and back/forward), the client
|
||||||
validates its state against the server by calling Rsx.validate_session().
|
validates its state against the server by calling Rsx.validate_session().
|
||||||
|
|||||||
Reference in New Issue
Block a user