diff --git a/core-web/libs/edit-content/src/lib/fields/dot-edit-content-file-field/components/dot-file-field/dot-file-field.component.spec.ts b/core-web/libs/edit-content/src/lib/fields/dot-edit-content-file-field/components/dot-file-field/dot-file-field.component.spec.ts index d483e45b992e..302e62add588 100644 --- a/core-web/libs/edit-content/src/lib/fields/dot-edit-content-file-field/components/dot-file-field/dot-file-field.component.spec.ts +++ b/core-web/libs/edit-content/src/lib/fields/dot-edit-content-file-field/components/dot-file-field/dot-file-field.component.spec.ts @@ -195,6 +195,43 @@ describe('DotFileFieldComponent', () => { expect(applySpy).toHaveBeenCalledWith(EDITED_TEMP_FILE); }); + it('should use the injected fieldVariable when the Binary preview is hydrated from the parent contentlet', () => { + mockImageEditorLauncher.isAvailable.mockReturnValue(true); + mockImageEditorLauncher.open.mockReturnValue(of(EDITED_TEMP_FILE)); + spectator = createComponent({ + props: { + field: BINARY_FIELD_MOCK, + contentlet: createFakeContentlet({ [BINARY_FIELD_MOCK.variable]: null }), + hasError: false + } as never + }); + spectator.detectChanges(); + + spectator.component.store.setPreviewFile({ + source: 'contentlet', + file: { + ...createFakeContentlet({}), + inode: 'parent-inode', + // The parent's titleImage points at a reference field with no binary; + // the editor must use the field variable injected by the store instead + titleImage: 'image', + fieldVariable: BINARY_FIELD_MOCK.variable, + metaData: { isImage: true, contentType: 'image/png', name: 'img.png' } + } + } as never); + spectator.detectChanges(); + + spectator.component.onEditImage(); + + expect(mockImageEditorLauncher.open).toHaveBeenCalledWith( + expect.objectContaining({ + inode: 'parent-inode', + variable: BINARY_FIELD_MOCK.variable, + fieldName: BINARY_FIELD_MOCK.variable + }) + ); + }); + it('should fall back to the legacy editor when the new launcher is unavailable', () => { mockImageEditorLauncher.isAvailable.mockReturnValue(false); setupBinaryWithImage(); diff --git a/core-web/libs/edit-content/src/lib/fields/dot-edit-content-file-field/components/dot-file-field/dot-file-field.component.ts b/core-web/libs/edit-content/src/lib/fields/dot-edit-content-file-field/components/dot-file-field/dot-file-field.component.ts index 9b1f531332eb..e4fa60146753 100644 --- a/core-web/libs/edit-content/src/lib/fields/dot-edit-content-file-field/components/dot-file-field/dot-file-field.component.ts +++ b/core-web/libs/edit-content/src/lib/fields/dot-edit-content-file-field/components/dot-file-field/dot-file-field.component.ts @@ -400,12 +400,15 @@ export class DotFileFieldComponent // unsaved draft that has no uploaded file yet fall back to the parent. const inode = uploaded?.source === 'contentlet' ? uploaded.file.inode : this.$contentlet()?.inode; - // For a standalone contentlet (e.g. AI-generated image) the image lives in - // its own field (titleImage), not in the parent binary field variable. - // The JSP uses this as fieldName to load /contentAsset/image/{inode}/{field}/. + // Resolve the field that actually holds the binary for /contentAsset/image/{inode}/{field}/: + // - Binary hydrated from the parent contentlet (setFileFromContentlet) injects + // `fieldVariable` — the parent's titleImage would point at an unrelated + // reference field with no binary (404). + // - Standalone assets (dotAsset via getAssetData, AI-generated) carry no + // fieldVariable; their image lives in their own titleImage field. const editorVariable = uploaded?.source === 'contentlet' - ? String(uploaded.file['titleImage'] ?? variable) + ? String(uploaded.file['fieldVariable'] ?? uploaded.file['titleImage'] ?? variable) : variable; // Prefer the new Angular image editor when its launcher is provided (Angular