foreach.py 1.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152
  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. if iterable.type_ == Any:
  30. raise TypeError(
  31. 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.)"
  32. )
  33. arg = BaseVar(name="_", type_=type_, is_local=True)
  34. return cls(
  35. iterable=iterable,
  36. render_fn=render_fn,
  37. children=[IterTag.render_component(render_fn, arg=arg)],
  38. **props,
  39. )
  40. def _render(self) -> Tag:
  41. return IterTag(iterable=self.iterable, render_fn=self.render_fn)