yysun / apprun

AppRun is a JavaScript library for developing high-performance and reliable web applications using the elm inspired architecture, events and components.
https://apprun.js.org
MIT License
1.18k stars 57 forks source link

Update URL in the browser's address bar when SPA component activates #102

Closed jkleiser closed 4 years ago

jkleiser commented 4 years ago

In my game SPA a button click in the "R" component publishes a "#gameAsX" event, and this event is handled by the "G" component. When I click that button, my SPA activates and displays the "G" component (and its event handler does its job), but the URL in the browser's address bar does not reflect the component switch. It still shows ".../?#R", and the Nav Bar menu also "wrongly" indicates that "R" is the selected component. What should I do to fix this?

yysun commented 4 years ago

You can set:

location.hash = ‘gameAsX’

It will change the address bar and will also fire the #gameAsX event.

On Sun, Jul 5, 2020 at 4:53 AM Jon Kleiser notifications@github.com wrote:

In my game SPA a button click in the "R" component publishes a "#gameAsX" event, and this event is handled by the "G" component. When I click that button, my SPA activates and displays the "G" component (and its event handler does its job), but the URL in the browser's address bar does not reflect the component switch. It still shows ".../?#R", and the Nav Bar menu also "wrongly" indicates that "R" is the selected component. What should I do to fix this?

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/yysun/apprun/issues/102, or unsubscribe https://github.com/notifications/unsubscribe-auth/AABJUM3CLEJHEGWRJHFRFIDR2A5PRANCNFSM4OQYZUPQ .

jkleiser commented 4 years ago

Doing onclick={e => location.hash = 'gameAsX'} does not seem like a possibility for me, as I also have to include some data. Today I do $onclick={["#gameAsX", game]}, but that does not change the URL.

yysun commented 4 years ago

You can send event parameters in the hash separated by / :

location.hash = ‘gameAsX/data1/data2’

or use history.pushState:

history.pushState(null, null, '#gameAsX/' + data);

See https://developer.mozilla.org/en-US/docs/Web/API/History_API/Working_with_the_History_API

jkleiser commented 4 years ago

It seems I have found a working solution. I discovered that in my main.tsz, all calls to start() or mount() had a second route argument, like here:

new About().mount(element, {route: '#About'});

I had not seen this second argument in any of my previous SPA projects. I therefore removed it from my main component (the "G"). Then in a local "gameAsX" event handler in my "R" component, I did the global app.run("#gameAsX", game) which would be handled by my "G" component, followed by location.hash = "#G" to fix the URL. If this is the optimal solution, I don't know, but at the moment it works.