Reputation: 2625
I'm using a store for a modal and like to use the magic $watch
method like so:
Alpine.store('modal', {
init() {
this.$watch('this.open', (val) => console.log(val))
// Here I like to do if(open) { document.body.classList.add('overflow-hidden') }
},
open: false,
id: null,
close() {
this.open = false
this.id = null
}
})
But I get TypeError: this.$watch is not a function
Upvotes: 4
Views: 2351
Reputation: 857
You can't use the $watch in the Alpine.store, still you have two options available
Use Store's data as x-data of html element and watch for that data using $watch in html itself. So here mystore's
data will be the x-data itself so watching it will eventually watch store's isStoreOpen
property of that store.
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/cdn.min.js"></script>
<script>
Alpine.store('mystore',{
init() {
console.log('hi there in store')
},
isStoreOpen: true,
toggle() {
this.isStoreOpen = !this.isStoreOpen;
}
})
</script>
<div x-data="$store.mystore" x-init="$watch('isStoreOpen', (val) => console.log(val))">
<p>
What you can toggle
</p>
<button @click="toggle()" x-text="$store.mystore.isStoreOpen">
</button>
</div>
Or for some reason if you need to use magic things in store's method itself or have different x-data
then you have to pass magic things using parameters. Here i took startStoreWatch
method in init
method of data instead of init
method of store as the store's init
method is used to init that store.
This way store will watch it's own property same as the data watches it's own.
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/cdn.min.js"></script>
<script>
Alpine.store('mystore',{
init() {
console.log('hi there in store')
},
count: 0,
startStoreWatch($watch, $store) {
$watch('$store.mystore.count', (val) => console.log(val))
},
toggle() {
this.count++;
}
})
</script>
<div x-data="{
init() {
// here we are watching isOpen of data and count of store
this.$store.mystore.startStoreWatch(this.$watch, this.$store)
this.$watch('isOpen', (val) => console.log(val))
},
isOpen: false,
toggle() {
this.isOpen = !this.isOpen;
}
}">
<p x-show="isOpen">
What you can toggle
</p>
<button @click="() => {
toggle()
$store.mystore.toggle()
}" x-text="`store is toggled ${$store.mystore.count} times`">
</button>
</div>
Upvotes: 0
Reputation: 155
Wrap the second argument in an arrow function:
Alpine.store('modal', () => ({
init() {
this.$watch('this.open', (val) => console.log(val))
},
open: false,
id: null,
close() {
this.open = false
this.id = null
}
}))
Arrow functions capture the this
value of the enclosing context, thus giving you access to Alpine's magic methods.
Upvotes: 2