Преглед изворни кода

improve foreach behavior with strings (#4751)

* improve foreach behavior with strings

* add a defensive guard before giving up

* add integration tests
Khaleel Al-Adhami пре 3 месеци
родитељ
комит
b3b79a652d
2 измењених фајлова са 22 додато и 2 уклоњено
  1. 12 2
      reflex/components/core/foreach.py
  2. 10 0
      tests/integration/test_var_operations.py

+ 12 - 2
reflex/components/core/foreach.py

@@ -54,9 +54,10 @@ class Foreach(Component):
             TypeError: If the render function is a ComponentState.
             UntypedVarError: If the iterable is of type Any without a type annotation.
         """
-        from reflex.vars.object import ObjectVar
+        from reflex.vars import ArrayVar, ObjectVar, StringVar
+
+        iterable = LiteralVar.create(iterable).guess_type()
 
-        iterable = LiteralVar.create(iterable)
         if iterable._var_type == Any:
             raise ForeachVarError(
                 f"Could not foreach over var `{iterable!s}` of type Any. "
@@ -75,6 +76,15 @@ class Foreach(Component):
         if isinstance(iterable, ObjectVar):
             iterable = iterable.entries()
 
+        if isinstance(iterable, StringVar):
+            iterable = iterable.split()
+
+        if not isinstance(iterable, ArrayVar):
+            raise ForeachVarError(
+                f"Could not foreach over var `{iterable!s}` of type {iterable._var_type}. "
+                "See https://reflex.dev/docs/library/dynamic-rendering/foreach/"
+            )
+
         component = cls(
             iterable=iterable,
             render_fn=render_fn,

+ 10 - 0
tests/integration/test_var_operations.py

@@ -628,6 +628,14 @@ def VarOperations():
                 ),
                 id="dict_in_foreach3",
             ),
+            rx.box(
+                rx.foreach("abcdef", lambda x: rx.text.span(x + " ")),
+                id="str_in_foreach",
+            ),
+            rx.box(
+                rx.foreach(VarOperationState.str_var1, lambda x: rx.text.span(x + " ")),
+                id="str_var_in_foreach",
+            ),
             rx.box(
                 rx.foreach(
                     VarOperationState.people,
@@ -844,6 +852,8 @@ def test_var_operations(driver, var_operations: AppHarness):
         ("dict_in_foreach1", "a1b2"),
         ("dict_in_foreach2", "12"),
         ("dict_in_foreach3", "1234"),
+        ("str_in_foreach", "a b c d e f"),
+        ("str_var_in_foreach", "f i r s t"),
         ("typed_dict_in_foreach", "Hello Alice33Hello Bob28"),
     ]