Compare commits

...
Author SHA1 Message Date
Mads Rasmussen 5d2b902baf Add entity context per table row 2026-02-12 09:39:33 +01:00
4 changed files with 56 additions and 2 deletions
@@ -0,0 +1,19 @@
import { UmbControllerHostMixin } from './controller-host.mixin.js';
/**
* A minimal UmbControllerHost adapter that wraps a plain DOM element.
* This enables creating contexts (like UmbEntityContext) that auto-provide
* on the given element without requiring it to be a UmbControllerHostElement.
*/
export class UmbElementControllerHost extends UmbControllerHostMixin(Object) {
#element: Element;
constructor(element: Element) {
super();
this.#element = element;
}
getHostElement(): Element {
return this.#element;
}
}
@@ -2,6 +2,7 @@ export * from './controller-host.mixin.js';
export type * from './controller-host.interface.js';
export type * from './controller-host-element.interface.js';
export * from './controller-host-element.mixin.js';
export * from './element-controller-host.js';
export type * from './controller.interface.js';
export type * from './controller-alias.type.js';
export * from './controller.event.js';
@@ -5,6 +5,7 @@ import {
html,
ifDefined,
property,
ref,
repeat,
state,
when,
@@ -19,6 +20,7 @@ export interface UmbTableItem {
entityType?: string;
data: Array<UmbTableItemData>;
selectable?: boolean;
onRowElement?: (element: HTMLElement) => void;
}
export interface UmbTableItemData {
@@ -334,6 +336,9 @@ export class UmbTableElement extends UmbLitElement {
const isItemSelectable = this.#isSelectableItem(item);
return html`
<uui-table-row
${ref((el) => {
if (el) item.onRowElement?.(el as HTMLElement);
})}
data-sortable-id=${item.id}
?selectable=${this.config.allowSelection && !this._sortable && isItemSelectable}
?select-only=${this._selectionMode || this.config.selectOnly}
@@ -1,11 +1,12 @@
import { UMB_DOCUMENT_COLLECTION_CONTEXT } from '../../document-collection.context-token.js';
import { UMB_DOCUMENT_ENTITY_TYPE } from '../../../entity.js';
import { UMB_EDIT_DOCUMENT_WORKSPACE_PATH_PATTERN } from '../../../paths.js';
import type { UmbDocumentCollectionItemModel } from '../../types.js';
import { css, customElement, html, state } from '@umbraco-cms/backoffice/external/lit';
import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element';
import { UmbTextStyles } from '@umbraco-cms/backoffice/style';
import type { UmbCollectionColumnConfiguration } from '@umbraco-cms/backoffice/collection';
import { UmbElementControllerHost } from '@umbraco-cms/backoffice/controller-api';
import { UmbEntityContext } from '@umbraco-cms/backoffice/entity';
import type {
UmbTableColumn,
UmbTableConfig,
@@ -59,6 +60,7 @@ export class UmbDocumentTableCollectionViewElement extends UmbLitElement {
private _selection: Array<string> = [];
#collectionContext?: typeof UMB_DOCUMENT_COLLECTION_CONTEXT.TYPE;
#rowHosts = new Map<string, UmbElementControllerHost>();
constructor() {
super();
@@ -121,6 +123,15 @@ export class UmbDocumentTableCollectionViewElement extends UmbLitElement {
}
#createTableItems(items: Array<UmbDocumentCollectionItemModel>) {
// Clean up hosts for items no longer present
const currentIds = new Set(items.map((i) => i.unique));
for (const [id, host] of this.#rowHosts) {
if (!currentIds.has(id)) {
host.destroy();
this.#rowHosts.delete(id);
}
}
this._tableItems = items.map((item) => {
if (!item.unique) throw new Error('Item id is missing.');
@@ -147,8 +158,18 @@ export class UmbDocumentTableCollectionViewElement extends UmbLitElement {
return {
id: item.unique,
icon: item.documentType.icon,
entityType: UMB_DOCUMENT_ENTITY_TYPE,
entityType: item.entityType,
data: data,
onRowElement: (element: HTMLElement) => {
if (!this.#rowHosts.has(item.unique)) {
const host = new UmbElementControllerHost(element);
const context = new UmbEntityContext(host);
context.setEntityType(item.entityType);
context.setUnique(item.unique);
host.hostConnected();
this.#rowHosts.set(item.unique, host);
}
},
};
});
}
@@ -177,6 +198,14 @@ export class UmbDocumentTableCollectionViewElement extends UmbLitElement {
});
}
override disconnectedCallback() {
super.disconnectedCallback();
for (const [, host] of this.#rowHosts) {
host.destroy();
}
this.#rowHosts.clear();
}
override render() {
return html`
<umb-table