How to pass values from state in vuex post request - vue.js

I am collecting data using get and set for my form. I want to post the states to the api.
How can I move the states or group them somehow so I can pass them as to action?
state: {
firstname: "",
lastname: "",
},
mutations: {
setFirstName(state, value) {
state.firstname = value
},
setLastName(state, value) {
state.lastname = value
},
So it looks like this:
sendInfo({commit}, object) {
axios.post('API_URL', object)
.then((response) => {
...
})
}
computed: {
firstname: {
get() {
return this.$store.state.firstname
},
set(value) {
this.$store.commit("setFirstName", value)
}
},
or am I approaching this wrongly?

It's probably best to put these values inside a state object like:
state: {
user: {
firstname: '',
lastname: ''
}
}
You can set the object in an action
actions: {
setData({ commit }, payload) {
commit('SET_DATA', payload);
}
},
mutations: {
SET_DATA(state, payload) {
state.user = payload;
}
}
It also makes it concise when using mapState:
computed: {
...mapState(['user'])
}

Related

About Vue. How to encapsulate Axios to reduce request code redundancy

Now I'm writing a project using Vue.I used a lot of Axios requests,
How to encapsulate the request code to reduce redundancy.
getProvinces() {
this.axios
.get(this.gv.serverUrl + "/location/province/list")
.then((res) => {
this.location.province.provinces = res.data.data;
});
},
getCities() {
this.axios
.get(this.gv.serverUrl + "/location/city/list", {
params: {
pid: this.location.province.province,
},
})
.then((res) => {
this.location.city.cities = res.data.data;
});
},
getCountries() {
this.axios
.get(this.gv.serverUrl + "/location/country/list", {
params: {
cid: this.location.city.city,
},
})
.then((res) => {
this.location.country.countries = res.data.data;
});
},
Use Axios.all to do concurrent requests. That will help you to encapsulate status of all requests.
Not exactly but something like this given below:
let endpoints = [
'https://this.gv.serverUrl + "/location/province/list"',
'https://this.gv.serverUrl + "/location/city/list"',
'https://api.github.com/users/ejirocodes/followers',
'https://api.github.com/users/ejirocodes/following'
];
axios.all(endpoints.map((endpoint) => axios.get(endpoint))).then(
(data) => console.log(data),
)
Here is the link for more help and good explanation: https://blog.logrocket.com/using-axios-all-make-concurrent-requests/
You could create a method that makes the axios call, passing the path and the params (as an optional argument). So a method that could work for the code you are providing could be:
fetch(resource, params) {
return this.axios.get(this.gv.serverUrl + `/location/${resource}/list`, { params })
This fetch method would return a promise, and your methods would look like this:
getProvinces() {
this.fetch("/location/province/list")
.then((res) => {
this.location.province.provinces = res.data.data;
});
},
getCities() {
this.fetch("/location/city/list", { pid: this.location.province.province })
.then((res) => {
this.location.city.cities = res.data.data;
});
},
getCountries() {
this.fetch("/location/country/list", { cid: this.location.city.city})
.then((res) => {
this.location.country.countries = res.data.data;
});
},
A further refactor could be conducted if there was some kind of uniformity in the data property of the Vue instance.
I cannot see the shape of your data property, but from what I see it looks something like this:
data() {
return {
location: {
province: {
provinces: [...],
},
city: {
cities: [...],
},
country: {
countries: [...],
},
}
}
}
If you could change it to something like this:
data() {
return {
location: {
province: {
list: [...],
},
city: {
list: [...],
},
country: {
list: [...],
},
}
}
Then the refactor of the methods could be this:
fetch(resource, params) {
return this.axios
.get(this.gv.serverUrl + `/location/${resource}/list`, { params })
.then((res) => {
this.location[resource].list = res.data.data;
})
getProvinces() {
this.fetch("/location/province/list")
},
getCities() {
this.fetch("/location/city/list", { pid: this.location.province.province })
},
getCountries() {
this.fetch("/location/country/list", { cid: this.location.city.city})
},

Vue Apollo subscription not updating the query

It's my first time implementing a GraphQL subscription, so excuse me if it's an obvious question.
I have a subscription which is working with Simple Subscription approach, but doesn't work with SubscribeToMore Here are both calls.
Simple Subscription:
$subscribe: {
onTransactionChanged: {
query: ON_TRANSACTION_CHANGED,
variables() {
return {
profileId: this.profile.profileId,
};
},
skip() {
return !this.profile?.profileId;
},
result({ data }: any) {
console.log(data.onTransactionChanged);
},
},
},
In this case, I see a new transaction in the console.
SubscribeToMore:
cartProducts: {
query: GET_CART_PRODUCTS,
loadingKey: "loading",
subscribeToMore: {
document: ON_TRANSACTION_CHANGED,
},
updateQuery: (previousResult: any, { subscriptionData }: any) => {
console.log("previousResult:", previousResult);
console.log("subscriptionData:", subscriptionData);
},
variables() {
return {
profileId: this.profile.profileId,
};
},
skip() {
return !this.profile?.profileId;
},
}
In this case, there is nothing in the console.
What am I doing wrong? Thank you in advance.
I just missed the curly braces scope. It's working
cartProducts: {
query: GET_CART_PRODUCTS,
loadingKey: "loading",
subscribeToMore: {
document: ON_TRANSACTION_CHANGED,
updateQuery(previousResult: any, { subscriptionData }: any) {
console.log("previousResult:", previousResult);
},
variables() {
return {
profileId: this.profile.profileId,
};
},
skip() {
return !this.profile?.profileId;
},
}
}

Get params of route Shopware 6

I try to extend the product detail page and get the productId out of the routes.
Shopware.Module.register('sw-product-content-element', {
routeMiddleware(next, currentRoute) {
if (currentRoute.name === 'sw.product.detail') {
currentRoute.children.push({
name: 'sw.product.detail.content-element',
path: '/sw/product/detail/:id/content-element',
component: 'sw-product-detail-content-element',
meta: {
parentPath: "sw.product.index"
},
props: {
default(route) {
console.log(route)
return {
productId: route.params.id
};
}
}
});
}
next(currentRoute);
}
});
I try to pass my productId as props to my component, but in my component productId is undefined.
Component.register('sw-product-detail-content-element', {
template,
props: {
productId: {
required: true,
type: String
},
},
data() {
return {
product: null
};
},
created() {
console.log(this.productId)
},
....
I found a solution. I do not need to pass my value as props, I can just use this.$route.params.id
Component.register('sw-product-detail-content-element', {
template,
props: {
productId: {
required: true,
type: String
},
},
data() {
return {
product: null
};
},
created() {
this.productId = this.$route.params.id
console.log(this.productId)
},
....

Getter undefined vuex and axios

I’m trying to get a getter in my component but it says an error. This is my code store.js
const store = new Vuex.Store({
state: {
config:{
themes: [],
typographies:[],
},
user: {
typography_id: 1,
theme_id: null
}
},
mutations: {
FETCH_CONFIG(state, config) {
state.config.themes = config.themes;
state.config.typographies = config.typographies;
},
FETCH_USER(state, user) {
state.user.theme_id = user.theme_id;
state.user.typography_id = user.typography_id;
},
},
actions: {
fetchConfig({commit}) {
axios.get('/api/config').then( function( response ){
commit('FETCH_CONFIG', response.data);
});
},
fetchUser({commit}) {
axios.get('/api/user').then( function( response ){
commit('FETCH_USER', response.data.data[0]);
});
},
},
getters: {
themes(state) {
return state.config.themes;
},
typographies(state) {
return state.config.typographies;
},
typography(state) {
if (state.user.theme_id == 1) {
return state.user.typography_id;
} else {
var theme = state.config.themes.filter(function (el) {
return el.id == state.user.theme_id;
});
return theme[0].typography_id;
}
},
user_theme(state) {
return state.user.theme_id;
},
}
});
And in my component in computed I have:
...mapGetters(['typographies', 'typography'])
And ths is the error I get:
I guess I’m doing something wrong but I don’t know what.
Your getter for typography returns the error because first it goes into the else and then tries to return theme[0].typography_id - but there is an empty array.. if you are loading the date, later on, make sure that the getter returns null before data is loaded.. like:
const store = new Vuex.Store({
state: {
config:{
themes: [],
typographies:[],
},
user: {
typography_id: 1,
theme_id: null
}
},
mutations: {
FETCH_CONFIG(state, config) {
state.config.themes = config.themes;
state.config.typographies = config.typographies;
},
FETCH_USER(state, user) {
state.user.theme_id = user.theme_id;
state.user.typography_id = user.typography_id;
},
},
actions: {
fetchConfig({commit}) {
axios.get('/api/config').then( function( response ){
commit('FETCH_CONFIG', response.data);
});
},
fetchUser({commit}) {
axios.get('/api/user').then( function( response ){
commit('FETCH_USER', response.data.data[0]);
});
},
},
getters: {
themes(state) {
return state.config.themes;
},
typographies(state) {
return state.config.typographies;
},
typography(state) {
if (state.user.theme_id == 1) {
return state.user.typography_id;
} else {
var theme = state.config.themes.filter(function (el) {
return el.id == state.user.theme_id;
});
return theme.length > 0 ? theme[0].typography_id: 1;
}
},
user_theme(state) {
return state.user.theme_id;
},
}
});

Vue vuex state watch is not working on first load

I have below code to get new ID using watch. Its working fine. However, I need the function to get the ID on first load as well, which is not working. Is there anything I am missing in my code?
watch: {
id: {
immediate: true,
handler(newV, oldV) {
this.id = newV;
},
},
},
mounted () {
store.watch(store.getters.getId, id => {
this.id = id;
});
},
created() {
this.userID();
},
methods: {
userID () {
console.log('this.id);
}
}
}
You can just do this:
data() {
return {id: null}
}
watch: {
'$store.getters.getId': {
immediate: true,
handler: function(newV) {
this.id = newV
},
},
}
Using a computed property is better, as your component does not 'own the id'.
computed: {
id() {
return this.$store.getters.getId
},
},