foreach.py 1.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253
  1. """Create a list of components from an iterable."""
  2. from __future__ import annotations
  3. from typing import Any, Callable, List
  4. from pynecone.components.component import Component
  5. from pynecone.components.tags import IterTag, Tag
  6. from pynecone.var import BaseVar, Var
  7. class Foreach(Component):
  8. """A component that takes in an iterable and a render function and renders a list of components."""
  9. # The iterable to create components from.
  10. iterable: Var[List]
  11. # A function from the render args to the component.
  12. render_fn: Callable
  13. @classmethod
  14. def create(cls, iterable: Var[List], render_fn: Callable, **props) -> Foreach:
  15. """Create a foreach component.
  16. Args:
  17. iterable: The iterable to create components from.
  18. render_fn: A function from the render args to the component.
  19. **props: The attributes to pass to each child component.
  20. Returns:
  21. The foreach component.
  22. Raises:
  23. TypeError: If the iterable is of type Any.
  24. """
  25. try:
  26. type_ = iterable.type_.__args__[0]
  27. except Exception:
  28. type_ = Any
  29. iterable = Var.create(iterable) # type: ignore
  30. if iterable.type_ == Any:
  31. raise TypeError(
  32. f"Could not foreach over var of type Any. (If you are trying to foreach over a state var, add a type annotation to the var.)"
  33. )
  34. arg = BaseVar(name="_", type_=type_, is_local=True)
  35. return cls(
  36. iterable=iterable,
  37. render_fn=render_fn,
  38. children=[IterTag.render_component(render_fn, arg=arg)],
  39. **props,
  40. )
  41. def _render(self) -> Tag:
  42. return IterTag(iterable=self.iterable, render_fn=self.render_fn)