Skip to content

Commit 20e8b83

Browse files
authored
[ENG-4570] Fix rx.foreach over dict (#4743)
* Add test case for literal dict in foreach * [ENG-4570] Iterate over ObjectVar.entries * Adjust expectations of test_foreach.py unit tests
1 parent 2ff840a commit 20e8b83

File tree

4 files changed

+31
-9
lines changed

4 files changed

+31
-9
lines changed

reflex/.templates/jinja/web/pages/utils.js.jinja2

+1-1
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@
6060
{# Args: #}
6161
{# component: component dictionary #}
6262
{% macro render_iterable_tag(component) %}
63-
<>{ {%- if component.iterable_type == 'dict' -%}Object.entries({{- component.iterable_state }}){%- else -%}{{- component.iterable_state }}{%- endif -%}.map(({{ component.arg_name }}, {{ component.arg_index }}) => (
63+
<>{ {{ component.iterable_state }}.map(({{ component.arg_name }}, {{ component.arg_index }}) => (
6464
{% for child in component.children %}
6565
{{ render(child) }}
6666
{% endfor %}

reflex/components/core/foreach.py

+5
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,8 @@ def create(
5454
TypeError: If the render function is a ComponentState.
5555
UntypedVarError: If the iterable is of type Any without a type annotation.
5656
"""
57+
from reflex.vars.object import ObjectVar
58+
5759
iterable = LiteralVar.create(iterable)
5860
if iterable._var_type == Any:
5961
raise ForeachVarError(
@@ -70,6 +72,9 @@ def create(
7072
"Using a ComponentState as `render_fn` inside `rx.foreach` is not supported yet."
7173
)
7274

75+
if isinstance(iterable, ObjectVar):
76+
iterable = iterable.entries()
77+
7378
component = cls(
7479
iterable=iterable,
7580
render_fn=render_fn,

tests/integration/test_var_operations.py

+17
Original file line numberDiff line numberDiff line change
@@ -605,6 +605,20 @@ def index():
605605
rx.box(rx.foreach(range(42, 80, 3), rx.text.span), id="range_in_foreach2"),
606606
rx.box(rx.foreach(range(42, 20, -6), rx.text.span), id="range_in_foreach3"),
607607
rx.box(rx.foreach(range(42, 43, 5), rx.text.span), id="range_in_foreach4"),
608+
# Literal dict in a foreach
609+
rx.box(rx.foreach({"a": 1, "b": 2}, rx.text.span), id="dict_in_foreach1"),
610+
# State Var dict in a foreach
611+
rx.box(
612+
rx.foreach(VarOperationState.dict1, rx.text.span),
613+
id="dict_in_foreach2",
614+
),
615+
rx.box(
616+
rx.foreach(
617+
VarOperationState.dict1.merge(VarOperationState.dict2),
618+
rx.text.span,
619+
),
620+
id="dict_in_foreach3",
621+
),
608622
)
609623

610624

@@ -809,6 +823,9 @@ def test_var_operations(driver, var_operations: AppHarness):
809823
("range_in_foreach2", "42454851545760636669727578"),
810824
("range_in_foreach3", "42363024"),
811825
("range_in_foreach4", "42"),
826+
("dict_in_foreach1", "a1b2"),
827+
("dict_in_foreach2", "12"),
828+
("dict_in_foreach3", "1234"),
812829
]
813830

814831
for tag, expected in tests:

tests/units/components/core/test_foreach.py

+8-8
Original file line numberDiff line numberDiff line change
@@ -170,32 +170,32 @@ def display_color_index_tuple(color):
170170
ForEachState.primary_color,
171171
display_primary_colors,
172172
{
173-
"iterable_state": f"{ForEachState.get_full_name()}.primary_color",
174-
"iterable_type": "dict",
173+
"iterable_state": f"Object.entries({ForEachState.get_full_name()}.primary_color)",
174+
"iterable_type": "list",
175175
},
176176
),
177177
(
178178
ForEachState.color_with_shades,
179179
display_color_with_shades,
180180
{
181-
"iterable_state": f"{ForEachState.get_full_name()}.color_with_shades",
182-
"iterable_type": "dict",
181+
"iterable_state": f"Object.entries({ForEachState.get_full_name()}.color_with_shades)",
182+
"iterable_type": "list",
183183
},
184184
),
185185
(
186186
ForEachState.nested_colors_with_shades,
187187
display_nested_color_with_shades,
188188
{
189-
"iterable_state": f"{ForEachState.get_full_name()}.nested_colors_with_shades",
190-
"iterable_type": "dict",
189+
"iterable_state": f"Object.entries({ForEachState.get_full_name()}.nested_colors_with_shades)",
190+
"iterable_type": "list",
191191
},
192192
),
193193
(
194194
ForEachState.nested_colors_with_shades,
195195
display_nested_color_with_shades_v2,
196196
{
197-
"iterable_state": f"{ForEachState.get_full_name()}.nested_colors_with_shades",
198-
"iterable_type": "dict",
197+
"iterable_state": f"Object.entries({ForEachState.get_full_name()}.nested_colors_with_shades)",
198+
"iterable_type": "list",
199199
},
200200
),
201201
(

0 commit comments

Comments
 (0)