Fix client routing: fall through to server on layout/section change

Client-side routing was only swapping #main-panel content without
updating OOB headers (nav rows, sub-rows). Now each page entry in the
registry includes a layout identity (e.g. "sx-section:Testing") and
try-client-route falls through to server when layout changes, so OOB
header updates are applied correctly.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-07 17:46:01 +00:00
parent 7f466f0fd6
commit 605aafa2eb
3 changed files with 63 additions and 14 deletions

View File

@@ -593,7 +593,14 @@
;; Client-side routing
;; --------------------------------------------------------------------------
;; No app-specific nav update here — apps handle sx:clientRoute event.
(define current-page-layout
(fn ()
;; Find the layout name of the currently displayed page by matching
;; the browser URL against the page route table.
(let ((pathname (url-pathname (browser-location-href)))
(match (find-matching-route pathname _page-routes)))
(if (nil? match) ""
(or (get match "layout") "")))))
(define swap-rendered-content
@@ -634,20 +641,25 @@
;; Try to render a page client-side. Returns true if successful, false otherwise.
;; target-sel is the CSS selector for the swap target (from sx-boost value).
;; For pure pages: renders immediately. For :data pages: fetches data then renders.
;; Falls through to server when layout changes (needs OOB header update).
(let ((match (find-matching-route pathname _page-routes)))
(if (nil? match)
(do (log-info (str "sx:route no match (" (len _page-routes) " routes) " pathname)) false)
(let ((content-src (get match "content"))
(closure (or (get match "closure") {}))
(params (get match "params"))
(page-name (get match "name")))
(if (or (nil? content-src) (empty? content-src))
(do (log-warn (str "sx:route no content for " pathname)) false)
(let ((target (resolve-route-target target-sel)))
(if (nil? target)
(do (log-warn (str "sx:route target not found: " target-sel)) false)
(if (not (deps-satisfied? match))
(do (log-info (str "sx:route deps miss for " page-name)) false)
(let ((target-layout (or (get match "layout") ""))
(cur-layout (current-page-layout)))
(if (not (= target-layout cur-layout))
(do (log-info (str "sx:route server (layout: " cur-layout " -> " target-layout ") " pathname)) false)
(let ((content-src (get match "content"))
(closure (or (get match "closure") {}))
(params (get match "params"))
(page-name (get match "name")))
(if (or (nil? content-src) (empty? content-src))
(do (log-warn (str "sx:route no content for " pathname)) false)
(let ((target (resolve-route-target target-sel)))
(if (nil? target)
(do (log-warn (str "sx:route target not found: " target-sel)) false)
(if (not (deps-satisfied? match))
(do (log-info (str "sx:route deps miss for " page-name)) false)
(let ((io-deps (get match "io-deps"))
(has-io (and io-deps (not (empty? io-deps)))))
;; Ensure IO deps are registered as proxied primitives
@@ -715,7 +727,7 @@
(do (log-info (str "sx:route server (eval failed) " pathname)) false)
(do
(swap-rendered-content target rendered pathname)
true)))))))))))))))
true)))))))))))))))))
(define bind-client-route-link