@lwce/router
Version:
A LWC router that supports server-side rendering
128 lines (110 loc) • 3.03 kB
JavaScript
import { LightningElement, api, createContextProvider } from "lwc";
import { routeParams } from "../../../wire-adapters/route-params";
const routeParamsContextProvider = createContextProvider(routeParams);
let id = 0;
function getUniqueId() {
return ++id;
}
function combinePaths(a, b) {
if (a.charAt(a.length - 1) === "/" && b.charAt(0) === "/") {
return a + b.substring(1);
} else {
return a + b;
}
}
export default class Route extends LightningElement {
path;
strict = false;
sensitive = false;
exact = false;
default = false;
routeParams = {};
rendered = false;
wireAdapters = [];
constructor() {
super();
this.uniqueId = getUniqueId();
this.routeChange = this._routeChange.bind(this);
this.addEventListener(
"lwcerouter_addrouteeventlistener",
this.interceptChildRouteEvent.bind(
this,
"lwcerouter_addrouteeventlistener"
)
);
this.addEventListener(
"lwcerouter_removeeventlistener",
this.interceptChildRouteEvent.bind(this, "lwcerouter_removeeventlistener")
);
}
interceptChildRouteEvent(name, event) {
if (event.detail.uniqueId !== this.uniqueId && !this.default) {
event.stopPropagation();
this.dispatchEvent(
new CustomEvent(name, {
detail: {
...event.detail,
path: combinePaths(this.path, event.detail.path),
uniqueId: this.uniqueId,
},
bubbles: true,
composed: true,
})
);
}
}
connectedCallback() {
if (
this.default &&
(this.path || this.exact || this.sensitive || this.strict)
) {
throw new Error("A default route cannot have other parameters!");
}
routeParamsContextProvider(this, {
consumerConnectedCallback: (consumer) => {
this.wireAdapters.push(consumer);
this.sendRouteParams();
},
consumerDisconnectedCallback: (consumer) => {
this.wireAdapters.splice(this.wireAdapters.indexOf(consumer), 1);
},
});
this.dispatchEvent(
new CustomEvent("lwcerouter_addrouteeventlistener", {
detail: {
path: this.path,
default: this.default,
exact: this.exact,
sensitive: this.sensitive,
strict: this.strict,
callback: this.routeChange,
uniqueId: this.uniqueId,
},
bubbles: true,
composed: true,
})
);
}
disconnectedCallback() {
this.dispatchEvent(
new CustomEvent("lwcerouter_removeeventlistener", {
detail: {
path: this.path,
callback: this.routeChange,
},
bubbles: true,
composed: true,
})
);
}
_routeChange({ found, data = {} }) {
this.rendered = found;
this.routeParams = data;
this.sendRouteParams();
}
sendRouteParams() {
if (this.rendered) {
this.wireAdapters.forEach((adapter) => adapter.provide(this.routeParams));
}
}
}