foreach.py 1.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162
  1. """Create a list of components from an iterable."""
  2. from __future__ import annotations
  3. from typing import Any, List, Protocol, runtime_checkable
  4. from pynecone.components.component import Component
  5. from pynecone.components.tags import IterTag, Tag
  6. from pynecone.var import BaseVar, Var
  7. @runtime_checkable
  8. class RenderFn(Protocol):
  9. """A function that renders a component."""
  10. def __call__(self, *args, **kwargs) -> Component:
  11. """Render a component.
  12. Args:
  13. *args: The positional arguments.
  14. **kwargs: The keyword arguments.
  15. Returns: # noqa: DAR202
  16. The rendered component.
  17. """
  18. ...
  19. class Foreach(Component):
  20. """Display a foreach."""
  21. # The iterable to create components from.
  22. iterable: Var[List]
  23. # A function from the render args to the component.
  24. render_fn: RenderFn
  25. @classmethod
  26. def create(cls, iterable: Var[List], render_fn: RenderFn, **props) -> Foreach:
  27. """Create a foreach component.
  28. Args:
  29. iterable: The iterable to create components from.
  30. render_fn: A function from the render args to the component.
  31. **props: The attributes to pass to each child component.
  32. Returns:
  33. The foreach component.
  34. """
  35. try:
  36. type_ = iterable.type_.__args__[0]
  37. except:
  38. type_ = Any
  39. arg = BaseVar(name="_", type_=type_, is_local=True)
  40. return cls(
  41. iterable=iterable,
  42. render_fn=render_fn,
  43. children=[IterTag.render_component(render_fn, arg=arg)],
  44. **props,
  45. )
  46. def _render(self) -> Tag:
  47. return IterTag(iterable=self.iterable, render_fn=self.render_fn)