How use a mutation function in a action function in Vuex? - javascript

I have this Vuex:
export default new Vuex.Store({
state: {
userInfo: {
nit_ID: { ID: '', Desc: '' },
userName: { ID: '', Desc: '' },
typeDocument: { ID: '', Desc: '' },
document: '',
},
globalPublicKey: 'ASDFGHJKL1234567890',
},
mutations: {
updateUserInfo(state, payload) {
state.userInfo = payload;
},
},
getters: {
userInfo: (state) => { return state.userInfo; },
},
actions: {
validateUserSession(context) {
var valido = false;
try {
let storageInfo = JSON.parse(
sjcl.decrypt(context.state.globalPublicKey, localStorage.userInfo)
);
if (localStorage.userToken === storageInfo.token) {
context.mutations.updateUserInfo(storageInfo);
valido = true;
}
} catch (e) {
console.error(e);
}
return valido;
},
},
})
But the problem is that I can't access to the mutation updateUserInfo(), I know that is easy to solved, only do the updateUserInfo process in my action, but the question is How can I use a mutation into a action?

In VueJS you can call a mutation from an action by calling context.commit, like this:
context.commit('mutationName', params)
params can be omitted if not parameters are passed to the mutation.
More on this here: vuex.vuejs.org/guide/actions.html
Actually you call a mutation from anywhere with a commit - but it's advised to use actions (so dispatch an action) that in turn commits the data (actually mutates the state).

Related

How do i get the props passed from a router.push params in vue 3?

Guys I am trying to get a prop value in my component sent through a router.push after an axios request but when i print the 'abaInicial' passed as a prop, it is returning as NaN. I don't know what i am doing wrong, someone help.
I would like someone who might help me out because i think Vue-router rules might have changed because this used to work and all of a sudden it stopped.
My parent component looks like this from the method.
methods: {
etapaEscolhida(etapa_id) {
var formData = new FormData();
formData.append("paciente", this.pacienteId);
formData.append("etapa", etapa_id);
formData.append("status", "EXECUTANDO");
formData.append("data_atendimento", new Date());
formData.append("csrfmiddlewaretoken", document.cookie.split(/;|=/)[1]);
this.axios.post("/preenchimento/", formData).then((response) => {
if (response.status === 200) {
this.$router.push({
name: "Coletas",
params: { abaInicial: response.data.id },
});
}
console.log(response.data.id)
});
},
},
My router.js file
const atendimentoRouter = [
{
path: '/coletas/',
name:'Coletas',
components: {
default: Home,
content: Coletas
},
props: {
default: Home,
content: route => ({
abaInicial: parseInt(route.params.abaInicial)
})
}
}
]
my child component/ The component where i need the props
props:{
abaInicial: Number,
},
data() {
return {
abaSelecionada: 0,
};
},
async created(){
await this.$store.dispatch("getAtendimentosAbertos");
this.$store.dispatch("getFormatosFormularios");
this.$store.dispatch("getFormatosPerguntas");
if(this.abaInicial && !isNaN(this.abaInicial)){
this.abaSelecionada = this.abaInicial
} else if(this.atendimentos.length){
this.abaSelecionada = this.atendimentos[0].id
}
},

Vuex getter method returns undefined

