@legumeinfo/web-components
Version:
Web Components for the Legume Information System and other AgBio databases
105 lines • 3.83 kB
JavaScript
/**
* A controller that allows components to interact with URL query string
* parameters in a manner that triggers changes in the component's template when
* parameter values change.
*/
export class LisQueryStringParametersController {
/**
* @param host - The component that's using the controller.
*/
constructor(host) {
/** @ignore */
this._preUpdateListeners = [];
/** @ignore */
this._listeners = [];
(this.host = host).addController(this);
}
/** @ignore */
hostConnected() {
window.addEventListener('popstate', this._popState.bind(this));
}
/** @ignore */
hostDisconnected() {
window.removeEventListener('popstate', this._popState.bind(this));
}
/**
* Gets the value of a URL query string parameter. This is reactive when used
* inside a component template.
*
* @param name - The name of the parameter to get the value of.
* @param defaultValue - The default value to return if the parameter isn't
* in the query string.
*
* @returns The value of the parameter or the default value provided.
*/
getParameter(name, defaultValue = '') {
const params = new URLSearchParams(window.location.search);
const value = params.get(name);
if (value !== null) {
return decodeURIComponent(value);
}
return defaultValue;
}
/**
* Updates the URL query string parameters.
*
* @param parameters - An object mapping parameter names to the values to
* assign them.
*/
setParameters(parameters) {
// don't update the query string if there's nothing to update
if (!this._differentValues(parameters)) {
return;
}
// push the new params onto the browser's history stack
const queryString = '?' +
Object.entries(parameters)
.map(([key, value]) => `${key}=${encodeURIComponent(value)}`)
.join('&');
history.pushState(parameters, '', queryString);
}
/**
* Adds a listener to the {@link !popstate | `'popstate'`} event that will be executed
* before the host's DOM is updated.
*
* @param listener - The listener to subscribe to the event.
*/
addPreUpdateListener(listener) {
// each listener is called in the scope of the host
this._preUpdateListeners.push(listener.bind(this.host));
}
/**
* Adds a listener to the {@link !popstate | `'popstate'`} event that will be executed
* after the host's DOM is updated.
*
* @param listener - The listener to subscribe to the event.
*/
addListener(listener) {
// each listener is called in the scope of the host
this._listeners.push(listener.bind(this.host));
}
/** @ignore */
// determines if any of the given parameters have different values than the URL parameters
_differentValues(parameters) {
const params = new URLSearchParams(window.location.search);
return Object.entries(parameters).some(([key, value]) => encodeURIComponent(value) !== params.get(key));
}
/** @ignore */
// calls all listeners of the popstate event
_popState(event) {
// call each pre update listener
this._preUpdateListeners.forEach((listener) => {
listener(event);
});
// redraw the host
this.host.requestUpdate();
// wait for the redraw to complete in case any listeners rely on state from the template
this.host.updateComplete.then(() => {
// call each listener
this._listeners.forEach((listener) => {
listener(event);
});
});
}
}
//# sourceMappingURL=lis-query-string-parameters-controller.js.map