diff --git a/src/myfasthtml/controls/DataGridsManager.py b/src/myfasthtml/controls/DataGridsManager.py index 8cb3ec0..b444f89 100644 --- a/src/myfasthtml/controls/DataGridsManager.py +++ b/src/myfasthtml/controls/DataGridsManager.py @@ -116,7 +116,30 @@ class DataGridsManager(MultipleInstance): except StopIteration: # the selected node is not a document (it's a folder) return None - + + def create_tab_content(self, tab_id): + """ + Recreate the content for a tab managed by this DataGridsManager. + Called by TabsManager when the content is not in cache (e.g., after restart). + + Args: + tab_id: ID of the tab to recreate content for + + Returns: + The recreated component (Panel with DataGrid) + """ + # Find the document associated with this tab + document = next((d for d in self._state.elements if d.tab_id == tab_id), None) + + if document is None: + raise ValueError(f"No document found for tab {tab_id}") + + # Recreate the DataGrid with its saved state + dg = DataGrid(self._tabs_manager, _id=document.datagrid_id) + + # Wrap in Panel + return Panel(self).set_main(dg) + def clear_tree(self): self._state.elements = [] self._tree.clear() diff --git a/src/myfasthtml/controls/TabsManager.py b/src/myfasthtml/controls/TabsManager.py index 2f7058a..81ce3c2 100644 --- a/src/myfasthtml/controls/TabsManager.py +++ b/src/myfasthtml/controls/TabsManager.py @@ -120,15 +120,36 @@ class TabsManager(MultipleInstance): if tab_config["component"] is None: return Div("Tab content does not support serialization.") - res = InstancesManager.get(self._session, tab_config["component"][1], None) + # 1. Try to get existing component instance + res = InstancesManager.get(self._session, tab_config["component"][1], None) if res is not None: + logger.debug(f"Component {tab_config['component'][1]} already exists") return res - - try: - logger.debug(f"Component not created yet. Need to manually create it.") - return InstancesManager.dynamic_get(self._session, tab_config["component_parent"], tab_config["component"]) - except Exception as e: - logger.error(f"Error while retrieving tab content: {e}") + + # 2. Get or create parent + if tab_config["component_parent"] is None: + logger.error(f"No parent defined for tab {tab_id}") + return Div("Failed to retrieve tab content.") + + parent = InstancesManager.get(self._session, tab_config["component_parent"][1], None) + if parent is None: + logger.error(f"Parent {tab_config['component_parent'][1]} not found for tab {tab_id}") + return Div("Parent component not available") + + # 3. If parent supports create_tab_content, use it + if hasattr(parent, 'create_tab_content'): + try: + logger.debug(f"Asking parent {tab_config['component_parent'][1]} to create tab content for {tab_id}") + content = parent.create_tab_content(tab_id) + # Store in cache + self._state.ns_tabs_content[tab_id] = content + return content + except Exception as e: + logger.error(f"Error while parent creating tab content: {e}") + return Div("Failed to retrieve tab content.") + else: + # Parent doesn't support create_tab_content, fallback to error + logger.error(f"Parent {tab_config['component_parent'][1]} doesn't support create_tab_content") return Div("Failed to retrieve tab content.") def _get_or_create_tab_content(self, tab_id): diff --git a/src/myfasthtml/core/instances.py b/src/myfasthtml/core/instances.py index a3f4e95..ec8f766 100644 --- a/src/myfasthtml/core/instances.py +++ b/src/myfasthtml/core/instances.py @@ -210,15 +210,24 @@ class InstancesManager: @staticmethod def dynamic_get(session, component_parent: tuple, component: tuple): - parent_type, parent_id = component_parent component_type, component_id = component - + + # 1. Check if component already exists + existing = InstancesManager.get(session, component_id, None) + if existing is not None: + logger.debug(f"Component {component_id} already exists, returning existing instance") + return existing + + # 2. Component doesn't exist, create it + parent_type, parent_id = component_parent + # parent should always exist parent = InstancesManager.get(session, parent_id) - + real_component_type = snake_to_pascal(component_type.removeprefix("mf-")) component_full_type = f"myfasthtml.controls.{real_component_type}.{real_component_type}" cls = get_class(component_full_type) + logger.debug(f"Creating new component {component_id} of type {real_component_type}") return cls(parent, _id=component_id) @staticmethod