Skip to content

Commit

Permalink
Merge pull request #2146 from enkelmedia/routed-modal-issue
Browse files Browse the repository at this point in the history
Fixes with `umb-route-slot` inside routed modal
  • Loading branch information
nielslyngsoe authored Nov 7, 2024
2 parents 77800ef + 3cf9fc8 commit aacf020
Show file tree
Hide file tree
Showing 12 changed files with 314 additions and 7 deletions.
47 changes: 47 additions & 0 deletions examples/modal-routed/dashboard.element.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import { css, html, LitElement, customElement, state } from '@umbraco-cms/backoffice/external/lit';
import { UmbTextStyles } from '@umbraco-cms/backoffice/style';
import { UmbElementMixin } from '@umbraco-cms/backoffice/element-api';
import type { UmbRoute } from '@umbraco-cms/backoffice/router';

@customElement('umb-dashboard')
export class UmbDashboardElement extends UmbElementMixin(LitElement) {
@state()
private _routes: UmbRoute[] = [
{
path: `/tab1`,
component: () => import('./tabs/tab1.element.js'),
},
{
path: `/tab2`,
component: () => import('./tabs/tab2.element.js'),
},
{
path: '',
redirectTo: 'tab1',
},
];

override render() {
return html`
<div>
Dashboard 1
<ul>
<li><a href="section/content/dashboard/example/tab1">Tab 1</a></li>
<li><a href="section/content/dashboard/example/tab2">Tab 2 (with modal)</a></li>
</ul>
<hr />
<umb-router-slot .routes=${this._routes}></umb-router-slot>
</div>
`;
}

static override styles = [UmbTextStyles, css``];
}

export default UmbDashboardElement;

declare global {
interface HTMLElementTagNameMap {
'umb-dashboard': UmbDashboardElement;
}
}
34 changes: 34 additions & 0 deletions examples/modal-routed/dashboard2.element.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { css, html, LitElement, customElement } from '@umbraco-cms/backoffice/external/lit';
import { UmbTextStyles } from '@umbraco-cms/backoffice/style';
import { UmbElementMixin } from '@umbraco-cms/backoffice/element-api';

@customElement('umb-dashboard2')
export class UmbDashboard2Element extends UmbElementMixin(LitElement) {
constructor() {
super();
}

override render() {
return html`
<div>
<h2>Link to modal route</h2>
<p>
This page only shows how to link to the routed modal that is placed on a tab on the "Modal Dashboard".
Clicking this link will not load the slots inside the modal, however, going to the "Modal Dashboard", clicking
on tab 2 and opening the modal from there will work.
</p>
<a href="section/content/dashboard/example/tab2/modal/example-routed-modal/view/abc123/">Open Modal Route</a>
</div>
`;
}

static override styles = [UmbTextStyles, css``];
}

export default UmbDashboard2Element;

declare global {
interface HTMLElementTagNameMap {
'umb-dashboard2': UmbDashboard2Element;
}
}
44 changes: 44 additions & 0 deletions examples/modal-routed/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import type { ManifestDashboard, ManifestModal } from '@umbraco-cms/backoffice/extension-registry';

// const section : ManifestSection = {
// type: "section",
// alias: 'demo.section',
// name: "Demo Section",
// meta: {
// label: "Demo",
// pathname: "demo"
// }
// }

const dashboard: ManifestDashboard = {
type: 'dashboard',
name: 'Example Modal Dashboard',
alias: 'example.dashboard.dataset',
element: () => import('./dashboard.element.js'),
weight: 15000,
meta: {
label: 'Modal Dashboard',
pathname: 'example',
},
};

const dashboard2: ManifestDashboard = {
type: 'dashboard',
name: 'Example Modal Dashboard2',
alias: 'example.dashboard.dataset2',
element: () => import('./dashboard2.element.js'),
weight: 15001,
meta: {
label: 'Link Dashboard',
pathname: 'example-2',
},
};

const modal: ManifestModal = {
type: 'modal',
name: 'Example Modal',
alias: 'example.routed.modal',
element: () => import('./modal/example-modal.element.js'),
};

