fix recursive UI

This commit is contained in:
Khaleel Al-Adhami 2025-01-07 11:16:09 -08:00
parent 08d9fbf9bc
commit 37bb97b1ee
3 changed files with 29 additions and 9 deletions

View File

@ -108,11 +108,14 @@ class Bare(Component):
return Tagless(contents=f"{{{self.contents!s}}}") return Tagless(contents=f"{{{self.contents!s}}}")
return Tagless(contents=str(self.contents)) return Tagless(contents=str(self.contents))
def _get_vars(self, include_children: bool = False) -> Iterator[Var]: def _get_vars(
self, include_children: bool = False, ignore_ids: set[int] | None = None
) -> Iterator[Var]:
"""Walk all Vars used in this component. """Walk all Vars used in this component.
Args: Args:
include_children: Whether to include Vars from children. include_children: Whether to include Vars from children.
ignore_ids: The ids to ignore.
Yields: Yields:
The contents if it is a Var, otherwise nothing. The contents if it is a Var, otherwise nothing.

View File

@ -1020,15 +1020,19 @@ class Component(BaseComponent, ABC):
event_args.append(spec) event_args.append(spec)
yield event_trigger, event_args yield event_trigger, event_args
def _get_vars(self, include_children: bool = False) -> list[Var]: def _get_vars(
self, include_children: bool = False, ignore_ids: set[int] | None = None
) -> Iterator[Var]:
"""Walk all Vars used in this component. """Walk all Vars used in this component.
Args: Args:
include_children: Whether to include Vars from children. include_children: Whether to include Vars from children.
ignore_ids: The ids to ignore.
Returns: Returns:
Each var referenced by the component (props, styles, event handlers). Each var referenced by the component (props, styles, event handlers).
""" """
ignore_ids = ignore_ids or set()
vars = getattr(self, "__vars", None) vars = getattr(self, "__vars", None)
if vars is not None: if vars is not None:
return vars return vars
@ -1075,9 +1079,12 @@ class Component(BaseComponent, ABC):
# Get Vars associated with children. # Get Vars associated with children.
if include_children: if include_children:
for child in self.children: for child in self.children:
if not isinstance(child, Component): if not isinstance(child, Component) or id(child) in ignore_ids:
continue continue
child_vars = child._get_vars(include_children=include_children) ignore_ids.add(id(child))
child_vars = child._get_vars(
include_children=include_children, ignore_ids=ignore_ids
)
vars.extend(child_vars) vars.extend(child_vars)
return vars return vars
@ -1811,19 +1818,25 @@ class CustomComponent(Component):
for name, prop in self.props.items() for name, prop in self.props.items()
] ]
def _get_vars(self, include_children: bool = False) -> list[Var]: def _get_vars(
self, include_children: bool = False, ignore_ids: set[int] | None = None
) -> Iterator[Var]:
"""Walk all Vars used in this component. """Walk all Vars used in this component.
Args: Args:
include_children: Whether to include Vars from children. include_children: Whether to include Vars from children.
ignore_ids: The ids to ignore.
Returns: Returns:
Each var referenced by the component (props, styles, event handlers). Each var referenced by the component (props, styles, event handlers).
""" """
ignore_ids = ignore_ids or set()
return ( return (
super()._get_vars(include_children=include_children) super()._get_vars(include_children=include_children, ignore_ids=ignore_ids)
+ [prop for prop in self.props.values() if isinstance(prop, Var)] + [prop for prop in self.props.values() if isinstance(prop, Var)]
+ self.get_component(self)._get_vars(include_children=include_children) + self.get_component(self)._get_vars(
include_children=include_children, ignore_ids=ignore_ids
)
) )
@lru_cache(maxsize=None) # noqa @lru_cache(maxsize=None) # noqa

View File

@ -250,8 +250,12 @@ class Form(BaseHTML):
) )
return form_refs return form_refs
def _get_vars(self, include_children: bool = True) -> Iterator[Var]: def _get_vars(
yield from super()._get_vars(include_children=include_children) self, include_children: bool = True, ignore_ids: set[int] | None = None
) -> Iterator[Var]:
yield from super()._get_vars(
include_children=include_children, ignore_ids=ignore_ids
)
yield from self._get_form_refs().values() yield from self._get_form_refs().values()
def _exclude_props(self) -> list[str]: def _exclude_props(self) -> list[str]: