feat: Subscribe to store inside a component
wobsoriano opened this issue · 5 comments
Hi, thanks for this great plugin. I've been using it and pardon for not following the format.
Is there a way to subscribe to the store in a component? Something like this in options API:
created() {
this.$store.subscribe((mutation, state) => {
if (mutation.type === 'snackbar/SHOW_MESSAGE') {
this.message = state.snackbar.content;
this.color = state.snackbar.color;
this.show = true;
}
});
}
I'm using vuetify currently and I had to create a plugin for a reusable snackbar since I cannot directly put a snackbar model in a store (mutation errors), so I had to subscribe to it and set the values locally.
Any help would be appreciated. Thanks.
@sorxrob This should still work. But I take it you mean - to subscribe to a store via the accessor, in a typed way?
@sorxrob This should still work. But I take it you mean - to subscribe to a store via the accessor, in a typed way?
Yes, sorry the post was incomplete. In a typed way.
My index.ts
file contains
import { getAccessorType } from 'nuxt-typed-vuex';
import * as auth from './auth';
import * as snackbar from './snackbar';
export const accessorType = getAccessorType({
modules: {
auth,
snackbar,
},
});
@sorxrob This doesn't answer your question, but may help with your implementation. I also use vuetify with a vuex controlled snack component. The following code has not been tested but should give you an idea of how to implement it - the golden ticket is in the computed prop for show
in the snack component.
store/snackControl.ts
import { getterTree, mutationTree } from 'typed-vuex'
export interface snackControlState {
message: string
color: string
show: boolean
}
export const state = (): snackControlState => ({
message: '',
color: 'primary',
show: false
})
export const mutations = mutationTree(state, {
SHOW_MESSAGE(state, options: snackControlState) {
Object.assign(state, options)
},
SET_SHOW(state, v: boolean) {
state.show = v
}
})
export const getters = getterTree(state, {
getMessage: state => state.message,
getColor: state => state.color,
getShow: state => state.show
})
store/index.ts
import { getAccessorType } from 'typed-vuex'
import * as snackControl from '~/store/snackControl'
export const accessorType = getAccessorType({
modules: {
snackControl
}
})
snack.vue
<template lang="html">
<v-snackbar v-model="show" :timeout="2000" top :color="color">
{{ message }}
</v-snackbar>
</template>
<script lang="ts">
import Vue from 'vue'
export default Vue.extend({
computed: {
show: {
get() {
return this.$accessor.snackControl.getShow
},
set(v: boolean) {
this.$accessor.snackControl.SET_SHOW(v)
}
},
color() {
return this.$accessor.snackControl.getColor
},
message() {
return this.$accessor.snackControl.getMessage
}
},
methods: {
// Use this method in a different page/component to show the snack
showSnackMessage() {
this.$accessor.snackControl.SHOW_MESSAGE({ message: 'Hello snack', color: 'warning', show: true })
}
}
})
</script>
<style lang="scss" scoped></style>
@JamieCurnow awesome, will try this out. Thanks!
@JamieCurnow thanks for the tip, indeed that works!
snackbar.ts
export const state = () => ({
show: false,
content: '',
color: '',
});
export const mutations = mutationTree(state, {
[MutationTypes.SHOW_MESSAGE](state, payload: ISnackbar) {
Object.assign(state, payload);
},
[MutationTypes.SET_SHOW](state, payload: boolean) {
state.show = payload;
},
});
export const getters = getterTree(state, {
getContent: (state) => state.content,
getColor: (state) => state.color,
getShow: (state) => state.show,
});
snackbar.vue
<template>
<v-snackbar v-model="show" :color="color">
{{ message }}
<template v-slot:action="{ attrs }">
<v-btn text v-bind="attrs" @click="show = false">Close</v-btn>
</template>
</v-snackbar>
</template>
<script lang="ts">
import { defineComponent, computed } from '@vue/composition-api';
export default defineComponent({
setup(_props, { root }) {
const show = computed({
get: () => root.$accessor.snackbar.getShow,
set: (v: boolean) => root.$accessor.snackbar.SET_SHOW(v),
});
const message = computed(() => root.$accessor.snackbar.getContent);
const color = computed(() => root.$accessor.snackbar.getColor);
return {
show,
message,
color,
};
},
});
</script>