1
0

select.py 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. """A select component."""
  2. from typing import Any, Dict, List, Union
  3. from reflex.components.component import Component
  4. from reflex.components.layout.foreach import Foreach
  5. from reflex.components.libs.chakra import ChakraComponent, LiteralInputVariant
  6. from reflex.components.typography.text import Text
  7. from reflex.constants import EventTriggers
  8. from reflex.utils.types import _issubclass
  9. from reflex.vars import Var
  10. class Select(ChakraComponent):
  11. """Select component is a component that allows users pick a value from predefined options. Ideally, it should be used when there are more than 5 options, otherwise you might consider using a radio group instead."""
  12. tag = "Select"
  13. # State var to bind the select.
  14. value: Var[str]
  15. # The default value of the select.
  16. default_value: Var[str]
  17. # The placeholder text.
  18. placeholder: Var[str]
  19. # The border color when the select is invalid.
  20. error_border_color: Var[str]
  21. # The border color when the select is focused.
  22. focus_border_color: Var[str]
  23. # If true, the select will be disabled.
  24. is_disabled: Var[bool]
  25. # If true, the form control will be invalid. This has 2 side effects: - The FormLabel and FormErrorIcon will have `data-invalid` set to true - The form element (e.g, Input) will have `aria-invalid` set to true
  26. is_invalid: Var[bool]
  27. # If true, the form control will be required. This has 2 side effects: - The FormLabel will show a required indicator - The form element (e.g, Input) will have `aria-required` set to true
  28. is_required: Var[bool]
  29. # "outline" | "filled" | "flushed" | "unstyled"
  30. variant: Var[LiteralInputVariant]
  31. # The size of the select.
  32. size: Var[str]
  33. # The name of the form field
  34. name: Var[str]
  35. def get_event_triggers(self) -> Dict[str, Union[Var, Any]]:
  36. """Get the event triggers that pass the component's value to the handler.
  37. Returns:
  38. A dict mapping the event trigger to the var that is passed to the handler.
  39. """
  40. return {
  41. **super().get_event_triggers(),
  42. EventTriggers.ON_CHANGE: lambda e0: [e0.target.value],
  43. }
  44. @classmethod
  45. def create(cls, *children, **props) -> Component:
  46. """Create a select component.
  47. If a list is provided as the first children, a default component
  48. will be created for each item in the list.
  49. Args:
  50. *children: The children of the component.
  51. **props: The props of the component.
  52. Returns:
  53. The component.
  54. """
  55. if len(children) == 1 and isinstance(children[0], list):
  56. children = [Option.create(child) for child in children[0]]
  57. if (
  58. len(children) == 1
  59. and isinstance(children[0], Var)
  60. and _issubclass(children[0]._var_type, List)
  61. ):
  62. children = [Foreach.create(children[0], lambda item: Option.create(item))]
  63. return super().create(*children, **props)
  64. class Option(Text):
  65. """A select option."""
  66. tag = "option"
  67. value: Var[Any]
  68. @classmethod
  69. def create(cls, *children, **props) -> Component:
  70. """Create a select option component.
  71. By default, the value of the option is the text of the option.
  72. Args:
  73. *children: The children of the component.
  74. **props: The props of the component.
  75. Returns:
  76. The component.
  77. """
  78. if "value" not in props:
  79. assert len(children) == 1
  80. props["value"] = children[0]
  81. return super().create(*children, **props)