I am trying to call a getter method and it's not getting called for some reason. If I console.log the store I can see that it's undefined:
This is where I'm calling the getter method:
computed: {
client() {
console.log(this.$store); //see above screenshot
console.log(this.$route.params.id); //shows a valid value.
//nothing seems to happen after this point, console.log in the below getter doesn't happen.
return this.$store.getters['clients/clientById', this.$route.params.id];
}
},
here's my getter in clients.js module:
getters: {
clients(state) {
return state.clients;
},
hasClients(state) {
return state.clients.length > 0;
},
clientById(state, id) {
console.log('test'); //this doesn't happen
return state.clients.find(client => client.id === id);
}
}
The first 2 getter methods are working fine, using the same syntax as what I'm doing when I'm calling the clientById getter.
What I'm trying to accomplish is to have an array of client objects, and then when a user clicks on a client in the client list, I grab the ID out of the route params and the appropriate client data is displayed on the page. I'd appreciate any guidance on whether I'm approaching this in the right way as well as I'm new to Vue.
state() {
return {
clients: [
{
id: null,
client_name: '',
address: '',
city: '',
state: '',
zip:'',
created_at: '',
updated_at: '',
deleted_at: null
},
]
};
},
UPDATE:
I'll provide my entire clients.js module in case something is off with that. Everything else seems to be working fine, so not sure if this is related or not. This is an updated version of the getter where I changed it to an arrow function based on your feedback. When I do this, I get another error: TypeError: 'caller', 'callee', and 'arguments' properties may not be accessed on strict mode functions or the arguments objects for calls to them at Function.
I've also tried hard-coding the ID within the getter method and taking it out of the passed-in ID parameter, and that seems to work, but is returning undefined, so it's still not getting a value from state.
import axios from "axios";
export default {
namespaced: true,
state() {
return {
isLoading: false,
clients: [
{
id: null,
client_name: '',
address: '',
city: '',
state: '',
zip:'',
created_at: '',
updated_at: '',
deleted_at: null
},
]
};
},
mutations: {
setLoadingStatus(state, status) {
state.isLoading = status;
},
setClients(state, clients) {
state.clients = clients;
}
},
actions: {
async fetchClients(context) {
context.commit('setLoadingStatus', true);
try {
const resp = await axios.get('http://localhost/api/clients');
context.commit('setLoadingStatus', false);
context.commit('setClients', resp.data);
} catch(e) {
console.log(e);
}
}
},
getters: {
clients(state) {
return state.clients;
},
hasClients(state) {
return state.clients.length > 0;
},
clientById: (state) => (id) => {
return state.clients.find(client => client.id === id);
}
}
};

Vuex getters has undefined data when I try to load data from API and use it in multiple components

I have a page component where I am making api call and storing the data in Vuex store through actions. This data has to be used at multiple places but everywhere I'm initially getting undefined data which loads after a few seconds asynchronously from the API. How should I use vuex getters asynchronously ?
Here's the code for my vuex store module :
import axios from 'axios';
const state = {
all_pokemon: {},
pokemon_details: {}
};
const getters = {
getAllPokemon: function(state) {
return state.all_pokemon;
},
getPokemonDetails: function(state) {
return state.pokemon_details;
}
};
const mutations = {
setAllPokemon: function(state, payload) {
return state.all_pokemon = payload;
},
setPokemon: function(state, payload) {
console.log('Pokemon details set with payload ', payload);
return state.pokemon_details = payload;
}
};
const actions = {
setPokemonAction: function({ commit }, passed_pokemon) {
axios.get('https://pokeapi.co/api/v2/pokemon/' + passed_pokemon)
.then((response) => {
console.log('Response data is : ', response.data);
});
commit('setAllPokemon', response.data);
},
setPokemonDetailAction: function({ commit }, passed_pokemon) {
console.log('Action method called..', passed_pokemon);
axios.get('https://pokeapi.co/api/v2/pokemon/' + passed_pokemon)
.then((response) => {
commit('setPokemon', response.data);
});
}
};
export default {
state,
getters,
mutations,
actions,
};
And code for the component where I want to get this data and pass it to other components :
<script>
import { mapGetters, mapActions } from 'vuex'
import axios from 'axios'
// Imported other components here
export default {
name: 'pokemon_detail_page',
data() {
return {
current_pokemon: this.$route.params.pokemon,
isLoading: false,
childDataLoaded: false,
search_pokemon: '',
sprites: [],
childData: 'False',
isAdded: false,
pokemon_added: 'none_display',
show: false
}
},
methods: {
...mapActions([
'setPokemonDetailAction',
'removePokemon'
]),
},
computed: {
...mapGetters([
'getPokemonDetails',
'getTeam'
])
},
components: {
Game_index,
PulseLoader,
PokemonComponent,
},
filters: {
},
watch: {
getTeam: function (val) {
},
getPokemonDetails: function(val) {
}
},
created() {
setTimeout(() => {
this.show = true;
}, 2000);
this.$store.dispatch('setPokemonDetailAction', this.current_pokemon)
.then(() => {
// const { abilities, name, order, species, } = {...this.getPokemonDetails};
})
},
mounted() {
},
}
</script>
And here's is the code for the template where I'm passing this data to multiple components :
<div v-if="show" class="pokemon_stats_container" :key="childData">
<ability-component
:abilities="getPokemonDetails.abilities"
>
</ability-component>
<sprites-component
:sprites="sprites"
>
</sprites-component>
<location-component
:location_area="getPokemonDetails.location_area_encounters"
:id="getPokemonDetails.id"
>
</location-component>
<stats-component
:stats="getPokemonDetails.stats"
>
</stats-component>
<game_index
:game_indices="getPokemonDetails.game_indices"
/>
<moves-component
:moves="getPokemonDetails.moves"
:pokemon_name="getPokemonDetails.name"
>
</moves-component>
</div>
As of now, I've adopted a roundabout way of doing this through setTimeout and setting a variable after 2 seconds so that data is available for other components to use. But, there has to be a more elegant way of handling vuex asynchronous data. Someone please help me in this.
Your first commit is not in the promise
commit('setAllPokemon', response.data);
make this :
axios.get('https://pokeapi.co/api/v2/pokemon/' + passed_pokemon)
.then((response) => {
console.log('Response data is : ', response.data);
commit('setAllPokemon', response.data);
});
try to use in your vue component
$forceUpdate()
when your request is end for reload the data

