Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

http-equiv="refresh" and hx-boost don't work together (well) #3213

Open
dashorst opened this issue Feb 26, 2025 · 5 comments
Open

http-equiv="refresh" and hx-boost don't work together (well) #3213

dashorst opened this issue Feb 26, 2025 · 5 comments
Labels
bug Something isn't working help wanted We would be interested in a PR that resolves that issue

Comments

@dashorst
Copy link

In an application I have a top level menu that is hx-boosted, and have in the <head> section a refresh for every 3 minutes:

<head>
    <meta http-equiv="refresh" content="180">

When I navigate to a different top menu item, it is nicely hx-boosted, and even the URL in the browser bar reflects the new URI of the page. However when the 3 minutes are up, the browser requests the original URL instead of the updated URL in the browser's URL field.

If I request the URL of the menu item manually the page correctly stays on that URI.

@Telroshan Telroshan added bug Something isn't working help wanted We would be interested in a PR that resolves that issue labels Feb 27, 2025
@MichaelWest22
Copy link
Contributor

I can't think of an easy way to fix this in htmx as this is browser built in behavior causing this and would probably need a major change to the browsers to support this use case. I think all web frameworks and libraries that manipulate the URL without performing old school refreshes (e.g. All SPA frameworks) will be impacted by this issue.

Note the purpose of hx-boost is to avoid refreshing the whole page when it is not needed so it is kind of at odds with this browser built in feature.

However it should be fairly easy to replicate this browser feature in a htmx website. htmx allows much much more control and you can place a hx-trigger with "every 180s" on any element you want on the page and get it to fetch and update whatever you want from your server and place it however or wherever you want. you should be able to put this on a hx-get="" which i think will fetch the current url for example. But reloading the whole page every time like this may not be really what you want and you may only need to replace a partial area of your page like for example the latest news feed div on the right with latest content every 180 seconds. Also it is possible to do advanced things like do the get every 180 seconds but detect on the server if no new updates send back nothing using hx-swap="none" and if there are updates detected instead return them in a hx-swap-oob or return the hx-reswap header to override the none swap when required. Another handy thing to know is that if you place a id on the element that does the polling every 180 seconds then the request will include this id in the HX-Trigger request header so your backend server knows it is a polling request to the url and not a new page navigation so you can use this to help decide what optional response to return

@MichaelWest22
Copy link
Contributor

<div hx-trigger="every 180s" hx-get="" hx-target="body"></div>

You could try adding this to a page to see if this works the same as the refresh browser head method.

@scrhartley
Copy link
Contributor

scrhartley commented Feb 28, 2025

If you want a hard refresh, then a JS solution seems fine and it can fall back to the meta tag (if JS isn't available then htmx wouldn't work anyway). Set the JS refresh trigger to be just before the meta tag one:

<meta http-equiv="refresh" content="180">
<script>setTimeout(() => window.location.reload(true), (180 - 1) * 1000)</script>

@scrhartley
Copy link
Contributor

Otherwise:

<meta http-equiv="refresh" content="180">
<script>
    document.addEventListener('htmx:pushedIntoHistory', function() {
        const meta = document.head.querySelector('meta[http-equiv=refresh]')
        meta.replaceWith(meta.cloneNode())
    })
</script>

@dashorst
Copy link
Author

dashorst commented Mar 3, 2025

The last solution of @scrhartley seems like the best way if I was to keep the boost and the hard refresh. I've removed the boost from the navigation element which fixed the issue for the users.

Thanks for looking into this!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working help wanted We would be interested in a PR that resolves that issue
Projects
None yet
Development

No branches or pull requests

4 participants