I would like to update window.location.search
without reloading the document and then execute a function based on the updated values in window.location.search
.
When the user clicks a button, that button's onclick
event fires the following function:
window.history.pushState({action : 'myAction'}, document.title, '?action=myAction');
So far so good. The window.location.search
updates in the browser URL bar.
But I can't find a general background event listener which detects this update - something like onhashchange
but for query strings.
The best I can come up with is:
window.history.pushState({action : 'myAction'}, document.title, '?action=myAction');
window.history.pushState({action : 'myAction'}, document.title, '?action=myAction');
window.history.back();
window.addEventListener('popstate', () => console.log(event.state.action));
This works but I'm convinced there must be a more elegant approach.
Window location.search The search property returns the querystring part of a URL, including the question mark (?). The search property can also be used to set the querystring.
host. The host property of the Location interface is a string containing the host, that is the hostname, and then, if the port of the URL is nonempty, a ':' , and the port of the URL.
I was mostly happy with the Second Attempt answer immediately below.
But I really didn't like:
history.back();
history.forward();
which I adopted to trigger the popstate
event, manually.
In practice, I found this hack worked sometimes, it was slow at other times and on occasion it failed completely.
On paper, it feels too makeshift.
After repeatedly searching and experimenting (this was remarkably hard to find), I have finally found the correct syntax for manually firing a popstate
event.
It's as simple as dispatching
this:
new Event('popstate')
Like this:
let myEvent = new Event('popstate');
window.dispatchEvent(myEvent);
So the final code is:
window.history.pushState({action : 'myAction'}, document.title, '?action=myAction');
let queryStringChange = new Event('popstate');
window.dispatchEvent(queryStringChange);
Building on the following:
I know for certain that the query-string will only need to be checked either:
when the page loads or reloads;
when window.history.pushstate
is invoked;
or when (as @Kaiido astutely pointed out in the comments below) a page is accessed via the forward and back buttons
I also know that:
window.load
event listener covers Point 1.;window.popstate
event listener covers Point 3.;This only leaves Point 2.
Dealing with Point 2
As MDN reports:
Note that just calling
history.pushState()
orhistory.replaceState()
won't trigger a popstate event. The popstate event will be triggered by doing a browser action such as a click on the back or forward button (or callinghistory.back()
orhistory.forward()
in JavaScript).Source: https://developer.mozilla.org/en-US/docs/Web/API/Window/popstate_event
But this means that rather than using (as in my first attempt, below):
window.history.pushState({action : 'myAction'}, document.title, '?action=myAction');
checkQueryString(); // DIRECT INVOCATION OF FUNCTION
I can use instead:
window.history.pushState({action : 'myAction'}, document.title, '?action=myAction');
history.back();
history.forward();
This means that rather than needing to invoke the function directly, I can now allow the same window.popstate
event listener covering Point 3 to do its work, giving me cleaner, more logically separated code.
N.B. I find it... weird... that pressing the forward button alone will fire the window.popstate
event listener, but invoking window.history.pushState()
will not... (necessitating the immediately subsequent addition of history.back(); history.forward();
to duplicate the functionality of a forward button).
But, as above, this is the best, cleanest, most optimised (in terms of logical separation and future code maintenance) solution I can come up with. If anyone has a dramatically better idea, I'll be happy to transfer the green tick.
I am tentatively concluding that there is no way to achieve this effect using a background event listener which can detect when the query string updates.
Instead, since I know for certain that the query-string will only need to be checked either:
window.history.pushstate
is invokedI can use the following:
window.addEventListener('load', checkQueryString);
and
window.history.pushState({action : 'myAction'}, document.title, '?action=myAction');
checkQueryString();
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With