Files
Umbraco-CMS/src/Umbraco.Web.UI.Client/examples/sorter-with-nested-containers/sorter-group.ts
Jacob Overgaard 71057b5f0b Build: Separate eslint logic for **/*.ts files (#19852)
* build: move typescript specific eslint rules to the `**/*ts.` pattern to avoid errors for .js files

* allow `Example` as class prefix

* allow `example-` as custom element prefix

* Removed `eslint-disable-next-line` comments

from the Example classes.

* Code formatting/tidy-up of Example classes

---------

Co-authored-by: leekelleher <leekelleher@gmail.com>
2025-08-05 11:42:39 +00:00

103 lines
2.8 KiB
TypeScript

import type { ExampleSorterItem } from './sorter-item.js';
import { UmbTextStyles } from '@umbraco-cms/backoffice/style';
import { css, html, customElement, LitElement, repeat, property } from '@umbraco-cms/backoffice/external/lit';
import { UmbElementMixin } from '@umbraco-cms/backoffice/element-api';
import { UmbSorterController } from '@umbraco-cms/backoffice/sorter';
import './sorter-item.js';
export type ModelEntryType = {
name: string;
children?: ModelEntryType[];
};
@customElement('example-sorter-group')
export class ExampleSorterGroup extends UmbElementMixin(LitElement) {
//
// Sorter setup:
#sorter = new UmbSorterController<ModelEntryType, ExampleSorterItem>(this, {
getUniqueOfElement: (element) => {
return element.name;
},
getUniqueOfModel: (modelEntry) => {
return modelEntry.name;
},
identifier: 'string-that-identifies-all-example-sorters',
itemSelector: 'example-sorter-item',
containerSelector: '.sorter-container',
onChange: ({ model }) => {
const oldValue = this._value;
this._value = model;
this.requestUpdate('value', oldValue);
// Fire an event for the parent to know that the model has changed.
this.dispatchEvent(new CustomEvent('change'));
},
});
@property({ type: Array, attribute: false })
public get value(): ModelEntryType[] {
return this._value ?? [];
}
public set value(value: ModelEntryType[]) {
const oldValue = this._value;
this._value = value;
this.#sorter.setModel(this._value);
this.requestUpdate('value', oldValue);
}
private _value?: ModelEntryType[];
removeItem = (item: ModelEntryType) => {
this.value = this.value.filter((r) => r.name !== item.name);
};
override render() {
return html`
<div class="sorter-container">
${repeat(
this.value,
// Note: ideally you have an unique identifier for each item, but for this example we use the `name` as identifier.
(item) => item.name,
(item) =>
html`<example-sorter-item name=${item.name}>
<button slot="action" @click=${() => this.removeItem(item)}>Delete</button>
<example-sorter-group
.value=${item.children ?? []}
@change=${(e: Event) => {
item.children = (e.target as ExampleSorterGroup).value;
}}></example-sorter-group>
</example-sorter-item>`,
)}
</div>
`;
}
static override styles = [
UmbTextStyles,
css`
:host {
display: block;
width: 100%;
border: 1px dashed rgba(122, 122, 122, 0.25);
border-radius: calc(var(--uui-border-radius) * 2);
padding: var(--uui-size-space-1);
}
.sorter-placeholder {
opacity: 0.2;
}
.sorter-container {
min-height: 20px;
}
`,
];
}
export default ExampleSorterGroup;
declare global {
interface HTMLElementTagNameMap {
'example-sorter-group-nested': ExampleSorterGroup;
}
}