initial refactor for binding modals to a host

This commit is contained in:
Niels Lyngsø
2024-03-02 09:06:40 +01:00
parent 573a7c63c2
commit 2e50560459
3 changed files with 29 additions and 23 deletions

View File

@@ -56,22 +56,18 @@ export class UmbModalElement extends UmbLitElement {
// Makes sure that the modal triggers the reject of the context promise when it is closed by pressing escape.
this.element.addEventListener(UUIModalCloseEvent, this.#onClose);
if (this.#modalContext.originTarget) {
// The following code is the context api proxy.
// It re-dispatches the context api request event to the origin target of this modal, in other words the element that initiated the modal.
this.element.addEventListener(UMB_CONTENT_REQUEST_EVENT_TYPE, ((event: UmbContextRequestEvent) => {
if (!this.#modalContext) return;
if (this.#modalContext.originTarget) {
// Note for this hack (The if-sentence):
// We do not currently have a good enough control to ensure that the proxy is last, meaning if another context is provided at this element, it might respond after the proxy event has been dispatched.
// To avoid such this hack just prevents proxying the event if its a request for the Modal Context.
if (event.contextAlias !== UMB_MODAL_CONTEXT.contextAlias) {
event.stopImmediatePropagation();
this.#modalContext.originTarget.dispatchEvent(event.clone());
}
}
}) as EventListener);
}
// The following code is the context api proxy.
// It re-dispatches the context api request event to the origin target of this modal, in other words the element that initiated the modal. [NL]
this.element.addEventListener(UMB_CONTENT_REQUEST_EVENT_TYPE, ((event: UmbContextRequestEvent) => {
if (!this.#modalContext) return;
// Note for this hack (The if-sentence): [NL]
// We do not currently have a good enough control to ensure that the proxy is last, meaning if another context is provided at this element, it might respond after the proxy event has been dispatched.
// To avoid such this hack just prevents proxying the event if its a request for the Modal Context. [NL]
if (event.contextAlias !== UMB_MODAL_CONTEXT.contextAlias) {
event.stopImmediatePropagation();
this.#modalContext.getHostElement().dispatchEvent(event.clone());
}
}) as EventListener);
this.#modalContext.onSubmit().then(
() => {

View File

@@ -26,8 +26,9 @@ export class UmbModalManagerContext extends UmbContextBase<UmbModalManagerContex
/**
* Opens a modal or sidebar modal
* @public
* @param {(string | UmbModalToken)} modalAlias
* @param {UmbModalContextClassArgs} args
* @param {UmbControllerHost} host - The host that the modal should be attached to, this is usually the controller/element that is opening the modal. This additionally acts as the modal origin for the context api.
* @param {(string | UmbModalToken)} modalAlias - The alias or token of the modal to open
* @param {UmbModalContextClassArgs} args - The arguments for this setup.
* @return {*} {UmbModalHandler}
* @memberof UmbModalManagerContext
*/
@@ -36,10 +37,11 @@ export class UmbModalManagerContext extends UmbContextBase<UmbModalManagerContex
ModalValue = unknown,
ModalAliasTypeAsToken extends UmbModalToken = UmbModalToken<ModalData, ModalValue>,
>(
host: UmbControllerHost,
modalAlias: UmbModalToken<ModalData, ModalValue> | string,
args: UmbModalContextClassArgs<ModalAliasTypeAsToken> = {},
) {
const modalContext = new UmbModalContext(modalAlias, args);
const modalContext = new UmbModalContext(host, modalAlias, args);
// Append to store:
this.#modals.setValue(

View File

@@ -1,9 +1,11 @@
import { UmbModalToken } from '../token/modal-token.js';
import type { UmbModalConfig, UmbModalType } from './modal-manager.context.js';
import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api';
import type { IRouterSlot } from '@umbraco-cms/backoffice/external/router-slot';
import type { UUIModalSidebarSize } from '@umbraco-cms/backoffice/external/uui';
import { UmbId } from '@umbraco-cms/backoffice/id';
import { UmbObjectState } from '@umbraco-cms/backoffice/observable-api';
import { UmbControllerBase } from '@umbraco-cms/backoffice/class-api';
export interface UmbModalRejectReason {
type: string;
@@ -21,7 +23,7 @@ export type UmbModalContextClassArgs<
};
// TODO: consider splitting this into two separate handlers
export class UmbModalContext<ModalPreset extends object = object, ModalValue = any> extends EventTarget {
export class UmbModalContext<ModalPreset extends object = object, ModalValue = any> extends UmbControllerBase {
//
#submitPromise: Promise<ModalValue>;
#submitResolver?: (value: ModalValue) => void;
@@ -32,20 +34,19 @@ export class UmbModalContext<ModalPreset extends object = object, ModalValue = a
public readonly type: UmbModalType = 'dialog';
public readonly size: UUIModalSidebarSize = 'small';
public readonly router: IRouterSlot | null = null;
public readonly originTarget?: Element;
public readonly alias: string | UmbModalToken<ModalPreset, ModalValue>;
#value;
public readonly value;
constructor(
host: UmbControllerHost,
modalAlias: string | UmbModalToken<ModalPreset, ModalValue>,
args: UmbModalContextClassArgs<UmbModalToken>,
) {
super();
super(host);
this.key = args.modal?.key || UmbId.new();
this.router = args.router ?? null;
this.originTarget = args.originTarget;
this.alias = modalAlias;
if (this.alias instanceof UmbModalToken) {
@@ -130,4 +131,11 @@ export class UmbModalContext<ModalPreset extends object = object, ModalValue = a
public updateValue(partialValue: Partial<ModalValue>) {
this.#value.update(partialValue);
}
public destroy(): void {
this.#value.destroy();
(this as any).router = null;
(this as any).data = undefined;
super.destroy();
}
}