export const manifests = [dashboard, dashboard2, modal];
13 changes: 13 additions & 0 deletions examples/modal-routed/modal/example-modal-token.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { UmbModalToken } from '@umbraco-cms/backoffice/modal';

export type Data = object;
export type ModalValue = object;

export const EXAMPLE_ROUTED_MODAL = new UmbModalToken<Data, ModalValue>(
'example.routed.modal', // this needs to match the alias of the modal registered in manifest.ts
{
modal: {
type: 'dialog',
},
},
);
43 changes: 43 additions & 0 deletions examples/modal-routed/modal/example-modal.element.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import { css, html, customElement, state } from '@umbraco-cms/backoffice/external/lit';
import { UmbTextStyles } from '@umbraco-cms/backoffice/style';
import { UmbModalBaseElement } from '@umbraco-cms/backoffice/modal';
import type { UmbRoute } from '@umbraco-cms/backoffice/router';

@customElement('umb-example-modal')
export class UmbExampleModal extends UmbModalBaseElement {
@state()
private _routes: UmbRoute[] = [
{
path: `modalOverview`,
component: () => import('./steps/example-modal-step1.element.js'),
},
{
path: `details`,
component: () => import('./steps/example-modal-step2.element.js'),
},
{
path: '',
redirectTo: 'modalOverview',
},
];

override render() {
return html`
<div>
umb-example modal element
<hr />
<umb-router-slot .routes=${this._routes}></umb-router-slot>
</div>
`;
}

static override styles = [UmbTextStyles, css``];
}

export default UmbExampleModal;

declare global {
interface HTMLElementTagNameMap {
'umb-example-modal': UmbExampleModal;
}
}
20 changes: 20 additions & 0 deletions examples/modal-routed/modal/steps/example-modal-step1.element.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { css, html, customElement } from '@umbraco-cms/backoffice/external/lit';
import { UmbTextStyles } from '@umbraco-cms/backoffice/style';
import { UmbModalBaseElement } from '@umbraco-cms/backoffice/modal';

@customElement('umb-example-modal-step1')
export class UmbExampleModalStep1 extends UmbModalBaseElement {
override render() {
return html` <div>example modal step1</div> `;
}

static override styles = [UmbTextStyles, css``];
}

export default UmbExampleModalStep1;

declare global {
interface HTMLElementTagNameMap {
'umb-example-modal-step1': UmbExampleModalStep1;
}
}
20 changes: 20 additions & 0 deletions examples/modal-routed/modal/steps/example-modal-step2.element.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { html, customElement } from '@umbraco-cms/backoffice/external/lit';
import { UmbTextStyles } from '@umbraco-cms/backoffice/style';
import { UmbModalBaseElement } from '@umbraco-cms/backoffice/modal';

@customElement('umb-example-modal-step2')
export class UmbExampleModalStep2 extends UmbModalBaseElement {
override render() {
return html` <div>example modal step2</div> `;
}

static override styles = [UmbTextStyles];
}

export default UmbExampleModalStep2;

declare global {
interface HTMLElementTagNameMap {
'umb-example-modal-step2': UmbExampleModalStep2;
}
}
31 changes: 31 additions & 0 deletions examples/modal-routed/tabs/tab1.element.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import { css, html, LitElement, customElement, state } from '@umbraco-cms/backoffice/external/lit';
import { UmbTextStyles } from '@umbraco-cms/backoffice/style';
import { UmbElementMixin } from '@umbraco-cms/backoffice/element-api';

@customElement('umb-dashboard-tab1')
export class UmbDashboardTab1Element extends UmbElementMixin(LitElement) {
@state()
_editLinkPath?: string;

constructor() {
super();
}

override render() {
return html`
<div>
<h2>tab 1</h2>
</div>
`;
}

static override styles = [UmbTextStyles, css``];
}

export default UmbDashboardTab1Element;

