When using custom views for blocks, the content in view is by default not clickable and possible to open/edit block.
However it has entity action, which can we used.
We can wrap inside umb-ref-grid-block or umb-ref-item and use href propery for these, but it may not look nice as it as it add an icon and it this case image/content wasn’t clickable.
I found we can just use <a> using href:
import { html, css, customElement, LitElement, property, state } from '@umbraco-cms/backoffice/external/lit';
import { UmbElementMixin } from '@umbraco-cms/backoffice/element-api';
import { UmbImagingRepository } from '@umbraco-cms/backoffice/imaging';
import { type PropertyValueMap } from '@umbraco-cms/backoffice/external/lit';
import type { UmbBlockEditorCustomViewElement, UmbBlockEditorCustomViewConfiguration } from '@umbraco-cms/backoffice/block-custom-view';
import type { UmbBlockDataType } from '@umbraco-cms/backoffice/block';
import type { UmbMediaPickerPropertyValueEntry } from '@umbraco-cms/backoffice/media';
@customElement('mcb-image-block-view')
export class McbImageBlockView extends UmbElementMixin(LitElement) implements UmbBlockEditorCustomViewElement {
@property({ attribute: false })
config?: UmbBlockEditorCustomViewConfiguration;
@property({ attribute: false })
content?: UmbBlockDataType;
@state()
imageUrls: Map<string, string> = new Map();
@state()
images: UmbMediaPickerPropertyValueEntry[] = [];
#imagingRepository = new UmbImagingRepository(this);
// Watch for content updates
updated(changedProperties: PropertyValueMap<any> | Map<PropertyKey, unknown>): void {
super.updated?.(changedProperties);
if (changedProperties.has('content') && this.content?.image) {
this.images = this.content.image as UmbMediaPickerPropertyValueEntry[];
this._fetchImageUrls();
}
}
async _fetchImageUrls() {
for (const item of this.images) {
if (item.mediaKey && !this.imageUrls.has(item.mediaKey)) {
const url = await this._resolveImageUrl(item.mediaKey);
if (url) {
this.imageUrls.set(item.mediaKey, url);
this.requestUpdate(); // Trigger re-render
}
}
}
}
async _resolveImageUrl(mediaKey: string): Promise<string> {
try {
const { data } = await this.#imagingRepository.requestThumbnailUrls([mediaKey], 1200, 0);
return data?.[0]?.url ?? '';
} catch (err) {
console.warn('Failed to load media URL for:', mediaKey, err);
return '';
}
}
render() {
if (!this.content?.image) {
return html`<em>No image selected</em>`;
}
return html`
<a href=${(this.config?.showContentEdit ? this.config?.editContentPath : undefined) ?? ''}>
<div class="image-block">
${this.images.map((item: UmbMediaPickerPropertyValueEntry) => {
const src = this.imageUrls.get(item.mediaKey) || '';
return src
? html`<img src="${src}" alt="" loading="lazy" style="max-width: 100%; height: auto;" />`
: html`<uui-loader></uui-loader>`;
})}
</div>
</a>
`;
}
static styles = [
css`
:host {
display: block;
box-sizing: border-box;
}
`
];
}
export default McbImageBlockView;
But I wonder if there is a component for this? And instead of constructing href maybe it can just accept a property for UmbBlockEditorCustomViewConfiguration and perhaps other things the component may handle like focus outline etc.