2

I'm following some tutorials to learn how to use the history events in JS to deal with what is essentially paging on one of my forms. I have added the following code to an onClick event that changes the page:

state = {'actionCode': 'pageChange', 'pageNum': pageNum};
window.history.pushState(state, 'Page ' + pageNum, '/subF/fileName.cfm#page' + pageNum);
console.log(state);

I tried a number of other variations originally, including blank or null title and url arguments.

I then added this to the bottom of my JS file to see what I have to work with:

function checkState(e) {
    console.log(e);
    console.log(history.state);
}

$(function() {
    window.onpopstate = checkState;
});

What I expected to see after changing 'pages' (running the first snippet of code) and then clicking the back button was a e.state object containing actionCode and pageNum variables. Instead, I see the state appear as null even though the object itself appears to hold the data immediately after passing said object to pushState:

console output

I get the same null value when dumping history.state, so I assume the problem is with the push and not the get, or that I'm completely misunderstanding how these functions work.

What I expected to be able to do was add code to checkState that looks at the 'actionCode' and takes appropriate action based on that, reference the variables I know will exist in the state object for that particular actionCode.

Nicholas
  • 1,974
  • 4
  • 20
  • 46
  • If you trigger the `onClick` event twice (by changing the page twice), and then click the browser back button, does the `state` include the information from the first `onClick`? – Ric Dec 27 '20 at 21:35
  • @Ric Yes, it does. That's enlightening; I may be looking at how this works a little wrong. – Nicholas Dec 27 '20 at 23:41
  • @Nicholas Like I said in my answer below, it works because you're pushing 2 states and you're performing an actual action that will trigger a 'popstate' event dispatch by pressing the 'back' button of the browser. – zhulien Dec 28 '20 at 09:24
  • @zhulien Thanks. My mistake was that I was expecting the state I put into the history when moving to page 2 to be there when I hit back to get from page 2 to page 1. I was just looking at what the states were attached to wrong; I thought they were attached to where I came from; not where I'm going. By adding a state on page load this all works for me. – Nicholas Dec 28 '20 at 23:33

1 Answers1

1

In order for the onpopstate event to get triggered, you have to perform an actual "change history" action, i.e. clicking the browser BACK/FORWARD button or manually calling history.back() / history.forward() / history.go(). Simply pushing/replacing a state won't trigger an event.

You can try this:

<script>
    window.onpopstate = function(event) {
        console.log(event);
    };

    const state1 = {'actionCode': 'pageChange', 'pageNum': 1};
    const state2 = {'actionCode': 'pageChange', 'pageNum': 2};

    history.pushState(state1, 'Page ' + state1.pageNum, '/subF/fileName.cfm#page' + state1.pageNum);
    history.pushState(state2, 'Page ' + state2.pageNum, '/subF/fileName.cfm#page' + state2.pageNum);

    history.go(-1);
</script>

Here, the invocation of history.go(-1) will load the previous page from the session history thus firing an onpopstate event and you will see the state is there.

You can learn more about the peculiarities here: MDN page.

If you're trying to simulate handling of location/state change for new entries, you'll have to manually fire a PopStateEvent(or any custom one with a respective handler).

const event = new PopStateEvent('popstate', { state: state });
window.dispatchEvent(event);

or simply:

window.dispatchEvent(new Event('popstate'));
zhulien
  • 5,145
  • 3
  • 22
  • 36