I am new to Vue.js. I have recently learned Vuex and trying to implement in my project.
I am calling calling an action dispatch from my dashboard component. And calling ...mapGetter in message component computed section. And I want to debug the data that I am getting.
I already searched my problem. But couldn't find it. What I learned I can't use console.log() in computed. I have to use debugger. But when I am using debugger it's saying debugger is a reserved word.
in my store:
state: {
conversationThreads: [],
conversation: [],
users: [],
},
getters: {
conversation: state => {
return state.conversation;
}
},
mutations: {
[MUTATION_TYPES.SET_CONVERSATION](state, conversationThread){
state.conversation= conversationThread;
}
},
actions: {
getConversationByID: ({ commit }, conversationInfo) => {
console.log("conversationData: ", conversationInfo)
axios.get("https://some_API" + conversationInfo.id)
.then(response => {
let conversationThread = response.data.messages.data.map(res => ({
name: res.from.name,
msg: res.message
}));
commit(MUTATION_TYPES.SET_CONVERSATION, conversationThread);
})
.catch(error => console.log(error))
}
}
in my dashboard component:
methods: {
selectedDiv: function(conversationInfo, event){
this.$store.dispatch('getConversationByID', conversationInfo)
}
}
in my message component:
computed: {
...mapGetters([
"conversation"
]),
debugger
},
You can get similar functionality without using mapGetter, below is example.
computed: {
yourProperty(){
const profile = this.$store.getters.profile;
console.log('profile: ', profile); //Debug
return profile;
}
},
Another option is to put a watch on computed property.
computed: {
...mapGetters(["profile"]),
},
watch: {
profile: {
handler(profile) {
console.log('profile: ', profile); //Debug
},
deep: true
}
},
Here deep true option is used to watch on key updates of profile object. If deep true is not provided then watch will get called only when profile getter is reassigned with new object.
Related
I'm trying to use an action to call method with boolean value using the store
In the store app.js, i've defined :
export default {
namespaced: true,
state: () => {
return {
isScrollDisabled: true,
}
},
mutations: {
setScrollDisabled(state, value) {
state.isScrollDisabled = value
},
actions: {
setScrollDisabled(context, value) {
console.log('Action called in store')
context.commit('setScrollDisabled', value)
},
getters: {
getScrollDisabled: state => state.isScrollDisabled,
}
,
In the component, i dispatch the action like this :
this.$store.dispatch('app/setScrollDisabled', false) // with true or false
And in other component, i use the store getter to retrieve the value :
computed: {
isDisabled() {
return this.$store.getters.getScrollDisabled
},
I see nothing in the console and also in the VueJs Chrome extension, there are no event displayed
What i forgot here ?
More friendly and easy
computed: {
...mapGetters('app', [
'getScrollDisabled'
])
},
methods: {
...mapActions('app', [
'setScrollDisabled'
])
}
I have created a module to grab api data and hold it for a vue component:
import Vue from 'vue';
export default {
namespaced: true,
state() {
return {
all: []
}
},
getters: {
all(state) {
return state.all;
}
},
mutations: {
all(state, data) {
Vue.set(state, 'all', data);
},
clear(state) {
Vue.set(state, 'all', []);
}
},
actions: {
async init({ commit, state }) {
let response = await this.axios.get('/api/v1/teams/', {
params: {
includes: 'users'
}
});
if (response.status === 200) {
let data = response.data.data.filter(function (element) {
return element.users.length > 0;
});
commit('userTeamSelect/all', data, {root: true});
} else {
Vue.toasted.error('Could not fetch team data', {
duration: 10000
});
}
}
}
}
I have a component that is dynamically registering the module when it is created and removing the module from the store before it is deleted:
created() {
if (this.$store.getters['userTeamSelect/all'] === undefined) {
this.$store.registerModule('userTeamSelect', UserTeamSelectModule);
this.$store.dispatch('userTeamSelect/init');
}
},
beforeDestroy() {
if (this.$store.getters['userTeamSelect/all'] !== undefined) {
this.$store.commit('userTeamSelect/clear');
this.$store.unregisterModule('userTeamSelect');
}
},
When I navigate to a page where this component is used, I get the following error message in the console:
[vuex] unknown mutation type: userTeamSelect/all
This mutation is only called within the init action of the dynamic module, so the problem must be there somewhere. I have tried calling it both locally commit('all', data) and globally commit('userTeamSelect/all', data, {root:true}) with no luck.
The module must have been added to the vuex store because I can call the action without issue. It just seems the mutation isn't being registered somehow? I would expect it to work fine, or recieve an error about an unknown action.
Can anyone point me in the right direction please?
I am really having a hard time to solve this problem. Trying to make pagination by using vuex. But I can't update actions when I change the argument value.
For example to go to the next page, I tried a simple way
in component: home
<button #click="nextPage()">{{currentPage}}</button>
I send the argument to actions.
mounted(){
this.$store.dispatch('bridalApi', {currentPage})
},
data(){
return {
currentPage: 1,
};
},
methods: {
nextPage(){
this.currentPage++
}
},
in store.js
I take the argument that I commited.
actions: {
bridalApi({commit}, currentPage){
axios.get("api/bridal?page=" + currentPage)
.then(response => {
commit("setBridals", response.data);
})
.catch(e => {
console.log(e);
})
},
}
it's clearly I can't update the argument inside actions. Because when I click the button, it doesn't go to next page. I mean currentPage inside actions doesn't updated. This was the first way. So, I tried different approach to solve this problem which is like below.
in component: home
<button #click="nextPage()">{{pager}}</button>
I set/get the currentPage, and change the state.
methods: {
nextPage(){
this.pager++
}
},
computed: {
...mapGetters([
"getBridals",
]),
pager: {
set(val){
this.$store.commit("setPagination", val);
},
get(){
return this.$store.state.bridal.pagination.currentPage;
}
},
bridals() {
return this.getBridals;
},
},
in Store.js
state: {
bridals: [],
pagination: {
currentPage: 1,
},
},
mutations: {
setBridals(state, bridal){
state.bridals = bridal;
},
setPagination(state, pager){
state.pagination.currentPage = pager;
},
},
getters: {
getBridals(state){
return state.bridals
},
},
actions: {
bridalApi({commit,state}){
console.log(state.pagination.currentPage)
axios.get("api/bridal?page=" + state.pagination.currentPage)
.then(response => {
commit("setBridals", response.data);
})
.catch(e => {
console.log(e);
})
},
}
But this way is not working either. And I am very much out of ideas. How can I update the actions? What is the right way to use vuex for pagination?...
I am not sure is it's the right way to this. But solved it. Used the first way I mentioned in the question and update home component like below.
data(){
return {
currentPage: 1,
};
},
watch: {
currentPage() {
this.$store.dispatch("bridalApi", this.currentPage);
console.log("ok")
}
},
You can use a mutation for this like
state:{
data:[]
}
mutations:{
SET_DATA:(state , data) => {
return state.data = data
}
}
actions: {
dataApi({commit}, currentPage){
console.log(currentPage)
axios.get("http://website.com/api/endpoint?page="+currentPage)
.then(response => {
commit('SET_DATA' , response.data)
})
.catch(e => {
console.log(e);
})
}
}
I would recommend using LaravelVuePagination package for this.
That way you can have something like:
<pagination :data="bridals" #pagination-change-page="getBridals"></pagination>
export default {
name: 'BridlaList',
mounted() {
this.getBridals();
},
methods: {
getBridals(page = 1){
this.$store.dispatch('getBridals',{
page: page
});
},
}
I'm learning Vue and I've run into a problem where my data returns undefined from a computed method. It seems that the data is not computed by the time the component is mounted, probably due to the get request - wrapping my this.render() in a setTimeout returns the data correctly. Setting a timeout is clearly not sensible so how should I be doing this for best practice?
Home.vue
export default {
created() {
this.$store.dispatch('retrievePost')
},
computed: {
posts() {
return this.$store.getters.getPosts
}
},
methods: {
render() {
console.log(this.comments)
}
},
mounted() {
setTimeout(() => {
this.render()
}, 2000);
},
}
store.js
export const store = new Vuex.Store({
state: {
posts: []
},
getters: {
getPosts (state) {
return state.posts
}
},
mutations: {
retrievePosts (state, comments) {
state.posts = posts
}
},
actions: {
retrievePosts (context) {
axios.defaults.headers.common['Authorization'] = 'Bearer ' + context.state.token
axios.get('/posts')
.then(response => {
context.commit('retrievePosts', response.data)
})
.catch(error => {
console.log(error)
})
}
}
})
It is because axios request is still processing when Vue invokes mounted hook(these actions are independent of each other), so state.posts are undefined as expected.
If you want to do something when posts loaded use watch or better computed if it's possible:
export default {
created() {
this.$store.dispatch('retrievePost')
},
computed: {
posts() {
return this.$store.getters.getPosts
}
},
methods: {
render() {
console.log(this.comments)
}
},
watch: {
posts() { // or comments I dont see comments definition in vue object
this.render();
}
}
}
P.S. And don't use render word as methods name or something because Vue instance has render function and it can be a bit confusing.
I'm at my first app in Vuejs Vuex.
I can not find the best way to filter a state.
store/index.js
state: {
projects: []
},
mutations: {
SET_PROJECT_LIST: (state, { list }) => {
state.projects = list
}
},
actions: {
LOAD_PROJECT_LIST: function ({ commit }) {
axios.get('projects').then((response) => {
commit('SET_PROJECT_LIST', { list: response.data})
}, (err) => {
console.log(err)
})
}
}
in the component:
computed: {
...mapState({
projects
})
}
At this point I have a list of my projects. Good!
Now I added buttons to filter my projects like:
Active Project, Type Project ...
How do I manipulate my projects object (this.projects)?
With another one this.$store.dispatch
With another getters function
I manipulate the state without changing the status?
I'm a bit confused.
Some examples of filters on lists populated in Vuex?
EDIT:
I was trying that way:
this.$store.getters.activeProjects()
But how I update this.projects?
activeProjects(){
this.projects = this.$store.getters.activeProjects()
}
does not work
I'd recommend to keep your original state intact and filter its data by using "getters".
In fact, the official documentation includes an example of how to get all the "done" todos. It might be useful for you:
const store = new Vuex.Store({
state: {
todos: [
{ id: 1, text: '...', done: true },
{ id: 2, text: '...', done: false }
]
},
getters: {
doneTodos: state => {
return state.todos.filter(todo => todo.done)
}
}
})
Getters reference: https://vuex.vuejs.org/en/getters.html
Good luck!