Last active
April 10, 2024 18:24
-
-
Save liamja/76416c9823c7949a7b00db2e74790455 to your computer and use it in GitHub Desktop.
An Alpine.js plugin to store state in the query string
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Alpine.plugin((Alpine) => { | |
Alpine.magic('query', () => (params) => { | |
const url = new URL(window.location.href) | |
// For each key in the params object, set the value to the query string value or the default value | |
let reactiveParams = Alpine.reactive(Object.keys(params).reduce((newParams, key) => { | |
const defaultValue = params[key] | |
const value = url.searchParams.get(key) | |
newParams[key] = value ?? defaultValue | |
url.searchParams.set(key, newParams[key]) | |
return acc | |
}, {})) | |
history.replaceState(null, '', url.toString()) | |
Alpine.effect(() => { | |
const url = new URL(window.location.href) | |
// For each key in the params object, update the query parameter value to the newly set value | |
Object.keys(reactiveParams).forEach(key => { | |
url.searchParams.set(key, reactiveParams[key]) | |
}) | |
history.replaceState(null, '', url.toString()) | |
}) | |
return reactiveParams | |
}) | |
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!-- Wrap the usual data object in $query() --> | |
<!-- If ?tab=second is set in the URL, then the second tab will be shown on page load. --> | |
<!-- Changing tabs will update the query parameter automatically. --> | |
<div x-data="$query({ 'tab': 'first' })"> | |
<div> | |
<!-- Navigation Links --> | |
<button @click="tab = 'first'">First</button> | |
<button @click="tab = 'second'">Second</button> | |
</div> | |
<div x-show="tab === 'first'"> | |
This is the profile tab. | |
</div> | |
<div x-show="tab === 'second'"> | |
This is the second tab. | |
</div> | |
</div> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment