Skip to content

Pass the stored value to nested editors when saving a block - #111

Open
talhamalik4025 wants to merge 1 commit into
PerplexDigital:masterfrom
talhamalik4025:fix/nested-file-editors-current-value
Open

talhamalik4025 wants to merge 1 commit into
PerplexDigital:masterfrom
talhamalik4025:fix/nested-file-editors-current-value

Conversation

@talhamalik4025

Copy link
Copy Markdown
Contributor

Fixes #110

ContentBlocksValueEditor.FromEditor passed each nested property's incoming editor value as currentValue. File-based editors (Image Cropper, File Upload) use currentValue to find the existing file, so clearing an image in a block left the file on disk and stored the text "null", after which Actions → Publish… failed with a 500.

This matches the stored blocks by id and their values by alias, as Umbraco's own block editors do (BlockValuePropertyValueEditorBase.MapBlockItemDataFromEditor), and passes the stored value.

Tested on Umbraco 17.7.1 with this branch built from source, on a page with one block keeping its image and one clearing it:

Before After
Clear file(s), Save and publish stores "null"; file stays on disk stores null; file deleted
Actions → Publish… 500 200

The other block's image, its file and its text values are unchanged. A later save with no edits still stores "null" through Umbraco's own cropper code (umbraco/Umbraco-CMS#24335), which this PR doesn't touch.

Not included: Umbraco also deletes the files of blocks that are removed entirely. Happy to add that here or in a follow-up.

Each nested value went through FromEditor with the incoming editor value
as currentValue. Editors that store a file (Image Cropper, File Upload)
use currentValue to find the existing file, so clearing one inside a
block left the file behind and stored the text "null", after which
publishing the page failed. Look up the stored block by id and its value
by alias and pass that instead, mirroring Umbraco core's
BlockValuePropertyValueEditorBase.MapBlockItemDataFromEditor.

Fixes PerplexDigital#110

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@talhamalik4025
talhamalik4025 marked this pull request as ready for review October 26, 2026 19:05
PropertyTypeKey = prop.PropertyType.Key,
};
prop.Value = valueEditor.FromEditor(propData, prop.Value);
var currentPropValue = currentData?.Values.FirstOrDefault(current => current.Alias == prop.Alias)?.Value;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's hard for me to oversee the consequences of this where you change from prop.Value to currentPropValue. Will this not introduce regressions with other property editors that do not need this fix to begin with? I don't know the answer here either but I am a bit hesitant to update this very import method without knowing the possible effects of this change.

@talhamalik4025

Copy link
Copy Markdown
Contributor Author

Thanks for looking at it, fair question. I went through every value editor in Umbraco 17.7.1 that overrides FromEditor. The links below are pinned to the release-17.7.1 commit.

Before this change, nested editors never saw the stored value. propData is built from prop.Value, and the same prop.Value is passed as currentValue (ContentBlocksValueEditor.cs#L123-L128), so currentValue was always the incoming value.

Everywhere else in Umbraco, currentValue is the stored value:

Most editors never read it. 13 of the 21 core overrides don't reference currentValue at all (list below). Date Time, Date Time (new), Media Picker and Multi URL Picker only pass it on to base.FromEditor; their base is DataValueEditor, whose FromEditor ignores it (DataValueEditor.cs#L164-L175).

The editors that do read it expect the stored value:

A new block, or a property the stored block doesn't have, gets null, as a new document does.

So the change only affects editors that read currentValue, and gives them what Umbraco passes them everywhere else. An editor that depended on getting the incoming value would already misbehave as a document property or inside a Block List. In the test in the description, the other block's image, its file and its text values were unchanged.

The 13 core overrides that never read currentValue

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.

Clearing an Image Cropper inside a block stores "null" and leaves the uploaded file behind

2 participants