select.py 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  1. """A select component."""
  2. from typing import Any, List
  3. from reflex.components.chakra import ChakraComponent, LiteralInputVariant
  4. from reflex.components.chakra.typography.text import Text
  5. from reflex.components.component import Component
  6. from reflex.components.core.foreach import Foreach
  7. from reflex.event import EventHandler
  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. # Fired when the value changes.
  36. on_change: EventHandler[lambda e0: [e0.target.value]]
  37. @classmethod
  38. def create(cls, *children, **props) -> Component:
  39. """Create a select component.
  40. If a list is provided as the first children, a default component
  41. will be created for each item in the list.
  42. Args:
  43. *children: The children of the component.
  44. **props: The props of the component.
  45. Returns:
  46. The component.
  47. """
  48. if len(children) == 1 and isinstance(children[0], list):
  49. children = [Option.create(child) for child in children[0]]
  50. if (
  51. len(children) == 1
  52. and isinstance(children[0], Var)
  53. and _issubclass(children[0]._var_type, List)
  54. ):
  55. children = [Foreach.create(children[0], lambda item: Option.create(item))]
  56. return super().create(*children, **props)
  57. class Option(Text):
  58. """A select option."""
  59. tag = "option"
  60. value: Var[Any]
  61. @classmethod
  62. def create(cls, *children, **props) -> Component:
  63. """Create a select option component.
  64. By default, the value of the option is the text of the option.
  65. Args:
  66. *children: The children of the component.
  67. **props: The props of the component.
  68. Returns:
  69. The component.
  70. """
  71. if "value" not in props:
  72. assert len(children) == 1
  73. props["value"] = children[0]
  74. return super().create(*children, **props)