SVG Chooser Block Fix Plan
Documents a bug where SVG selections vanish on re-save and lists the root causes and fixes applied.
What this file does
Documents a bug where SVG selections vanish on re-save and lists the root causes and fixes applied.
When to use it
- Debugging a Wagtail chooser widget that loses state after page reload
- Fixing a StreamField block that drops its value on re-save
- Understanding how to align custom chooser templates with Wagtail's standard interface
- Troubleshooting message type mismatches in Wagtail chooser JavaScript
Assumes this stack
SVG Chooser Block Fix Plan
Problem Description
The SVG chooser block allows selecting an SVG file and saving it once, but when saving again, the SVG is removed from the page as if it was left blank. This suggests the JavaScript/code doesn't maintain the previous file context after page reload.
Investigation Steps
- Analyze the current codebase structure - Understand how the SVG chooser block works
- Examine the widget implementation - Check the AdminSvgChooser widget for state management issues
- Review form state handling - Investigate how form state is preserved between saves
- Check JavaScript functionality - Look for client-side code that might be clearing the selection
- Test the current behavior - Run the application to reproduce the issue
- Identify the root cause - Determine why the SVG selection is lost on subsequent saves
- Implement the fix - Apply the necessary changes to maintain state
- Test the fix - Verify the issue is resolved
Current Status
- Initial investigation started
- Root cause identified
- Fix implemented
- Testing completed
Findings
-
Widget State Issue: The
render_htmlmethod inAdminSvgChooserconverts empty string values toNone, which may cause the widget to lose its state on subsequent saves. -
Message Type Mismatch: The chooser templates are using a custom message type
'svg_chooser:choose'but Wagtail's standard chooser expects a different message format. -
Value Data Handling: The
get_value_datamethod returns empty string for "value" when instance is None, butrender_htmlconverts this toNone, potentially causing state loss. -
Debug Logging: There's already debug logging in place that shows the issue - the
value_from_datadictmethod is being called and should help identify when values are being lost. -
CRITICAL: Block Form State Issue: The
SvgChooserBlock.get_form_statemethod was returning a processed value_data dictionary instead of the raw value (SVG ID). This caused StreamFields to lose the SVG selection on re-save because the widget expected the raw ID value, not a processed dictionary.
Solution
-
Fixed Widget State Issue: Removed the conversion of empty string to
Nonein therender_htmlmethod. The widget now preserves the original value fromget_value_datato maintain state between saves. -
Fixed Message Type Mismatch: Updated the chooser templates to use the standard Wagtail message type
'chooser:choose'instead of the custom'svg_chooser:choose'type. -
Improved Debug Logging: Enhanced the debug logging in both
get_value_dataandvalue_from_datadictmethods to better track state changes. -
Fixed URL References: Updated the chooser templates to use the correct URL namespace
'wagtailsvg:edit'instead of'svg_chooser:edit'. -
Fixed Template Inheritance: Updated chooser templates to properly extend Wagtail's base chooser templates (
wagtailadmin/generic/chooser/choose.htmlandwagtailadmin/generic/chooser/results.html). -
Switched to Standard Chooser Interface: Disabled custom chooser templates and switched to using Wagtail's standard chooser interface, which handles JavaScript communication properly.
-
Fixed JavaScript Constructor: Updated the widget's
js_constructorto use the standard Wagtail chooser constructor. -
Added Missing Methods: Added
get_instanceandget_chooser_modal_urlmethods to ensure proper widget functionality. -
Enhanced Block Value Handling: Added
value_from_formmethod to the block to properly handle form value conversion. -
CRITICAL FIX: Fixed Block Form State: Fixed the
get_form_statemethod to return the raw SVG ID instead of a processed value_data dictionary. This was the root cause of the StreamField state loss issue. -
Enhanced Error Handling: Added proper error handling in
get_form_stateto handle various input types (None, empty string, invalid values) gracefully. -
Added Database Value Conversion: Added
to_python,get_prep_value, andget_db_prep_valuemethods to ensure proper value conversion during database operations.
The root cause was that the widget was converting empty string values to None in the render_html method, which caused the widget to lose its state on subsequent saves. Additionally, the chooser templates were not properly extending the base Wagtail chooser templates, which could cause JavaScript communication issues. Most critically, the SvgChooserBlock.get_form_state method was returning a processed dictionary instead of the raw value, causing StreamFields to lose SVG selections on re-save. By preserving the original value, fixing the message type, ensuring proper template inheritance, and fixing the block's form state handling, the chooser should now maintain its state correctly.
What's inside
Problem description, 8 investigation steps, 5 findings, 12 solution items, status checklist
Change this for your project
- Replace
'wagtailsvg:edit'with your own URL namespace - Replace
'svg_chooser:choose'with your custom message type - Replace
AdminSvgChooserandSvgChooserBlockclass names with your own - Replace
wagtailsvgapp label with your app's label
Where it goes
A standard operating procedure. Keep where the team or agent running the process will find it.
Worth borrowing
- Check
render_htmlfor unintended empty-to-None conversion that drops state - Ensure
get_form_statereturns the raw value (e.g., ID) not a processed dictionary - Use Wagtail's standard chooser templates and message types instead of custom ones
Related Documents
Comprehensive AI Assistant Tools Reference
Lists 80+ tools with MCP server associations, bulk support, parallel capability, resource impact, and execution type for AI agent workflows.
iOS Deployment Guide
Walks through setting up an iOS development environment, building a Tauri app for iOS, and publishing to the App Store or alternative channels.
How to Add Resources to Your FastMCP Server
Teaches how to add static and dynamic MCP resources to a FastMCP server, with six ready-to-copy examples for a GitHub crawler.
PCI Compliance Guide
Explains PCI DSS compliance via tokenization, lists forbidden and allowed data, and provides code examples for BigCommerce and Stripe.