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 e 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.
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 e 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.
Share Improve this question edited Sep 21, 2019 at 12:09 Rounin asked Sep 21, 2019 at 11:07 RouninRounin 29.6k13 gold badges98 silver badges123 bronze badges1 Answer
Reset to default 6Final Answer:
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 pletely.
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);
Best Answer I can e up with (Second Attempt):
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 ments below) a page is accessed via the forward and back buttons
I also know that:
- The
window.load
event listener covers Point 1.; - The
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/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 e up with. If anyone has a dramatically better idea, I'll be happy to transfer the green tick.
First Attempt at an Answer:
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:
- when the page loads or reloads
- when
window.history.pushstate
is invoked
I can use the following:
window.addEventListener('load', checkQueryString);
and
window.history.pushState({action : 'myAction'}, document.title, '?action=myAction');
checkQueryString();