How to access data from a component in a method

Hallo I am stuck with the following:
I am working on a Vue application that consists of multiple component. Now i have a component that uses vee-validate. Only for a custom validation I want change a data element in the component data() object. Only if I try this the following Exception pops up: cannot set property 'kenteken' of undefined
The code is as follow:
<script>
import {Validator} from 'vee-validate';
import nl from 'vee-validate/dist/locale/nl';
const isKenteken = (value) =>{
app.loader.kenteken= true;
return axios.post('/api/validate/kenteken', {kenteken: value}).then((response) => {
// Notice that we return an object containing both a valid property and a data property.
app.loader.kenteken = false;
app.voertuig.merk = response.data.Algemeen.Merk;
app.voertuig.model = response.data.Algemeen.Type;
app.voertuig.brandstof = response.data.Algemeen.Brandstof.toLowerCase();
app.voertuig.type_id = response.data.Algemeen.TypeId;
app.voertuig.model_id = response.data.Algemeen.ModelId;
app.voertuig.merk_id = response.data.Algemeen.MerkId;
console.log(response.data.Algemeen);
return {
valid: true,
data: {
message: response.data.Algemeen,
}
};
}, (error) => {
console.log(error);
app.voertuig.kenteken = '';
app.loader.kenteken_onbekend = 1;
app.loader.kenteken = false;
return false;
});
};
Validator.localize('nl', nl);
Validator.extend('kenteken', {
validate:isKenteken,
getMessage: (field, params, data) => {
loader.kenteken = false;
voertuig.merk = data.message.Merk;
}
});
export default {
name: "app",
data() {
return {
voertuig: {
kenteken: '',
model: '',
model_id: '',
type: '',
type_id: '',
merk: '',
merk_id: '',
brandstof: '',
schadevrijejaren: ''
},
bestuurder: {
geboortedatum: '',
postcode: '',
huisnummer: '',
straat: '',
woonplaats: ''
},
loader: {
kenteken_onbekend: false,
kenteken: false,
},
}
},
mounted() {
var self = this;
}
}
</script>
So how to access the load.kenteken in the isKenteken function?
You shouldn't create function that will reference to Vue component outside Vue application scope. Instead, You should place the isKenteken() function inside Vue component as following
<script>
import {Validator} from 'vee-validate';
import nl from 'vee-validate/dist/locale/nl';
Validator.localize('nl', nl);
Validator.extend('kenteken', {
validate:isKenteken,
getMessage: (field, params, data) => {
loader.kenteken = false;
voertuig.merk = data.message.Merk;
}
});
export default {
name: "app",
data() {
return {
voertuig: {
kenteken: '',
model: '',
model_id: '',
type: '',
type_id: '',
merk: '',
merk_id: '',
brandstof: '',
schadevrijejaren: ''
},
bestuurder: {
geboortedatum: '',
postcode: '',
huisnummer: '',
straat: '',
woonplaats: ''
},
loader: {
kenteken_onbekend: false,
kenteken: false,
},
}
},
methods{
isKenteken(value){
this.loader.kenteken= true;
return axios.post('/api/validate/kenteken', {kenteken: value}).then((response) => {
// Notice that we return an object containing both a valid property and a data property.
this.loader.kenteken = false;
this.voertuig.merk = response.data.Algemeen.Merk;
this.voertuig.model = response.data.Algemeen.Type;
this.voertuig.brandstof = response.data.Algemeen.Brandstof.toLowerCase();
this.voertuig.type_id = response.data.Algemeen.TypeId;
this.voertuig.model_id = response.data.Algemeen.ModelId;
this.voertuig.merk_id = response.data.Algemeen.MerkId;
console.log(response.data.Algemeen);
return {
valid: true,
data: {
message: response.data.Algemeen,
}
};
}, (error) => {
console.log(error);
this.voertuig.kenteken = '';
this.loader.kenteken_onbekend = 1;
this.loader.kenteken = false;
return false;
});
}
},
mounted() {
var self = this;
}
}
</script>
If you need to use the function from other component. You will need to find a way to make them reference to this component in order to use this methods. For example, inside other component's mounted(), you can use the root component methods by this.$root.isKenteken()

