foreach.py 1.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748
  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. TypeError: If the render function is a ComponentState.
  24. """
  25. iterable = LiteralVar.create(iterable)
  26. if isinstance(iterable, ObjectVar):
  27. iterable = iterable.items()
  28. if not isinstance(iterable, ArrayVar):
  29. raise ForeachVarError(
  30. f"Could not foreach over var `{iterable!s}` of type {iterable._var_type!s}. "
  31. "(If you are trying to foreach over a state var, add a type annotation to the var). "
  32. "See https://reflex.dev/docs/library/dynamic-rendering/foreach/"
  33. )
  34. return iterable.foreach(render_fn)