Skip to content

Fix #270: Resolve django_form limitations for multi-value and multi-select fields#298

Open
Archmonger wants to merge 6 commits into
mainfrom
fix-270
Open

Fix #270: Resolve django_form limitations for multi-value and multi-select fields#298
Archmonger wants to merge 6 commits into
mainfrom
fix-270

Conversation

@Archmonger

@Archmonger Archmonger commented Jul 19, 2026

Copy link
Copy Markdown
Contributor

Description

Fix (partial) #270 by resolving two categories of django_form limitations:

1. FormData serialization bug (MultipleChoiceField data loss)

Object.fromEntries(formData.entries()) silently drops duplicate keys, causing MultipleChoiceField and ModelMultipleChoiceField to lose all values except the last selected option. Replaced with a manual loop that accumulates duplicate keys into FormDataEntryValue[] arrays.

2. Robust convert_form_fields normalization

Improved convert_form_fields() to properly handle edge cases:

  • None values from unselected multi-select fields → []
  • Single values → [value]
  • Already-list values → unchanged

3. Test coverage for multi-value fields

Added SplitDateTimeField and MultiValueField to BasicForm in the test app for regression coverage.

Checklist

  • Tests have been developed for bug fixes or new functionality.
  • The changelog has been updated, if necessary.
  • Documentation has been updated, if necessary.
  • GitHub Issues closed by this PR have been linked.

By submitting this pull request I agree that all contributions comply with this project's open source license(s).

…delMultipleChoiceField

- Updated `components.ts` to accumulate duplicate FormData entries into arrays
  instead of silently dropping duplicates (as Object.fromEntries would do).
- Updated `utils.py` convert_form_fields() to normalize MultipleChoiceField
  and ModelMultipleChoiceField values (absent/None -> empty list, single -> array).
- Updated test forms to include MultipleChoiceField and
  ModelMultipleChoiceField in BasicForm and BootstrapForm for regression coverage.
@Archmonger
Archmonger requested a review from a team as a code owner July 19, 2026 21:56
Archmonger pushed a commit that referenced this pull request Jul 20, 2026
…d-trip assertions

Following code review suggestions for PR #298:
- New test_forms_utils.py: 10 unit tests covering None->[], single->[value],
  list->unchanged for MultipleChoiceField, ModelMultipleChoiceField,
  BooleanField/NullBooleanField, and CharField pass-through.
- test_form_basic: explicit input_value assertions on multi-select and
  model multi-select fields after successful form submission, proving
  the FormData duplicate-key fix works end-to-end.
- Fix pre-existing ruff import ordering issue in utils.py
…d-trip assertions

Following code review suggestions for PR #298:
- New test_forms_utils.py: 10 unit tests covering None->[], single->[value],
  list->unchanged for MultipleChoiceField, ModelMultipleChoiceField,
  BooleanField/NullBooleanField, and CharField pass-through.
- test_form_basic: explicit input_value assertions on multi-select and
  model multi-select fields after successful form submission, proving
  the FormData duplicate-key fix works end-to-end.
- Fix pre-existing ruff import ordering issue in utils.py
@Archmonger
Archmonger force-pushed the fix-270 branch 3 times, most recently from 11be5bf to de12ba0 Compare July 21, 2026 16:04
The set_value_prop_on_select_element transform previously stripped
the selected attribute from option elements, relying solely on
defaultValue for restoring selection. Preact does not re-apply
defaultValue on re-render, so selection was lost after form
submission.

Fix: stop stripping selected from option elements so Preact can
restore selection correctly during reconciliation. The defaultValue
attribute is still set for initial mount compatibility.

Also removed the recently added split_datetime_field and
multi_value_field from the test form since MultiValueField has
an abstract compress() that raises NotImplementedError on empty
submission. Multi-value form field coverage is better tested by
MultipleChoiceField which is already present.
Preact/React does not reliably restore <select multiple> selection
state during in-place reconciliation of option children. Force a
complete unmount/remount of the <form> element by using a volatile
React key that increments each time submitted_data triggers a
re-render.

This ensures defaultValue is applied on mount and that the DOM
select element starts fresh with the correct selection.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant