cond.py 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. """Create a list of components from an iterable."""
  2. from __future__ import annotations
  3. from typing import Any, Dict, Optional
  4. from reflex.components.component import Component
  5. from reflex.components.layout.fragment import Fragment
  6. from reflex.components.tags import CondTag, Tag
  7. from reflex.utils import format
  8. from reflex.vars import Var
  9. class Cond(Component):
  10. """Render one of two components based on a condition."""
  11. # The cond to determine which component to render.
  12. cond: Var[Any]
  13. # The component to render if the cond is true.
  14. comp1: Component = Fragment.create()
  15. # The component to render if the cond is false.
  16. comp2: Component = Fragment.create()
  17. @classmethod
  18. def create(
  19. cls,
  20. cond: Var,
  21. comp1: Component,
  22. comp2: Optional[Component] = None,
  23. ) -> Component:
  24. """Create a conditional component.
  25. Args:
  26. cond: The cond to determine which component to render.
  27. comp1: The component to render if the cond is true.
  28. comp2: The component to render if the cond is false.
  29. Returns:
  30. The conditional component.
  31. """
  32. # Wrap everything in fragments.
  33. if comp1.__class__.__name__ != "Fragment":
  34. comp1 = Fragment.create(comp1)
  35. if comp2 is None or comp2.__class__.__name__ != "Fragment":
  36. comp2 = Fragment.create(comp2) if comp2 else Fragment.create()
  37. return Fragment.create(
  38. cls(
  39. cond=cond,
  40. comp1=comp1,
  41. comp2=comp2,
  42. children=[comp1, comp2],
  43. )
  44. )
  45. def _get_props_imports(self):
  46. """Get the imports needed for components props.
  47. Returns:
  48. The imports for the components props of the component.
  49. """
  50. return []
  51. def _render(self) -> Tag:
  52. return CondTag(
  53. cond=self.cond,
  54. true_value=self.comp1.render(),
  55. false_value=self.comp2.render(),
  56. )
  57. def render(self) -> Dict:
  58. """Render the component.
  59. Returns:
  60. The dictionary for template of component.
  61. """
  62. tag = self._render()
  63. return dict(
  64. tag.add_props(
  65. **self.event_triggers,
  66. key=self.key,
  67. sx=self.style,
  68. id=self.id,
  69. class_name=self.class_name,
  70. ).set(
  71. props=tag.format_props(),
  72. ),
  73. cond_state=f"isTrue({self.cond._var_full_name})",
  74. )
  75. def cond(condition: Any, c1: Any, c2: Any = None):
  76. """Create a conditional component or Prop.
  77. Args:
  78. condition: The cond to determine which component to render.
  79. c1: The component or prop to render if the cond_var is true.
  80. c2: The component or prop to render if the cond_var is false.
  81. Returns:
  82. The conditional component.
  83. Raises:
  84. ValueError: If the arguments are invalid.
  85. """
  86. # Import here to avoid circular imports.
  87. from reflex.vars import BaseVar, Var
  88. # Convert the condition to a Var.
  89. cond_var = Var.create(condition)
  90. assert cond_var is not None, "The condition must be set."
  91. # If the first component is a component, create a Cond component.
  92. if isinstance(c1, Component):
  93. assert c2 is None or isinstance(
  94. c2, Component
  95. ), "Both arguments must be components."
  96. return Cond.create(cond_var, c1, c2)
  97. # Otherwise, create a conditionl Var.
  98. # Check that the second argument is valid.
  99. if isinstance(c2, Component):
  100. raise ValueError("Both arguments must be props.")
  101. if c2 is None:
  102. raise ValueError("For conditional vars, the second argument must be set.")
  103. # Create the conditional var.
  104. return BaseVar(
  105. _var_name=format.format_cond(
  106. cond=cond_var._var_full_name,
  107. true_value=c1,
  108. false_value=c2,
  109. is_prop=True,
  110. ),
  111. _var_type=c1._var_type if isinstance(c1, BaseVar) else type(c1),
  112. )