Hello,
I’m currently building a set of custom views for the backoffice in Umbraco 16.
I need to be able to look up a document ( uploaded to the media library ) by id and extract some custom field data from it.
Typescript/Lit information on this subject is very scarce. Could some one show me how this is done.
Many thanks
Hi All,
Managed to solve this one. If anyone needs something similar here is my code:
import { html, customElement, LitElement, property, css, state } from '@umbraco-cms/backoffice/external/lit';
import { UmbElementMixin } from '@umbraco-cms/backoffice/element-api';
import { UmbMediaDetailRepository } from '@umbraco-cms/backoffice/media';
import type { UmbBlockDataType } from '@umbraco-cms/backoffice/block';
import type { UmbBlockEditorCustomViewElement } from '@umbraco-cms/backoffice/block-custom-view';
import type { UmbMediaPickerPropertyValue } from '@umbraco-cms/backoffice/media';
@customElement('document-block-view')
export class DocumentBlockViewElement extends UmbElementMixin(LitElement) implements UmbBlockEditorCustomViewElement {
@property({ attribute: false })
content?: UmbBlockDataType;
@state()
document: UmbMediaPickerPropertyValue[] = [];
@state()
private _documentDetails: Map<string, { name: string, url: string, extension: string, size: number }> = new Map();
#mediaRepository = new UmbMediaDetailRepository(this);
override async updated(changedProperties: Map<string | number | symbol, unknown>) {
super.updated(changedProperties);
if (changedProperties.has('content') && this.content?.document) {
this.document = this.content.document as UmbMediaPickerPropertyValue[];
await this.fetchDocumentDetails();
}
}
async fetchDocumentDetails() {
if (!this.document) return;
for (const doc of this.document) {
if (doc.mediaKey && !this._documentDetails.has(doc.mediaKey)) {
const mediaItem = await this.resolveMediaItem(doc.mediaKey);
if (mediaItem) {
// Find properties by their unique alias
const uploadField = mediaItem.values.find(v => v.alias === 'umbracoFile');
const extensionField = mediaItem.values.find(v => v.alias === 'umbracoExtension');
const sizeField = mediaItem.values.find(v => v.alias === 'umbracoBytes');
// Check that the properties exist before using them
if (uploadField && extensionField && sizeField) {
this._documentDetails.set(doc.mediaKey, {
name: mediaItem.variants[0].name,
url: (uploadField.value as { src: string }).src,
extension: extensionField.value as string,
size: sizeField.value as number
});
this.requestUpdate();
}
}
}
}
}
async resolveMediaItem(mediaKey: string) {
const { data } = await this.#mediaRepository.requestByUnique(mediaKey);
return data;
}
render() {
return html`
<ul class="document-list">
${this.document.map((doc) => {
const details = this._documentDetails.get(doc.mediaKey || '');
return html`
<li>
<a href="${details?.url}" target="_blank" rel="noopener noreferrer">
${details ? `${details.name} (${details.extension}, ${details.size} bytes)` : 'Loading...'}
</a>
</li>
`;
})}
</ul>`;
}
static styles = [
css`
:host {
display: block;
height: 100%;
box-sizing: border-box;
background-color: white;
border-radius: 9px;
padding: 12px;
}
.document-list {
list-style-type:- disclosure-closed;
padding-inline-start: 20px;
}
.document-list a {
text-decoration: none;
color: var(--uui-color-interactive, #2152a3);
}
.document-list a:hover {
text-decoration: underline;
}
`,
];
}
export default DocumentBlockViewElement;
declare global {
interface HTMLElementTagNameMap {
'document-block-view': DocumentBlockViewElement;
}
}
1 Like
system
(system)
Closed
4
This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.