Skip to content

Instantly share code, notes, and snippets.

@liamja
Last active April 10, 2024 18:24
Show Gist options
  • Save liamja/76416c9823c7949a7b00db2e74790455 to your computer and use it in GitHub Desktop.
Save liamja/76416c9823c7949a7b00db2e74790455 to your computer and use it in GitHub Desktop.
An Alpine.js plugin to store state in the query string
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
})
})
<!-- 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