Capture the state of the application in the URL. All Gramex apps use this approach. This makes it easy to:
Do not use the URL to capture state if:
When the user performs an action capture the state as form-encoded URL query. For example:
city=Rome
city=Rome&city=Olso
city=Rome&city=Olso&top=10
You can use the @gramex/url package to encode/decode state:
<script src="https://cdn.jsdelivr.net/npm/@gramex/url/url.min.js">
<script>
<script>
const query = gramex.url.encode({city: ['Rome', 'Oslo'], top: 10})
const state = gramex.url.decode(query)
</script>
If you only have single values for keys, use URLSearchParams:
const query = new URLSearchParams({ city: "Rome", top: 10 }).toString();
const state = Object.fromEntries(new URLSearchParams(query));
To reload your page on every action, add the state after a ?
. For example, /page?city=Rome&top=10
.
HTML forms do this automatically. For example, submitting this form will reload the page with ?city=Rome&top=10
added.
<form>
<label>City: <input name="city" value="Rome" /></label>
<label>Top: <input name="top" value="10" /></label>
<button type="submit">Submit</button>
</form>
Use window.location.search
to reload the page with the new state:
const query = new URLSearchParams({ city: "Rome", top: 10 }).toString();
window.location.search = query;
// This will immediately reload the page with ?city=Rome&top=10
On page load, you can access the query via window.location.search
:
const query = window.location.search;
const state = Object.fromEntries(new URLSearchParams(query));
// Now do what you want with the state, e.g. update the page filters
To update your page without reloading, add the state after a #?
. For example, /page#?city=Rome&top=10
.
Use window.location.hash
to update the page without reloading:
window.addEventListener("hashchange", renderPage);
function renderPage() {
const query = window.location.hash.slice(2);
const state = Object.fromEntries(new URLSearchParams(query));
// Now do what you want with the state, e.g. update the page filters
}
render();
const query = new URLSearchParams({ city: "Rome", top: 10 }).toString();
window.location.hash = "?" + query;
When listening to filter changes or button clicks, NEVER update the page directly.
Instead, update the hash. The hashchange
listener updates the page.
(Otherwise, the user state and page go out-of-sync.)