foreach.py 1.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253
  1. """Create a list of components from an iterable."""
  2. from __future__ import annotations
  3. from typing import Callable, Iterable
  4. from reflex.vars.base import LiteralVar, Var
  5. from reflex.vars.object import ObjectVar
  6. from reflex.vars.sequence import ArrayVar
  7. class ForeachVarError(TypeError):
  8. """Raised when the iterable type is Any."""
  9. class ForeachRenderError(TypeError):
  10. """Raised when there is an error with the foreach render function."""
  11. def foreach(
  12. iterable: Var[Iterable] | Iterable,
  13. render_fn: Callable,
  14. ) -> Var:
  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. Returns:
  20. The foreach component.
  21. Raises:
  22. ForeachVarError: If the iterable is of type Any.
  23. """
  24. iterable = LiteralVar.create(iterable).guess_type()
  25. if isinstance(iterable, ObjectVar):
  26. iterable = iterable.items()
  27. if not isinstance(iterable, ArrayVar):
  28. raise ForeachVarError(
  29. f"Could not foreach over var `{iterable!s}` of type {iterable._var_type!s}. "
  30. "(If you are trying to foreach over a state var, add a type annotation to the var). "
  31. "See https://reflex.dev/docs/library/dynamic-rendering/foreach/"
  32. )
  33. return iterable.foreach(render_fn)
  34. class Foreach:
  35. """Create a list of components from an iterable."""
  36. create = staticmethod(foreach)