Improve instance form errors #173

Merged
tobru merged 3 commits from 164-keep-values-on-error into main 2025-09-12 07:21:30 +00:00
2 changed files with 42 additions and 12 deletions
Showing only changes of commit 1a2a75880d - Show all commits

View file

@ -48,18 +48,31 @@ class DynamicArrayWidget(forms.Widget):
def value_from_datadict(self, data, files, name): def value_from_datadict(self, data, files, name):
value = data.get(name) value = data.get(name)
if value: if value is None:
return []
if value == "":
return []
if isinstance(value, list):
return [item for item in value if item is not None and str(item).strip()]
if isinstance(value, str):
if value.strip() == "" or value.strip().lower() == "null":
return []
try: try:
parsed = json.loads(value) parsed = json.loads(value)
if parsed: if parsed is None:
return []
if isinstance(parsed, list):
return [ return [
item item
for item in parsed for item in parsed
if item is not None and str(item).strip() if item is not None and str(item).strip()
] ]
return [] return [parsed] if str(parsed).strip() else []
except (json.JSONDecodeError, TypeError): except (json.JSONDecodeError, TypeError):
pass return [value] if value.strip() else []
return [] return []
@ -104,11 +117,17 @@ class DynamicArrayField(forms.JSONField):
if value is None: if value is None:
return [] return []
if isinstance(value, list): if isinstance(value, list):
return value return [item for item in value if item is not None]
if isinstance(value, str): if isinstance(value, str):
if value.strip() == "" or value.strip().lower() == "null":
return []
try: try:
parsed = json.loads(value) parsed = json.loads(value)
return parsed if isinstance(parsed, list) else [parsed] if parsed is None:
return []
if isinstance(parsed, list):
return [item for item in parsed if item is not None]
return [parsed]
except (json.JSONDecodeError, TypeError): except (json.JSONDecodeError, TypeError):
return [value] if value else [] return [value] if value else []
return [str(value)] return [str(value)]
@ -117,16 +136,24 @@ class DynamicArrayField(forms.JSONField):
"""Handle bound data properly to avoid JSON parsing issues""" """Handle bound data properly to avoid JSON parsing issues"""
if data is None: if data is None:
return initial return initial
# If data is already a list (from our widget), return it as-is
if isinstance(data, list): if isinstance(data, list):
return data return [item for item in data if item is not None and str(item).strip()]
# If data is a string, try to parse it as JSON
if isinstance(data, str): if isinstance(data, str):
if data.strip() == "" or data.strip().lower() == "null":
return []
try: try:
parsed = json.loads(data) parsed = json.loads(data)
return parsed if isinstance(parsed, list) else [parsed] if parsed is None:
return []
if isinstance(parsed, list):
return [
item
for item in parsed
if item is not None and str(item).strip()
]
return [parsed] if str(parsed).strip() else []
except (json.JSONDecodeError, TypeError): except (json.JSONDecodeError, TypeError):
return [data] if data else [] return [data] if data and data.strip() else []
return data return data
def validate(self, value): def validate(self, value):

View file

@ -19,6 +19,9 @@ const initDynamicArrayWidget = () => {
addRemoveEventListeners(container) addRemoveEventListeners(container)
addInputEventListeners(container) addInputEventListeners(container)
updateRemoveButtonVisibility(container) updateRemoveButtonVisibility(container)
// Ensure hidden input is synced with visible inputs on initialization
updateHiddenInput(container)
}) })
} }
@ -94,7 +97,7 @@ const updateHiddenInput = (container) => {
if (!hiddenInput) return if (!hiddenInput) return
const values = Array.from(inputs) const values = Array.from(inputs)
.map(input => input.value.trim()) .map(input => input.value ? input.value.trim() : '')
.filter(value => value !== '') .filter(value => value !== '')
hiddenInput.value = JSON.stringify(values) hiddenInput.value = JSON.stringify(values)