How to invoke component method from store.js - vue.js

I have Login.vue component which has method postData()
postData() {
this.$store.dispatch('doLogin', fdata)
},
doLogin is in store.js
actions: {
doLogin({ commit }, loginData) {
commit('loginStart');
axios.post(this.state.apiURL+'/login', {
...loginData
})
.then(response => {
commit('loginStop', null);
commit('updateAccessToken', response.data.access_token);
})
.catch(error => {
commit('loginStop', error);
})
},
how to invoke back from router.js a method in other component, let say again from Login.vue?
I want in general invoke Toast which is bootstrap thing in Login.vue methods.
Any idea?

Login.vue component method
this.$store.dispatch('doLogin', fdata).then(response => {
console.log("response from promise:",response)
}, error => {
this.makeToast(true, error, 'danger', 'b-toaster-top-center')
console.error("Got error:",error)
})
store.js Actions
doLogin({ commit }, loginData) {
return new Promise((resolve, reject) => {
console.log("store - doLogin", loginData)
commit('loginStart');
axios.post(this.state.apiURL+'/login', {
...loginData
})
.then(response => {
localStorage.setItem('accessToken', response.data.access_token);
commit('loginStop', null);
commit('updateAccessToken', response.data.access_token);
router.push('/profile');
resolve(response);
})
.catch(error => {
console.log('error', error)
commit('loginStop', error);
commit('updateAccessToken', null);
reject(error)
})
})
},

Related

How make Axios "finally" waiting until "then" is finished?

I'm trying to the finally be executed after the method getCharacters is finished, but without success.
He always is executed before.
There is a way to make him be executed after everything in the then is finished?
I suspect that the problem is the axios inside the getCharacters method.
new Vue({
el: '#app',
data () {
return {
message: '',
}
},
methods: {
getCharacters() {
axios
.get('/api/messages/characters')
.then(response => {
console.log('finish get')
})
},
submitForm: function (event) {
axios
.post('/api/messages/send', {
message: this.message
})
.then(response => {
this.getCharacters()
})
.finally(() => {
console.log('finish post')
})
}
}
})
You have to return the result of getCharacters:
.then(response => {
return this.getCharacters()
})
or
.then(response =>
this.getCharacters()
)

use a function in action of auth modules in wizard module in vuex in vue

I have this function in auth.module.js:
async [VERIFY_AUTH](context) {
if (JwtService.getToken()) {
ApiService.setTokenAxios();
return (
ApiService.get("api/customer/me")
.then(({ data }) => {
console.log("auth request - useer:", data);
context.commit(SET_AUTH, data);
})
///////////
.catch(({ response }) => {
console.log(response);
context.commit(SET_ERROR, serviceErrors(response.data));
})
);
} else {
context.commit(PURGE_AUTH);
}
},
I want dispatch it in wizard.modules.js
[SPOUSES](context, data) {
console.log(data);
return new Promise(() => {
ApiService.post(`api/customer/${data.id}/spouses`, data.form).then(
({ data }) => {
console.log(data);
context.dispatch("auth/VERIFY_AUTH", null, { root: true });
}
);
});
},
I try it but it dont work
do you know what should I do?

Asynchronous VuexFire Data Fetch With Then/Catch

Given the following functioning vuex action named init that fetches a settings and an accounts collection:
actions: {
init: firestoreAction(({ bindFirestoreRef, commit }, payload) => {
bindFirestoreRef(
'settings', fb.settings.doc(payload),
)
.then(() => commit('SETTINGS_READY', true))
.catch((err) => {
commit('SNACKBAR_TEXT', err.message);
Sentry.captureException(err);
});
bindFirestoreRef(
'accounts', fb.accounts.where('program', '==', payload),
)
.then(() => commit('ACCOUNTS_READY', true))
.catch((err) => {
commit('SNACKBAR_TEXT', err.message);
Sentry.captureException(err);
});
}),
},
I have two questions:
The code appears to run synchronously, but I want the two collections to be fetched asynchronously to maximize performance. How can that be achieved?
Is it possible to refactor this code to be more concise and yet provide for the independent (and synchronous) then/catch functionality present in the example?
You can use async / await function then call the bindFirestoreRef inside Promise constructor.
actions: {
init: firestoreAction(async ({ bindFirestoreRef, commit }, payload) => {
await Promise((resolve, reject) => {
bindFirestoreRef('settings', fb.settings.doc(payload))
.then((res) => {
commit('SETTINGS_READY', true);
resolve(res);
})
.catch((err) => {
commit('SNACKBAR_TEXT', err.message)
Sentry.captureException(err)
reject(err)
})
})
await new Promise((resolve, reject) => {
bindFirestoreRef('accounts', fb.accounts.where('program', '==', payload))
.then((res) => {
commit('ACCOUNTS_READY', true);
resolve(res);
})
.catch((err) => {
commit('SNACKBAR_TEXT', err.message)
Sentry.captureException(err)
reject(err)
})
})
})
},

Vue - call async action only after first one has finished

I need to call 2 actions from inside my component, but the second should only start after the first one has 100% finished it's job.
I'm trying this but it doesn't work
mounted() {
this.$store.dispatch('coinModule/loadApiCoins')
.then(() => {
this.$store.dispatch('coinModule/loadUserCoins')
})
.catch(error => {
console.log(error)
});
},
and the 2 actions are these
loadApiCoins({ commit, dispatch, rootGetters }) {
Vue.axios({
method: 'get',
url: 'https://api.coinmarketcap.com/v1/ticker/',
transformRequest: [(data, headers) => {
delete headers.common.Authorization
return data
}]
})
.then(response => { commit('SET_API_COINS', response.data) })
.catch(error => { console.log(error) })
},
loadUserCoins({ commit, dispatch, rootGetters }) {
Vue.axios.get('http://127.0.0.1:8000/api/coins/')
.then(response => {
commit('SET_USER_COINS', response.data)
commit('SET_USER_PORTFOLIO_OVERVIEW')
})
.catch(error => { console.log(error) })
}
These should be the other way around.
Screen of my network tab
When you dispatch an action, it doesn't have a then callback by default. That's only the case if the action returns a Promise. Your axios.get call should return a Promise, but you aren't returning it in your action. You should simply return it and then then callback will fire in your mounted hook.
loadApiCoins({ commit, dispatch, rootGetters }) {
return Vue.axios({
method: 'get',
url: 'https://api.coinmarketcap.com/v1/ticker/',
transformRequest: [(data, headers) => {
delete headers.common.Authorization
return data
}]
})
.then(response => { commit('SET_API_COINS', response.data) })
.catch(error => { console.log(error) })
},

VueJs. How to close pre-loader after data from server have been loaded

I use VueX in my VueJs app and I need to close pre-loader after I got an answer from server for 4 my get requests. I try to use callback function to change pre-loader state but it changes after requests STARTs, but I need to change pre-loader state after all requests SUCCESS. Below is my code:
Index.vue
<template>
<div class="index">
<div class="content-is-loading"
v-if="appIsLoading"></div>
<div v-else class="index__wrapper">
<navbarInner></navbarInner>
<div class="index__content">
<sidebar></sidebar>
<router-view></router-view>
</div>
<foo></foo>
</div>
</div>
</template>
<script>
import NavbarInner from './NavbarInner'
import Sidebar from './Sidebar'
import Foo from './../Foo'
import Shows from './Shows/Shows'
import Dashboard from './Dashboard'
import { API_URL } from '../../../config/constants'
import { mapState } from 'vuex'
export default {
name: 'index',
data () {
return {
appIsLoading: true,
bandName: ''
}
},
components: {
NavbarInner,
Sidebar,
Foo,
Shows,
Dashboard
},
created () {
function loadData (context, callback) {
// Loading bands for the user
context.$store.dispatch('getBands')
// Loading contacts for the user
context.$store.dispatch('getContacts')
// Loading merch for the user
context.$store.dispatch('getInventory')
// Loading tours for the active band
context.$store.dispatch('getToursList')
callback(context)
}
loadData(this, function (context) {
context.appIsLoading = false
})
}
}
Below I add code of one of the request:
api/tour.js
import axios from 'axios'
import { API_URL } from '../../config/constants'
export default {
getToursList () {
return new Promise((resolve, reject) => {
let bandId = window.localStorage.getItem('active_band_id')
let token = window.localStorage.getItem('token')
axios.get(API_URL + '/api/bands/' + bandId + '/tours/', {
headers: {'x-access-token': token}
})
.then((result) => {
return resolve(result.data)
})
.catch(err => reject(err))
})
},
getInventory () {
return new Promise((resolve, reject) => {
let token = window.localStorage.getItem('token')
axios.get(API_URL + '/api/merch/listProductForUser/1000/0', {
headers: {'x-access-token': token}
})
.then((response) => {
let items = response.data
return resolve(items)
})
.catch((err) => {
return reject(err)
})
})
},
getContacts () {
return new Promise((resolve, reject) => {
let token = window.localStorage.getItem('token')
axios.get(API_URL + '/api/contact/get_contacts_for_user/1000/0', {
headers: {'x-access-token': token}
})
.then((response) => {
console.log(response.data)
let contacts = response.data
return resolve(contacts)
})
.catch((err) => {
return reject(err)
})
})
},
getBands () {
return new Promise((resolve, reject) => {
let token = window.localStorage.getItem('token')
axios.get(API_URL + '/api/band/getBandsForUser/1000/0', {
headers: {'x-access-token': token}
})
.then((response) => {
console.log(response.data)
let bands = response.data
return resolve(bands)
})
.catch((err) => {
return reject(err)
})
})
}
}
Vuex/tour.js
import api from '../../api/onload'
import * as types from '../mutation-types'
const state = {
tours: [],
contacts: [],
bands: [],
merch: [],
success: false,
loading: false
}
const actions = {
getToursList ({commit}) {
api.getToursList()
.then((tours) => {
commit(types.RECEIVE_TOURS, tours)
}).catch((err) => {
console.error('Error receiving tours: ', err)
commit(types.RECEIVE_TOURS_ERROR)
})
},
getInventory ({commit}) {
api.getInventory()
.then((items) => {
commit(types.RECEIVE_INVENTORY, items)
})
.catch((err) => {
console.error('Error receiving inventory: ', err)
commit(types.RECEIVE_INVENTORY_ERROR)
})
},
getBands ({commit}) {
api.getBands()
.then((bands) => {
commit(types.RECEIVE_BANDS, bands)
})
.catch((err) => {
console.error('Error receiving bands: ', err)
commit(types.RECEIVE_BANDS_ERROR)
})
},
getContacts ({commit}) {
api.getContacts()
.then((contacts) => {
commit(types.RECEIVE_CONTACTS, contacts)
})
.catch((err) => {
console.error('Error receiving bands: ', err)
commit(types.RECEIVE_CONTACTS_ERROR)
})
}
}
const mutations = {
[types.RECEIVE_TOURS] (state, tours) {
state.tours = tours
},
[types.RECEIVE_INVENTORY] (state, items) {
state.items = items
},
[types.RECEIVE_BANDS] (state, bands) {
state.bands = bands
},
[types.RECEIVE_CONTACTS] (state, contacts) {
state.contacts = contacts
console.log(state.contacts)
}
}
export default {
state, mutations, actions
}
How should I change the code?
The code you posted doesn't actually wait on the response from any of the actions you are calling.
You could also move everything to a method and refactor.
Finally I've assumed your actions return a Promise i.e.
created () {
this.getAll()
},
methods: {
getAll () {
Promise.all([
this.$store.dispatch('getBands'),
this.$store.dispatch('getContacts'),
this.$store.dispatch('getInventory'),
this.$store.dispatch('getToursList'),
])
.then(responseArray => {
this.appIsLoading = false
})
.catch(error => { console.error(error) })
EDIT
To get your actions to resolve as you need them (when the mutations have fired and your store is updated) you need to wrap them in a Promise:
Vuex/tour.js (actions object)
getToursList: ({ commit }) =>
new Promise((resolve, reject) => {
api.getToursList()
.then((tours) => {
commit(types.RECEIVE_TOURS, tours)
resolve()
}).catch((err) => {
console.error('Error receiving tours: ', err)
commit(types.RECEIVE_TOURS_ERROR)
reject()
})
})