Skip to content

Commit cca3423

Browse files
authored
Merge pull request #2003 from umbraco/v14/feature/sorter-nested-example
Improved example + minor code refactor
2 parents 5f238cc + 70e3031 commit cca3423

File tree

3 files changed

+51
-42
lines changed

3 files changed

+51
-42
lines changed

examples/sorter-with-nested-containers/sorter-dashboard.ts

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { UmbTextStyles } from '@umbraco-cms/backoffice/style';
22
import { css, html, customElement, LitElement } from '@umbraco-cms/backoffice/external/lit';
33
import { UmbElementMixin } from '@umbraco-cms/backoffice/element-api';
4-
import type { ModelEntryType } from './sorter-group.js';
4+
import type { ExampleSorterGroup, ModelEntryType } from './sorter-group.js';
55

66
import './sorter-group.js';
77
@customElement('example-sorter-dashboard')
@@ -57,9 +57,16 @@ export class ExampleSorterDashboard extends UmbElementMixin(LitElement) {
5757
return html`
5858
<uui-box class="uui-text">
5959
<div class="outer-wrapper">
60-
<h5>Notice this example still only support single group of Sorter.</h5>
61-
<example-sorter-group .initialItems=${this.groupOneItems}></example-sorter-group>
62-
<example-sorter-group .initialItems=${this.groupTwoItems}></example-sorter-group>
60+
<example-sorter-group
61+
.value=${this.groupOneItems}
62+
@change=${(e: Event) => {
63+
this.groupOneItems = (e.target as ExampleSorterGroup).value;
64+
}}></example-sorter-group>
65+
<example-sorter-group
66+
.value=${this.groupTwoItems}
67+
@change=${(e: Event) => {
68+
this.groupTwoItems = (e.target as ExampleSorterGroup).value;
69+
}}></example-sorter-group>
6370
</div>
6471
</uui-box>
6572
`;

examples/sorter-with-nested-containers/sorter-group.ts

Lines changed: 27 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -13,28 +13,8 @@ export type ModelEntryType = {
1313

1414
@customElement('example-sorter-group')
1515
export class ExampleSorterGroup extends UmbElementMixin(LitElement) {
16-
@property({ type: Array, attribute: false })
17-
public get initialItems(): ModelEntryType[] {
18-
return this.items;
19-
}
20-
public set initialItems(value: ModelEntryType[]) {
21-
// Only want to set the model initially, cause any re-render should not set this again.
22-
if (this._items !== undefined) return;
23-
this.items = value;
24-
}
25-
26-
@property({ type: Array, attribute: false })
27-
public get items(): ModelEntryType[] {
28-
return this._items ?? [];
29-
}
30-
public set items(value: ModelEntryType[]) {
31-
const oldValue = this._items;
32-
this._items = value;
33-
this.#sorter.setModel(this._items);
34-
this.requestUpdate('items', oldValue);
35-
}
36-
private _items?: ModelEntryType[];
37-
16+
//
17+
// Sorter setup:
3818
#sorter = new UmbSorterController<ModelEntryType, ExampleSorterItem>(this, {
3919
getUniqueOfElement: (element) => {
4020
return element.name;
@@ -46,26 +26,45 @@ export class ExampleSorterGroup extends UmbElementMixin(LitElement) {
4626
itemSelector: 'example-sorter-item',
4727
containerSelector: '.sorter-container',
4828
onChange: ({ model }) => {
49-
const oldValue = this._items;
50-
this._items = model;
51-
this.requestUpdate('items', oldValue);
29+
const oldValue = this._value;
30+
this._value = model;
31+
this.requestUpdate('value', oldValue);
32+
// Fire an event for the parent to know that the model has changed.
33+
this.dispatchEvent(new CustomEvent('change'));
5234
},
5335
});
5436

37+
@property({ type: Array, attribute: false })
38+
public get value(): ModelEntryType[] {
39+
return this._value ?? [];
40+
}
41+
public set value(value: ModelEntryType[]) {
42+
const oldValue = this._value;
43+
this._value = value;
44+
this.#sorter.setModel(this._value);
45+
this.requestUpdate('value', oldValue);
46+
}
47+
private _value?: ModelEntryType[];
48+
5549
removeItem = (item: ModelEntryType) => {
56-
this.items = this.items.filter((r) => r.name !== item.name);
50+
this.value = this.value.filter((r) => r.name !== item.name);
5751
};
5852

5953
render() {
6054
return html`
6155
<div class="sorter-container">
6256
${repeat(
63-
this.items,
57+
this.value,
58+
// Note: ideally you have an unique identifier for each item, but for this example we use the `name` as identifier.
6459
(item) => item.name,
6560
(item) =>
6661
html`<example-sorter-item name=${item.name}>
6762
<button slot="action" @click=${() => this.removeItem(item)}>Delete</button>
68-
${item.children ? html`<example-sorter-group .initialItems=${item.children}></example-sorter-group>` : ''}
63+
<example-sorter-group
64+
.value=${item.children ?? []}
65+
@change=${(e: Event) => {
66+
item.children = (e.target as ExampleSorterGroup).value;
67+
}}></example-sorter-group>
6968
</example-sorter-item>`,
7069
)}
7170
</div>

src/packages/core/sorter/sorter.controller.ts

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -387,16 +387,23 @@ export class UmbSorterController<T, ElementType extends HTMLElement = HTMLElemen
387387
}
388388
};
389389

390+
#getDraggableElement(element: HTMLElement) {
391+
if (this.#config.draggableSelector) {
392+
// Concept for enabling getting element within ShadowRoot: (But it might need to be configurable, so its still possible to get light dom element(slotted), despite the host is a web-component with shadow-dom.) [NL]
393+
//const queryFromEl = element.shadowRoot ?? element;
394+
return (element.querySelector(this.#config.draggableSelector) as HTMLElement | undefined) ?? element;
395+
}
396+
return element;
397+
}
398+
390399
setupItem(element: ElementType) {
391400
if (this.#config.ignorerSelector) {
392401
setupIgnorerElements(element, this.#config.ignorerSelector);
393402
}
394403

395404
if (!this.#config.disabledItemSelector || !element.matches(this.#config.disabledItemSelector)) {
396405
// Idea: to make sure on does not get initialized twice: if ((element as HTMLElement).draggable === true) return;
397-
const draggableElement = this.#config.draggableSelector
398-
? (element.querySelector(this.#config.draggableSelector) as HTMLElement | undefined) ?? element
399-
: element;
406+
const draggableElement = this.#getDraggableElement(element);
400407
(draggableElement as HTMLElement).draggable = true;
401408
draggableElement.addEventListener('dragstart', this.#handleDragStart);
402409
draggableElement.addEventListener('dragend', this.#handleDragEnd);
@@ -419,9 +426,7 @@ export class UmbSorterController<T, ElementType extends HTMLElement = HTMLElemen
419426
destroyIgnorerElements(element, this.#config.ignorerSelector);
420427
}
421428

422-
const draggableElement = this.#config.draggableSelector
423-
? (element.querySelector(this.#config.draggableSelector) as HTMLElement | undefined) ?? element
424-
: element;
429+
const draggableElement = this.#getDraggableElement(element);
425430
draggableElement.removeEventListener('dragstart', this.#handleDragStart);
426431
// We are not ready to remove the dragend or drop, as this is might be the active one just moving container:
427432
//draggableElement.removeEventListener('dragend', this.#handleDragEnd);
@@ -447,9 +452,7 @@ export class UmbSorterController<T, ElementType extends HTMLElement = HTMLElemen
447452
#setCurrentElement(element: ElementType) {
448453
UmbSorterController.activeElement = element;
449454

450-
UmbSorterController.activeDragElement = this.#config.draggableSelector
451-
? element.querySelector(this.#config.draggableSelector) ?? undefined
452-
: element;
455+
UmbSorterController.activeDragElement = this.#getDraggableElement(element);
453456

454457
if (!UmbSorterController.activeDragElement) {
455458
throw new Error(
@@ -629,7 +632,7 @@ export class UmbSorterController<T, ElementType extends HTMLElement = HTMLElemen
629632
const elRect = el.getBoundingClientRect();
630633
// gather elements on the same row.
631634
if (this.#dragY >= elRect.top && this.#dragY <= elRect.bottom) {
632-
const dragElement = this.#config.draggableSelector ? el.querySelector(this.#config.draggableSelector) : el;
635+
const dragElement = this.#getDraggableElement(el as unknown as HTMLElement);
633636
if (dragElement) {
634637
const dragElementRect = dragElement.getBoundingClientRect();
635638
if (el !== UmbSorterController.activeElement) {

0 commit comments

Comments
 (0)