Fix detached action redirect loops, abstract Spa_Action detection, jqhtml update
🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -1001,11 +1001,14 @@ class Spa {
|
||||
const $detached = $('<div>');
|
||||
|
||||
// Instantiate the action on the detached element
|
||||
// This triggers the full component lifecycle: on_create -> render -> on_render -> on_load -> on_ready
|
||||
$detached.component(action_name, args);
|
||||
// Skip render and on_ready phases - detached actions are for data extraction only
|
||||
// (e.g., getting title/breadcrumbs). Running on_ready() could trigger side effects
|
||||
// like Spa.dispatch() which would cause redirect loops.
|
||||
const options = { skip_render_and_ready: true };
|
||||
$detached.component(action_name, args, options);
|
||||
const action = $detached.component();
|
||||
|
||||
// Wait for the action to be fully ready (including on_load completion)
|
||||
// Wait for on_load to complete (data fetching)
|
||||
await action.ready();
|
||||
|
||||
console_debug('Spa', `load_detached_action: ${action_name} ready`);
|
||||
|
||||
@@ -78,4 +78,71 @@ class Spa_Action extends Component {
|
||||
const url = this.url(params);
|
||||
Spa.dispatch(url);
|
||||
}
|
||||
|
||||
// =========================================================================
|
||||
// Page Title & Breadcrumb System
|
||||
// =========================================================================
|
||||
|
||||
/**
|
||||
* Page title displayed in the header/title area
|
||||
*
|
||||
* Override this in every action to provide a meaningful page title.
|
||||
* For entity pages, include entity details (e.g., "Contact: John Smith C001")
|
||||
*
|
||||
* @returns {Promise<string>} The page title
|
||||
*/
|
||||
async page_title() {
|
||||
return '(title not set)';
|
||||
}
|
||||
|
||||
/**
|
||||
* Breadcrumb label for this action
|
||||
*
|
||||
* Used when this action appears as a parent in another action's breadcrumb chain.
|
||||
* For entity pages (viewing a specific user, contact, etc.), return the entity name.
|
||||
* For list/index pages, return the section name.
|
||||
*
|
||||
* Default: Returns page_title()
|
||||
*
|
||||
* @returns {Promise<string>} The breadcrumb label
|
||||
*/
|
||||
async breadcrumb_label() {
|
||||
return await this.page_title();
|
||||
}
|
||||
|
||||
/**
|
||||
* Breadcrumb label when this action is the active/last crumb
|
||||
*
|
||||
* Use this to show a descriptive action name instead of the entity name
|
||||
* when the entity name is already visible in the page title above.
|
||||
*
|
||||
* Example: For a user profile view page:
|
||||
* - page_title() = "User Profile: John Smith U001"
|
||||
* - breadcrumb_label() = "John Smith" (for when it's a parent)
|
||||
* - breadcrumb_label_active() = "View User Profile" (avoids redundancy with title)
|
||||
*
|
||||
* Default: Returns breadcrumb_label()
|
||||
*
|
||||
* @returns {Promise<string>} The active breadcrumb label
|
||||
*/
|
||||
async breadcrumb_label_active() {
|
||||
return await this.breadcrumb_label();
|
||||
}
|
||||
|
||||
/**
|
||||
* Parent action URL for breadcrumb chain
|
||||
*
|
||||
* Return the URL of the parent action using Rsx.Route().
|
||||
* Return null if this action is a root (no parent breadcrumb).
|
||||
*
|
||||
* Example:
|
||||
* async breadcrumb_parent() {
|
||||
* return Rsx.Route('Settings_Users_Action');
|
||||
* }
|
||||
*
|
||||
* @returns {Promise<string|null>} Parent URL or null if root
|
||||
*/
|
||||
async breadcrumb_parent() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user