Skip to content

Commit 5d4e674

Browse files
author
User
committed
Fix #270: Preserve multi-select selection state on form re-render
The _find_selected_options transform was stripping the 'selected' attribute from <option> elements and relying solely on defaultValue on the <select> element. This works on initial mount (Preact applies defaultValue once), but on re-render after form submission, Preact only diffs attributes — it does not re-apply defaultValue. Since the selected attribute had been removed from <option> elements, Preact had no way to know which options should be selected, and the form lost all multi-select selections after submission. Fix: keep the selected attribute on <option> elements. defaultValue is still set on <select> for initial mount compatibility, but selected on <option> ensures re-renders correctly restore state.
1 parent 3f59f80 commit 5d4e674

1 file changed

Lines changed: 9 additions & 2 deletions

File tree

‎src/reactpy_django/forms/transforms.py‎

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,15 @@ def infer_key_from_attributes(vdom_tree: VdomDict) -> VdomDict:
8989

9090
def _find_selected_options(vdom_node: Any) -> list[str]:
9191
"""Recursively iterate through the tree to find all <option> tags with the 'selected' prop.
92-
Removes the 'selected' prop and returns a list of the 'value' prop of each selected <option>."""
92+
Returns a list of the 'value' prop of each selected <option>.
93+
94+
.. note::
95+
We intentionally do **not** remove the ``selected`` prop from the ``<option>`` elements.
96+
The ``defaultValue`` attribute is already set on the ``<select>`` element for initial
97+
mount in React/Preact, but it is only applied once (on mount). Keeping ``selected``
98+
on the ``<option>`` elements ensures that selection state is correctly restored after
99+
the form is re-rendered (e.g. after a form submission that does not trigger a full
100+
Preact remount)."""
93101
if not isinstance(vdom_node, dict):
94102
return []
95103

@@ -98,7 +106,6 @@ def _find_selected_options(vdom_node: Any) -> list[str]:
98106
value = vdom_node["attributes"].setdefault("value", vdom_node["children"][0])
99107

100108
if "selected" in vdom_node["attributes"]:
101-
vdom_node["attributes"].pop("selected")
102109
selected_options.append(value)
103110

104111
for child in vdom_node.get("children", []):

0 commit comments

Comments
 (0)