router
router copied to clipboard
Page title updates
As a developer I want to update the browser window title when the current route changes.
While there is no special support for this use case, it is straightforward to implement via the onAfterEnter
route component lifecycle callback (see #23):
onAfterEnter() {
document.title = 'Title';
}
Related use case:
Sometimes we need to wait for something else to update the page title. For example, a request to the API to know the title of the post. The same could apply to other meta tags such as description.
The problem with the onAfterEnter
callback approach is that it can be seen as mixing concerns - the UI component becomes responsible for the page title, which could be understood as the responsibility of the routing table.
If the router instance itself had callbacks (i.e. hooks), users could implement this feature themselves fairly easily:
// strawman
const router = new Router(document.querySelector('main'), {
onAfterEnter(location): void {
const title =
location.routes.reduceRight((title, route) =>
title ?? route.metadata?.title ?? route.name ?? null, null);
document.title = `App | ${title}`.replace(/ \| $/, '');
},
});
I accomplished this locally using the following @vaadin+router+1.7.2.patch
:
diff --git a/node_modules/@vaadin/router/dist/vaadin-router.js b/node_modules/@vaadin/router/dist/vaadin-router.js
index c0dc354..760d442 100644
--- a/node_modules/@vaadin/router/dist/vaadin-router.js
+++ b/node_modules/@vaadin/router/dist/vaadin-router.js
@@ -1524,6 +1524,7 @@ class Router extends Resolver {
// Using WeakMap instead of WeakSet because WeakSet is not supported by IE11
this.__createdByRouter = new WeakMap();
this.__addedByRouter = new WeakMap();
+ this.onAfterEnter = options.onAfterEnter;
}
__resolveRoute(context) {
@@ -2173,6 +2174,12 @@ class Router extends Resolver {
currentComponent.onAfterEnter,
[location, {}, currentContext.resolver],
currentComponent);
+ if (i === currentContext.chain.length - 1) {
+ runCallbackIfPossible(
+ this.onAfterEnter,
+ [location, {}, currentContext.resolver],
+ this);
+ }
}
}
diff --git a/node_modules/@vaadin/router/interfaces.d.ts b/node_modules/@vaadin/router/interfaces.d.ts
index 472b8bb..f492f81 100644
--- a/node_modules/@vaadin/router/interfaces.d.ts
+++ b/node_modules/@vaadin/router/interfaces.d.ts
@@ -124,6 +124,8 @@ declare module './dist/vaadin-router' {
export interface RouterOptions {
baseUrl?: string;
+ onBeforeEnter?: BeforeEnterObserver['onBeforeEnter'];
+ onAfterEnter?: AfterEnterObserver['onAfterEnter'];
}
type _RouterOptions = RouterOptions;
See also #465