Is it possible to access VueX Getters during dynamic component registration - vue.js

Is it possible to access VueX store getters when defining a dynamic component using webpack?
I'm using multiple modules inside my store.
Example:
components: {
'some-template': () => {
const someVal = this.$store.getters.someVal;
return System.import(`./some-template/${someVal}.vue`)
}
}
Main.js
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
import { someStore } from ./stores/some-store'
import { otherStore } from ./stores/other-store'
new Vue({
el: '#app',
store: new VueX.Store({
modules: {
someStore,
otherStore
}
})
})
Store example:
export const someStore = {
state: {
someVal: 'blah'
},
getters: {
someVal(state) {
return state.someVal;
}
}
}

To work around the issue with modules, I instead created an app store that will default using new Vuex instance, then dynamically add modules as needed. That way, I can import the store where needed and access the getters

Related

Modules vs Multiple vuex store files

I am working on a project using vue and vuex. And I think most of the people are having the problem, after sometime the store.js (or index.js) is getting too big. So I want to split the store.js file. After some google I found I can use Modules to overcome this problem. BUT I tried also with creating a new Instance of vuex and it works perfectly fine.
Single instance with modules :
---store.js
import Vuex from "vuex";
import thisismodule1 from "./modules/module1";
import thisismodule2 from "./modules/module2";
const createStore = () => {
return new Vuex.Store({
modules: {
module1: thisismodule1,
module2: thisismodule2
}
});
};
export default createStore;
const store = new Vuex.Store({
module
});
Multiple files with multiple instances:
---storeCar.js
---storeHouse.js
---storeTree.js
...
So my question is, is this allowed or do I have to use modules with single instance?
Thank you in advance!
there is a best practice for that:
Create a file. that's name is Shared
Create a Store folder and create a modules folder on it:
you should modules in the modules folder and define your store for a target:
for example:
import * as types from "../types";
const state = {
currentPage: {}
};
const getters = {
[types.avatarManagement.getters.AVATAR_MANAGEMENT_GET]: state => {
return state.currentPage;
}
};
const mutations = {
[types.avatarManagement.mutations.AVATAR_MANAGEMENT_MUTATE]: (
state,
payload
) => {
state.currentPage = payload;
}
};
const actions = {
[types.avatarManagement.actions.AVATAR_MANAGEMENT_ACTION]: (
{ commit },
payload
) => {
commit(types.avatarManagement.mutations.AVATAR_MANAGEMENT_MUTATE, payload);
}
};
export default {
state,
getters,
mutations,
actions
};
Create index.js for define Vuex and import your modules:
index.js file:
import Vue from "vue";
import Vuex from "vuex";
import avatarManagement from "./modules/avatarManagement";
Vue.use(Vuex);
export default new Vuex.Store({
modules: {
avatarManagement
}
});
5) also you can types of your vuex store on Type.js file:
type.js:
export const avatarManagement = {
getters: {
AVATAR_MANAGEMENT_GET: "AVATAR_MANAGEMENT_GET"
},
mutations: {
AVATAR_MANAGEMENT_MUTATE: "AVATAR_MANAGEMENT_MUTATE"
},
actions: {
AVATAR_MANAGEMENT_ACTION: "AVATAR_MANAGEMENT_ACTION"
}
};
***for get data from Store:
computed: {
...mapGetters({
registrationData:types.avatarManagement.AVATAR_MANAGEMENT_GET,
getDataFromStore() {
return this.registrationData;
}
}
***for Change data to Store and mutate that:
methods: {
goToActivity() {
const activity = {
companyList: this.categories
};
this.$store.commit(types.avatarManagement.AVATAR_MANAGEMENT_MUTATE, {
newData
});
},
}

How can I fix '[vuex] unknown action type: lookupName' within my Vue component?

I am having an issue calling up an action from my Vue component using this.$store.dispatch('lookupName'). I have tried console logging the this.$store method, but the actions within it are empty.
Main.js
import Vue from "vue";
import App from "./App.vue";
import router from "./router";
import store from "./store";
new Vue({
router,
store,
render: h => h(App)
}).$mount("#app");
store/index.js
import Vue from 'vue'
import Vuex from 'vuex'
import { findCertificate } from '#/api';
Vue.use(Vuex)
const state = {
// single source of data
nameLookup: {},
}
const actions = {
// asynchronous operations
lookupName(context, form){
return findCertificate(form)
}
}
const store = new Vuex.Store({
state,
actions,
mutations,
getters
})
export default store
Vue Component
import VueRecaptcha from 'vue-recaptcha';
import { mapGetters, mapActions} from 'vuex'
export default {
created() {
},
methods: {
...mapActions({
lookupName: 'lookupName'
}),
...mapActions({
add: 'lookupName'
}),
onCaptchaVerified: function(recaptchaToken){
this.$refs.recaptcha.reset();
console.log(this.$store.dispatch('lookupName', this.form))
},
}
}
Why am I still getting this error? I have looked up many other people's questions about similar issues, but those solutions did not work for me.

vuex unknown action type when attempting to dispatch action from vuejs component

I'm using laravel, vue and vuex in another project with almost identical code and it's working great. I'm trying to adapt what I've done there to this project, using that code as boilerplate but I keep getting the error:
[vuex] unknown action type: panels/GET_PANEL
I have an index.js in the store directory which then imports namespaced store modules, to keep things tidy:
import Vue from "vue";
import Vuex from "vuex";
var axios = require("axios");
import users from "./users";
import subscriptions from "./subscriptions";
import blocks from "./blocks";
import panels from "./panels";
Vue.use(Vuex);
export default new Vuex.Store({
state: {
},
actions: {
},
mutations: {
},
modules: {
users,
subscriptions,
blocks,
panels
}
})
panels.js:
const state = {
panel: []
}
const getters = {
}
const actions = {
GET_PANEL : async ({ state, commit }, panel_id) => {
let { data } = await axios.get('/api/panel/'+panel_id)
commit('SET_PANEL', data)
}
}
const mutations = {
SET_PANEL (state, panel) {
state.panel = panel
}
}
export default {
namespaced: true,
state,
getters,
actions,
mutations
}
Below is the script section from my vue component:
<script>
import { mapState, mapActions } from "vuex";
export default {
data () {
return {
}
},
mounted() {
this.$store.dispatch('panels/GET_PANEL', 6)
},
computed:
mapState({
panel: state => state.panels.panel
}),
methods: {
...mapActions([
"panels/GET_PANEL"
])
}
}
</script>
And here is the relevant code from my app.js:
import Vue from 'vue';
import Vuex from 'vuex'
import store from './store';
Vue.use(Vuex)
const app = new Vue({
store: store,
}).$mount('#bsrwrap')
UPDATE:: I've tried to just log the initial state from vuex and I get: Error in mounted hook: "ReferenceError: panel is not defined. I tried creating another, very basic components using another module store, no luck there either. I checked my vuex version, 3.1.0, the latest. Seems to be something in the app.js or store, since the problem persists across multiple modules.
Once you have namespaced module use the following mapping:
...mapActions("panels", ["GET_PANEL"])
Where first argument is module's namespace and second is array of actions to map.

this.$store is undefined following example application structure

I'm trying to use Vuex as shown in the application structure documentation. However, $store isn't showing in Vue dev tools and returning undefined in my code. I've used the shopping cart example as a reference.
import Vue from 'vue/dist/vue';
import store from './store';
import router from './router';
const app = new Vue({
el: '#app',
store,
router,
computed: {
loading() {
return this.$store.state.application.loading.active;
}
}
});
In store/index.js (following the example layout) I have:
import Vue from 'vue';
import Vuex from 'vuex';
import application from './modules/application';
Vue.use(Vuex);
export default new Vuex.Store({
modules: {
application
}
});
And finally in store/modules/application.js:
const state = {
loading: {
active: true,
message: ''
},
syncing: {
active: false,
message: ''
}
}
const getters = {
//
}
const actions = {
//
}
const mutations = {
/**
* Update Loading
*
* #param {*} state
* #param {string} appState
* #param {boolean} active
* #param {string} message
*/
updateAppState(state, appState = false, active = false, message = '') {
if (Object.keys(state).includes(appState)) {
state.appState = {
active: active,
message: message
}
}
}
}
export default {
namespaced: true,
state,
getters,
actions,
mutations
}
Note i'm importing my router instance in a similar manor and it's working, router/index.js:
import Vue from 'vue/dist/vue';
import VueRouter from 'vue-router';
import ContentDefault from '../components/main/ContentDefault';
Vue.use(VueRouter);
export default new VueRouter({
routes: [
{
// Default view
path: '/',
components: {
default: ContentDefault
},
}
]
});
EDIT: Side issue, wasn't able to access $store in child components, it was because I was importing a different version of Vue in my main app and store files, vue instead of vue/dist/vue
You don't need the $ in your app const. And since you've just imported store you can use it directly.
Try the following:
import Vue from 'vue/dist/vue';
import store from './store';
import router from './router';
const app = new Vue({
el: '#app',
store,
router,
computed: {
loading() {
return store.state.application.loading.active;
}
}
});

Vuex doesn't work as expected - problem with import?

Trying to use Vuex states in components.
This works fine:
main.js:
const store = new Vuex.Store({
state: {
counter: 1
},
mutations: {
increment(state) {
state.counter++
}
}
})
new Vue({
store,
render: h => h(App)
}).$mount('#app')
and inside component:
<span>{{this.$store.state.test}}</span>
When I tried to move Vuex to a separate store.js, it doesn't work.
store.js (right near main.js):
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
counter: 1
},
mutations: {
increment(state) {
state.counter++
}
}
})
and inside component I make import:
import store from '../store',
than try to use:
<span>{{store.state.test}}</span>
and I get
Property or method "store" is not defined on the instance
<span>{{this.$store.state.test}}</span> results
Uncaught ReferenceError: store is not defined
I've tried to change export default new Vuex.Store({...}) to export const store = new Vuex.Store({...}) but it didn't helped.
P. S. This works for me:
inside component:
computed: {
counter() {
return store.state.counter
}
}
and <span>{{counter}}</span>.
But is there other way without using computed properties? Because I use Vuex for calling its states globally, and here I have to define computed in each component anywhere...
your export and import don't follow the ES6 rules,
if you are using export const store = new Vuex.Store({...})
you need to either import like this
import {store} from '../store.js'
if not, update your code to this:
import Vue from 'vue' import Vuex from 'vuex'
Vue.use(Vuex)
export default const store = new Vuex.Store({ state: {
counter: 1 }, mutations: {
increment(state) {
state.counter++
} } })
I went this way:
store.js:
export default new Vuex.Store({...})
main.js:
import store from './store'
new Vue({
...
store,
render: h => h(App)
}).$mount('#app')
Than in any component's template: <span>{{this.$store.state.counter}}</span>.
Can't confirm this is the best way, but it works for me.