diff --git a/src/Umbraco.Web.UI.Client/src/external/router-slot/model.ts b/src/Umbraco.Web.UI.Client/src/external/router-slot/model.ts index 6872b18149..5c4d4240ba 100644 --- a/src/Umbraco.Web.UI.Client/src/external/router-slot/model.ts +++ b/src/Umbraco.Web.UI.Client/src/external/router-slot/model.ts @@ -62,6 +62,9 @@ export interface IRouteBase { // - If "full" router-slot will try to match the entire path. // - If "fuzzy" router-slot will try to match an arbitrary part of the path. pathMatch?: PathMatch; + + // A unique identifier for the route, used to identify the route so we can avoid re-rendering it. + unique?: string | Symbol; } /** diff --git a/src/Umbraco.Web.UI.Client/src/external/router-slot/router-slot.ts b/src/Umbraco.Web.UI.Client/src/external/router-slot/router-slot.ts index 007c8d6c32..d21c76461e 100644 --- a/src/Umbraco.Web.UI.Client/src/external/router-slot/router-slot.ts +++ b/src/Umbraco.Web.UI.Client/src/external/router-slot/router-slot.ts @@ -208,10 +208,8 @@ export class RouterSlot extends HTMLElement implements IRouter // If navigate is not determined, then we will check if we have a route match, and if the new match is different from current. [NL] const newMatch = this.getRouteMatch(); if (newMatch) { - if (this._routeMatch?.route.path !== newMatch.route.path) { - // Check if this match matches the current match (aka. If the path has changed), if so we should navigate. [NL] - navigate = shouldNavigate(this.match, newMatch); - } + // Check if this match matches the current match (aka. If the path has changed), if so we should navigate. [NL] + navigate = shouldNavigate(this.match, newMatch); } } } diff --git a/src/Umbraco.Web.UI.Client/src/external/router-slot/util/router.ts b/src/Umbraco.Web.UI.Client/src/external/router-slot/util/router.ts index 7c731abe59..2eb410f903 100644 --- a/src/Umbraco.Web.UI.Client/src/external/router-slot/util/router.ts +++ b/src/Umbraco.Web.UI.Client/src/external/router-slot/util/router.ts @@ -301,9 +301,10 @@ export function shouldNavigate(currentMatch: IRouteMatch | null, newMatch: const { route: currentRoute, fragments: currentFragments } = currentMatch; const { route: newRoute, fragments: newFragments } = newMatch; - const isSameRoute = currentRoute == newRoute; + const isSameRoute = currentRoute.path == newRoute.path; const isSameFragments = currentFragments.consumed == newFragments.consumed; + const isSameBasedOnUnique = currentRoute.unique === newRoute.unique; // Only navigate if the URL consumption is new or if the two routes are no longer the same. - return !isSameFragments || !isSameRoute; + return !isSameFragments || !isSameRoute || !isSameBasedOnUnique; } diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/collection/collection-view.manager.ts b/src/Umbraco.Web.UI.Client/src/packages/core/collection/collection-view.manager.ts index d7fc98c2af..2c7832a555 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/collection/collection-view.manager.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/collection/collection-view.manager.ts @@ -94,6 +94,7 @@ export class UmbCollectionViewManager extends UmbControllerBase { if (routes.length > 0) { routes.push({ + unique: fallbackView.alias, path: '', component: () => createExtensionElement(fallbackView), setup: () => { diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/modal/component/modal.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/modal/component/modal.element.ts index 9313a8de31..1096ec181e 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/modal/component/modal.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/modal/component/modal.element.ts @@ -95,6 +95,7 @@ export class UmbModalElement extends UmbLitElement { this.#modalRouterElement = document.createElement('umb-router-slot'); this.#modalRouterElement.routes = [ { + unique: '_umbEmptyRoute_', path: '', component: document.createElement('slot'), }, diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/router/components/router-slot/route.context.ts b/src/Umbraco.Web.UI.Client/src/packages/core/router/components/router-slot/route.context.ts index 2bd561dbfb..ea40a677f8 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/router/components/router-slot/route.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/router/components/router-slot/route.context.ts @@ -60,6 +60,7 @@ export class UmbRouteContext extends UmbContextBase { #generateRoute(modalRegistration: UmbModalRouteRegistration): UmbRoutePlusModalKey { return { __modalKey: modalRegistration.key, + unique: 'umbModalKey_' + modalRegistration.key, path: '/' + modalRegistration.generateModalPath(), component: EmptyDiv, setup: async (component, info) => { @@ -112,6 +113,7 @@ export class UmbRouteContext extends UmbContextBase { // Add an empty route, so there is a route for the router to react on when no modals are open. this.#modalRoutes.push({ __modalKey: '_empty_', + unique: 'umbEmptyModal', path: '', component: EmptyDiv, }); diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/components/workspace-editor/workspace-editor.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/components/workspace-editor/workspace-editor.element.ts index 845b2248af..ae686a5243 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/components/workspace-editor/workspace-editor.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/components/workspace-editor/workspace-editor.element.ts @@ -70,11 +70,11 @@ export class UmbWorkspaceEditorElement extends UmbLitElement { (component as any).manifest = manifest; } }, - } as UmbRoute; + }; }); // Duplicate first workspace and use it for the empty path scenario. [NL] - newRoutes.push({ ...newRoutes[0], path: '' }); + newRoutes.push({ ...newRoutes[0], unique: newRoutes[0].path, path: '' }); newRoutes.push({ path: `**`,