Vue.js: mutation for deleting a comment

I have been working on the feature of comment deleting and came across a question regarding a mutation for an action.
Here is my client:
delete_post_comment({post_id, comment_id} = {}) {
// DELETE /api/posts/:post_id/comments/:id
return this._delete_request({
path: document.apiBasicUrl + '/posts/' + post_id + '/comments/' + comment_id,
});
}
Here is my store:
import Client from '../client/client';
import ClientAlert from '../client/client_alert';
import S_Helper from '../helpers/store_helper';
const state = {
comment: {
id: 0,
body: '',
deleted: false,
},
comments: [],
};
const actions = {
deletePostComment({ params }) {
// DELETE /api/posts/:post_id/comments/:id
document.client
.delete_post_comment({ params })
.then(ca => {
S_Helper.cmt_data(ca, 'delete_comment', this);
})
.catch(error => {
ClientAlert.std_fail_with_err(error);
});
},
};
delete_comment(context, id) {
context.comment = comment.map(comment => {
if (!!comment.id && comment.id === id) {
comment.deleted = true;
comment.body = '';
}
});
},
};
export default {
state,
actions,
mutations,
getters,
};
I am not quite sure if I wrote my mutation correctly. So far, when I am calling the action via on-click inside the component, nothing is happening.
Guessing you are using vuex the flow should be:
according to this flow, on the component template
#click="buttonAction(someParams)"
vm instance, methods object:
buttonAction(someParams) {
this.$store.dispatch('triggerActionMethod', { 'something_else': someParams })
}
vuex actions - Use actions for the logic, ajax call ecc.
triggerActionMethod: ({commit}, params) => {
commit('SOME_TRANSATION_NAME', params)
}
vuex mutations - Use mutation to make the changes into your state
'SOME_TRANSATION_NAME' (state, data) { state.SOME_ARG = data }

Categories

Resources