declare global {
interface UmbDashboardTab1Element {
'umb-dashboard-tab1': UmbDashboardTab1Element;
}
}
55 changes: 55 additions & 0 deletions examples/modal-routed/tabs/tab2.element.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import { EXAMPLE_ROUTED_MODAL } from '../modal/example-modal-token.js';
import { css, html, LitElement, customElement, state } from '@umbraco-cms/backoffice/external/lit';
import { UmbTextStyles } from '@umbraco-cms/backoffice/style';
import { UmbElementMixin } from '@umbraco-cms/backoffice/element-api';
import { UmbModalRouteRegistrationController } from '@umbraco-cms/backoffice/router';

@customElement('umb-dashboard-tab2')
export class UmbDashboardTab2Element extends UmbElementMixin(LitElement) {
#workspaceModal?: UmbModalRouteRegistrationController<
typeof EXAMPLE_ROUTED_MODAL.DATA,
typeof EXAMPLE_ROUTED_MODAL.VALUE
>;

@state()
_editLinkPath?: string;

constructor() {
super();

// Using workspace modal context
this.#workspaceModal?.destroy();
this.#workspaceModal = new UmbModalRouteRegistrationController(this, EXAMPLE_ROUTED_MODAL)
.addAdditionalPath('view/:entityKey')
.onSetup(() => {
return {
data: {},
value: {},
};
})
.observeRouteBuilder((routeBuilder) => {
this._editLinkPath = routeBuilder({ entityKey: 'abc123' });
});
}

override render() {
return html`
<div>
<h2>tab 2</h2>
<p>This element hosts the UmbModalRouteRegistrationController</p>
<a href=${this._editLinkPath ?? ''}>Open modal</a>
</div>
`;
}

static override styles = [UmbTextStyles, css``];
}

export default UmbDashboardTab2Element;

declare global {
interface UmbDashboardTab2Element {
'umb-dashboard-tab2': UmbDashboardTab2Element;
}
}
6 changes: 4 additions & 2 deletions src/external/router-slot/router-slot.ts
Original file line number Diff line number Diff line change
Expand Up @@ -162,9 +162,11 @@ export class RouterSlot<D = any, P = any> extends HTMLElement implements IRouter
this._setParent(null);
}
}
if (this.parent && this.parent.match !== null && this.match === null) {
if (this.parent) {
requestAnimationFrame(() => {
this.render();
if (this.parent && this.parent.match !== null && this.match === null) {
this.render();
}
});
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/packages/core/router/route.context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ export class UmbRouteContext extends UmbContextBase<UmbRouteContext> {
if (this.#activeModalPath) {
// If if there is a modal using the old path.
const activeModal = this.#modalRegistrations.find((registration) => {
return registration.generateModalPath() === this.#activeModalPath;
return '/' + registration.generateModalPath() === this.#activeModalPath;
});
if (activeModal) {
this.#modalContext?.close(activeModal.key);
Expand Down
6 changes: 2 additions & 4 deletions src/packages/core/router/router-slot.element.ts
Original file line number Diff line number Diff line change
Expand Up @@ -94,9 +94,7 @@ export class UmbRouterSlotElement extends UmbLitElement {

protected override firstUpdated(_changedProperties: PropertyValueMap<any> | Map<PropertyKey, unknown>): void {
super.firstUpdated(_changedProperties);
this._routerPath = this._constructAbsoluteRouterPath();
this.#routeContext._internal_routerGotBasePath(this._routerPath);
this.dispatchEvent(new UmbRouterSlotInitEvent());
this._updateRouterPath();
}

protected _updateRouterPath() {
Expand Down Expand Up @@ -124,7 +122,7 @@ export class UmbRouterSlotElement extends UmbLitElement {
this.dispatchEvent(new UmbRouterSlotChangeEvent());
}
} else if (event.detail.slot === this.#modalRouter) {
const newActiveModalLocalPath = this.#modalRouter.match?.fragments.consumed ?? '';
const newActiveModalLocalPath = this.#modalRouter.match?.route.path ?? '';
this.#routeContext._internal_modalRouterChanged(newActiveModalLocalPath);
}
};
Expand Down

0 comments on commit aacf020

Please sign in to comment.