# Images not updating order in custom block preview

**URL:** <https://forum.umbraco.com/t/images-not-updating-order-in-custom-block-preview/6582>\
**Category:** Questions\
**Tags:** extending, bellissima, v16\
**Created:** [November 4, 2025, 4:50pm UTC](https://forum.umbraco.com/t/images-not-updating-order-in-custom-block-preview/6582 "2025-11-04T16:50:13Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![warren](https://forum.umbraco.com/user_avatar/forum.umbraco.com/warren/32/78_2.png) [@warren](https://forum.umbraco.com/u/warren)\
**Post date:** [November 4, 2025, 4:50pm UTC](https://forum.umbraco.com/t/images-not-updating-order-in-custom-block-preview/6582/1 "2025-11-04T16:50:13Z")

</div>

Hello 👋  
I am currently building a custom view for an item in the block grid in Bellissima (aka WebComponent era of the Umbraco backoffice)

I have a simple element/block type that contains two properties

- Heading (Textstring)
- Images (Media Picker - Limited to a max of two images)

## Problem

When changing the order of the images in the media picker it does not update the images displayed, however printing the two GUID/Keys of the picked media items correctly display and update in the component.

## Video

## Questions

- Should I be using `umb-imaging-thumbnail` to help render out the picked image or using an alternative approach with some context that I need to consume to resolve/convert the picked GUID to an image URL ?

- Why when I drag and drop and change the order of the images or pick a new image to replace one, that it does not update the image rendered with `<umb-imaging-thumbnail>`?

## Code

**manifest.ts**

```typescript
export const manifests: Array<UmbExtensionManifest> = [
    {
        name: "Block Preview - Images",
        alias: "blockpreview.images",
        type: "blockEditorCustomView",
        forContentTypeAlias: "imagesBlock",
        js: () => import("./images-block"),
    }
];

```

**images-block.ts**

```ts
import { html, customElement, LitElement, property, css, when } from '@umbraco-cms/backoffice/external/lit';
import { UmbElementMixin } from '@umbraco-cms/backoffice/element-api';
import { type UmbBlockDataType } from '@umbraco-cms/backoffice/block';
import type { UmbBlockEditorCustomViewConfiguration, UmbBlockEditorCustomViewElement } from '@umbraco-cms/backoffice/block-custom-view';
import { commonStyles } from './common-styles';

@customElement('images-block-custom-view')
export class ImagesBlockCustomView extends UmbElementMixin(LitElement) implements UmbBlockEditorCustomViewElement {
	
	@property({ attribute: false })
	content?: UmbBlockDataType & {
        images: Array<{ mediaKey: string }>;
    }

    @property({ attribute: false })
    label?: string;

	@property({ attribute: false })
	settings?: UmbBlockDataType;

    @property({ attribute: false })
    config?: UmbBlockEditorCustomViewConfiguration;

    constructor() {
        super();
    }

	render() {
        const leftImageMediaKey = this.content?.images?.[0]?.mediaKey ?? '';
        const rightImageMediaKey = this.content?.images?.[1]?.mediaKey ?? '';

		return html`
            <fieldset>
                <legend>${this.label ?? 'Images'}</legend>
                <a href=${this.config?.editContentPath ?? ''} class="edit">
                    <figure>
                        <h2>${this.content?.heading}</h2>

                        <pre>
                            Left = ${leftImageMediaKey}
                            Right = ${rightImageMediaKey}
                        </pre>

                        <div id="grid">
                            <div>
                                 ${when(
                                    leftImageMediaKey,
                                    () => html`<umb-imaging-thumbnail .unique=${leftImageMediaKey!} width="600" mode="Crop"></umb-imaging-thumbnail>`,
                                    () => html`<p>No image selected</p>`
                                )}
                            </div>
                            <div>
                                ${when(
                                    rightImageMediaKey,
                                    () => html`<umb-imaging-thumbnail .unique=${rightImageMediaKey!} width="600" mode="Crop"></umb-imaging-thumbnail>`,
                                    () => html`<p>No image selected</p>`
                                )}
                            </div>
                        </div>
                    </figure>
                </a>
            </fieldset>

            <!-- <pre>${JSON.stringify(this.content, null, 2)}</pre> -->
		`;
	}

	static styles = [
        commonStyles,
		css`
            h2 {
                color: var(--colour-black);
                font-family: var(--font-family-bravo);
                font-size: var(--font-size-heading-3);

                text-align: center;
            }

            #grid {
                display:grid;
                grid-template-columns: 1fr 1fr;
                gap: 24px;

                div {
                    background: var(--colour-grey--mid-light);
                }

                p {
                    text-align: center;
                }
            }
		`,
	];
	
}
export default ImagesBlockCustomView;

declare global {
	interface HTMLElementTagNameMap {
		'images-block-custom-view': ImagesBlockCustomView;
	}
}

```

---

<div class="post-metadata">

**Author:** ![warren](https://forum.umbraco.com/user_avatar/forum.umbraco.com/warren/32/78_2.png) [@warren](https://forum.umbraco.com/u/warren)\
**Post date:** [November 5, 2025, 4:24pm UTC](https://forum.umbraco.com/t/images-not-updating-order-in-custom-block-preview/6582/2 "2025-11-05T16:24:58Z")

</div>

## Update

Well poking around the code, I stumbled across more things such as:

- `#imagingRepository = new UmbImagingRepository(this);`
- A store context `UMB_IMAGING_STORE_CONTEXT`
- `#mediaRepository = new UmbMediaUrlRepository(this);`

I tried some of these and in the end I went with newing up a `UmbMediaUrlRepository` and was then able to give it an array of GUIDs to request and get information about the media item URLs.

## Approach

```typescript
#mediaRepository = new UmbMediaUrlRepository(this);
...

const mediaKeys = ['4500f413-253d-4204-a047-cd5e2170cf58', '01b17128-82c3-48d3-a84a-58cb5623c174'];
const mediaItemsObservable = await (await this.#mediaRepository.requestItems(mediaKeys)).asObservable();

this.observe(mediaItemsObservable, (mediaItems) => {
   console.log('Media Items', mediaItems);
});

```

## Solution

This is the approach I took in the end. If this is the **right** solution I am not 100% sure, but it works.

**images-block.ts**

```typescript
import { html, customElement, LitElement, property, css, when, state } from '@umbraco-cms/backoffice/external/lit';
import { UmbElementMixin } from '@umbraco-cms/backoffice/element-api';
import { type UmbBlockDataType } from '@umbraco-cms/backoffice/block';
import type { UmbBlockEditorCustomViewConfiguration, UmbBlockEditorCustomViewElement } from '@umbraco-cms/backoffice/block-custom-view';
import { commonStyles } from './common-styles';
import { UmbMediaUrlRepository } from '@umbraco-cms/backoffice/media';

@customElement('images-block-custom-view')
export class ImagesBlockCustomView extends UmbElementMixin(LitElement) implements UmbBlockEditorCustomViewElement {
	
	@property({ attribute: false })
	content?: UmbBlockDataType & {
        images: Array<{ mediaKey: string }>;
    }

    @property({ attribute: false })
    label?: string;

	@property({ attribute: false })
	settings?: UmbBlockDataType;

    @property({ attribute: false })
    config?: UmbBlockEditorCustomViewConfiguration;

    @state()
    private _mediaUrlMap: Map<string, string> = new Map();

    #mediaRepository = new UmbMediaUrlRepository(this);

    constructor() {
        super();
    }

    updated(changedProperties: Map<string | number | symbol, unknown>) {
        super.updated(changedProperties);
        
        if (changedProperties.has('content')) {
            const mediaKeys = [this.content?.images?.[0]?.mediaKey!, this.content?.images?.[1]?.mediaKey!].filter(key => key !== undefined);
            this.#loadMediaItems(mediaKeys);
        }
    }

    async #loadMediaItems(mediaKeys: string[]) {
        try {
            const mediaItemsObservable = await (await this.#mediaRepository.requestItems(mediaKeys)).asObservable();
            this.observe(mediaItemsObservable, (mediaItems) => {
                if (!mediaItems) return;

                // Create a map of media key to URL
                const newMediaUrlMap = new Map<string, string>();
                mediaItems.forEach(mediaItem => {
                    if (mediaItem.unique && mediaItem.url) {
                        newMediaUrlMap.set(mediaItem.unique, mediaItem.url);
                    }
                });
                
                this._mediaUrlMap = newMediaUrlMap;
            });
        } catch (error) {
            console.error('Error loading media items:', error);
            this._mediaUrlMap = new Map();
        }
    };

    #getMediaUrl(mediaKey: string): string {
        return this._mediaUrlMap.get(mediaKey) || '';
    }

	render() {
        const leftImageUrl = this.#getMediaUrl(this.content?.images?.[0]?.mediaKey || '');
        const rightImageUrl = this.#getMediaUrl(this.content?.images?.[1]?.mediaKey || '');

		return html`
            <fieldset>
                <legend>${this.label ?? 'Images'}</legend>
                <a href=${this.config?.editContentPath ?? ''} class="edit">
                    <figure>
                        <h2>${this.content?.heading}</h2>

                        <div id="grid">
                            <div class="img-container">
                                 ${when(
                                    leftImageUrl,
                                    () => html`<img src="${leftImageUrl}" />`,
                                    () => html`<p>No image selected</p>`
                                )}
                            </div>
                            <div class="img-container">
                                ${when(
                                    rightImageUrl,
                                    () => html`<img src="${rightImageUrl}" />`,
                                    () => html`<p>No image selected</p>`
                                )}
                            </div>
                        </div>
                    </figure>
                </a>
            </fieldset>

            <!-- <pre>${JSON.stringify(this.content, null, 2)}</pre> -->
        `;
	}

	static styles = [
        commonStyles,
		css`
            h2 {
                color: var(--colour-black);
                font-family: var(--font-family-bravo);
                font-size: var(--font-size-heading-3);

                text-align: center;
            }

            #grid {
                display:grid;
                grid-template-columns: 1fr 1fr;
                gap: 24px;
            }

            .img-container {
                background: var(--colour-grey--mid-light);
                height: 300px; /* Fixed height for all containers */
                overflow: hidden;
                display: flex;
                align-items: center;
                justify-content: center;
            }

            .img-container img {
                width: 100%;
                height: 100%;
                object-fit: cover; /* Crops to fill container while maintaining aspect ratio */
            }

            .img-container p {
                text-align: center;
                margin: 0;
            }
		`,
	];
	
}
export default ImagesBlockCustomView;

declare global {
	interface HTMLElementTagNameMap {
		'images-block-custom-view': ImagesBlockCustomView;
	}
}

```

---

<div class="post-metadata">

**Author:** ![warren](https://forum.umbraco.com/user_avatar/forum.umbraco.com/warren/32/78_2.png) [@warren](https://forum.umbraco.com/u/warren)\
**Post date:** [November 7, 2025, 2:18pm UTC](https://forum.umbraco.com/t/images-not-updating-order-in-custom-block-preview/6582/3 "2025-11-07T14:18:41Z")

</div>

Was reminded about @nielslyngsoe demo site from CodeGarden  
His approach is to use the lifecycle event `willUpdate` along with the `UmbImagingRepository` like so by asking for a LARGE thumbnail/resized image at 1000 by 1000.

Interesting to see how Niels solved this and I may change my code to use the **willUpdate** lifecycle event as opposed to **updated**

> <https://github.com/nielslyngsoe/cg25-umbrago-next-level-backoffice/blob/main/CG25NextLevelBackoffice/Client/src/blocks/image-block/image-block-custom-view.ts#L32-L47>
