Passing an error to a component - vue.js

I have an AddComment.vue component which has a form, on submit it hits a laravel api endpoint where validation happens. If validation fails I want to show the errors in AddComment.vue. How can return the error.response object to AddComment.vue? Currently, I can see 'fired' in the console when I want to be logging the error. Where am I going wrong any help would be greatly appreciated
AddComponent.vue
methods: {
addComment() {
this.$store.dispatch('addComment', {
name: this.name,
email: this.email,
body: this.body
})
.then(response => {
this.$router.push({ name: 'home' })
console.log('fired')
})
.catch(error => {
console.log(error)
})
},
}
store.js
actions: {
addComment(context, comment) {
new Promise((resolve, reject) => {
axios.post('/comments', {
name: comment.name,
email: comment.email,
body: comment.body,
approved: false
})
.then(response => {
context.commit('addComment', response.data)
resolve(response)
})
.catch(error => {
reject(error)
})
});
},
}

The catch() block only gets called if the Laravel backend throws an error. So if you are returning a normal status code of 2xx then axios always calls the .then() part. In that case, you have to resolve the error message yourself.
Try something like this in your backend route (it will return an error):
return response()->toJson([
'message' => 'error message',
], 500);
And see if this responds with an actual error in you vuejs application.

Related

How to redirect in Nuxt's asyncData

I'm new to the vue.js and I have a simple question.
I have a code like below:
asyncData({ params, error }) {
return Job.api()
.fetchByID(params.id)
.then((response) => {
const selectedJob = response.entities.jobs[0]
if (selectedJob) {
const industryID = selectedJob.industryId
return Industry.api()
.fetchByID(industryID)
.then((result) => {
const jobInd = result.response.data
return {
tagsArray:
selectedJob.tags === 'null' || selectedJob.tags === ''
? []
: selectedJob.tags.split(','),
job: selectedJob,
jobIndustry: jobInd,
}
})
.catch(() => {
error({
statusCode: 404,
message: 'Job Industry not found',
})
})
}
})
.catch(() => {
error({
statusCode: 404,
message: 'Job not found',
})
})
},
I want to know how should I redirect the page to the home page after catching the error 404.
asyncData()'s argument is the Nuxt context, which includes redirect() that you can use to redirect the user:
export default {
asyncData({ redirect, params, error }) {
return Job.api()
.fetchByID(params.id)
.then(/*...*/)
.catch(() => {
redirect('/')
})
}
}
You can redirect user programmatically to another page like that:
this.$router.push({ name: 'home' })
or
this.$router.push('/')
Notice: First example using name is better way than hardcoded path
Example:
.catch((error) => {
error({
statusCode: 404,
message: 'Job not found',
})
this.$router.push({ name: 'home' })
})

Data return is undefined vue.js?

i have a problem i don't understand why i can't recover my recette.
My route at node is ok i have my good res ut at vue my code don't work my res is undefined.
What I am trying to do is to filter my recipes by retrieving only the recipes which have as category recipe 1. I made a route on node which works and which returns me exactly what I want but at the level of view i have a problem.
NODE.JS
router.get("/recette_light", (req, res) => {
db.cat_recette
.findOne({
where: { id: req.body.id },
include: { all: true },
})
.then((cat_recette) => {
if (cat_recette) {
res.status(200).json({
cat_recette: cat_recette,
});
} else {
res.json("il n'y a pas de cat_recettes");
}
})
.catch(err => {
res.json(err);
});
});
VUE.JS
<div>
<navbar_user />
<mylight :recette="recette" :user="user" />
<myfooter />
</div>
</template>
<script>
import navbar_user from "../components/navbar_user";
import mylight from "../components/light";
import myfooter from "../components/myfooter";
export default {
name: "",
data() {
return {
recette: "",
user: "",
};
},
components: {
navbar_user,
mylight,
myfooter,
},
created: function() {
this.axios
.get("http://localhost:3000/recette/rec_recette/:1")
.then((res) => {
(this.cat_recette.recette = res.data.recette),
this.axios
.get(
"http://localhost:3000/user/rec_user/" +
localStorage.getItem("email")
)
.then((res) => {
this.user = res.data.user;
});
});
},
};
Thank you for your help i'm novice
On the frontend, you are making an HTTP request with the GET method, which has no body. On the backend, req.body.id will be undefined because there is no request body in the first place.
So you have several options:
First: use a POST request on the front end
axios({
method: 'POST',
url:"http://localhost:3000/recette/rec_recette",
headers: {},
data: {
id: 'votre_id_ici', // This is the body part
}
});
The backend code to handle the post request:
(Use async/await to make the code cleaner)
router.post('/recette_light', async (req, res) => {
try {
// Assuming you are searching for your recette using MongoDB doc.id
const cat_recette = await db.cat_recette.findById(req.body.id);
// If there are no matching docs.
if (!cat_recette) {
return res.json("il n'y a pas de cat_recettes");
}
// Otherwise send the data to the frontend
res.status(200).json({ cat_recette: cat_recette, });
} catch (err) {
console.log(err);
res.status(500).json({ msg: 'Server Error', });
}
});
Second: use the GET method still but with URL parameters
axios.get("http://localhost:3000/recette/rec_recette/votre_id_ici")
The backend code to handle it:
// Note the /:id at the end
router.get('/recette_light/:id', async (req, res) => {
try {
// Assuming you are searching for your recette using MongoDB doc. id
// Note the req.params.id here not req.body.id
const cat_recette = await db.cat_recette.findById(req.params.id);
// If there are no matching docs.
if (!cat_recette) {
return res.json("il n'y a pas de cat_recettes");
}
res.status(200).json({ cat_recette: cat_recette, });
} catch (err) {
console.log(err);
res.status(500).json({ msg: 'Server Error', });
}
});

blink store data after change route

how can i avoid the data blink after update store data?
you can see the effect here:
https://drive.google.com/file/d/178raL6AJiC4bpIOImnaTKh6Yf9GruTCz/view?usp=sharing
component:
[...]
mounted() {
this.getIdeasFromBoard(this.$route.params.board_id);
},
[...]
store:
[...]
const actions = {
getIdeasFromBoard({ commit, dispatch }, board_id) {
apiClient
.get('/ideas/' + board_id)
.then((result) => {
console.log('success');
commit("SET_IDEAS_BOARD", result.data);
})
.catch(error => {
console.log('error' + error);
alert("You have failed to log in. Try again with another credentials.");
dispatch('auth/logout', null, { root: true });
this.$router.push({ name: "public" });
});
},
[...]
i've searched some simple tutorial about consuming api with error handling, but didnt find it.
thanks
It's because IDEAS_BOARD has the previous data until the new API call is completed. You would need to display a loader or a blank screen until the API call for the selected board is completed.
From actions, return a promise so that your component knows when is the call completed.
getIdeasFromBoard({ commit, dispatch }, board_id) {
return new Promise((resolve, reject) => {
apiClient
.get('/ideas/' + board_id)
.then((result) => {
console.log('success');
commit("SET_IDEAS_BOARD", result.data);
resolve()
})
.catch(error => {
console.log('error' + error);
alert("You have failed to log in. Try again with another credentials.");
dispatch('auth/logout', null, { root: true });
this.$router.push({ name: "public" });
reject()
});
})
},
In your .vue component,
async mounted () {
this.loading = true // some flag to display a loader instead of data
await this.$store.dispatch()
this.loading = false
}
There must be some other ways too like having this loading flag in the Vuex store. But it depends on you

Vuex promise reject returns undefined

I want the promise reject to return the error to my method but the response is empty inside my methods then() function, how can i get the error response to be returned to my method for further use or even inside the catch function.
My vuex action
//authAction
login({ commit }, payload) {
new Promise((resolve, reject) => {
user.login(payload.user.email, payload.user.password)
.then(response => {
const user = response.data.user;
// If there's user data in response
if (user) {
const payload = [user]
commit('AUTH_SUCCESS', payload, { root: true })
resolve(response)
} else {
reject({ message: "Sorry, cant login right now" })
}
})
.catch(error => {
console.log(error.response.status)
reject(error)
})
})
}
My method
// Login method
login() {
if (!this.checkLogin()) return;
this.$vs.loading();
const payload = {
checkbox_remember_me: this.checkbox_remember_me,
user: {
email: this.email,
password: this.password
}
};
this.$store
.dispatch("auth/login", payload)
.then(res => {
this.$vs.loading.close();
console.log(res);
})
.catch(error => {
this.$vs.loading.close();
this.$vs.notify({
title: "Error",
text: error.message,
});
});
}
What am i missing?
Thanks in advance!
My solution is to 1. dispatch an action whenever an error is thrown which updates state 2. watch state change in view and do something with it

VueJS / ExpressJS (Backend) - Getting data from an API

I'm learning VueJS / Express and I'm trying to display data from an external API onto my page. I'm using Express as the API Calls require headers + I believe its safer to keep it separate from Vue.
Here is my Express
app.get('/summoner', function(request, response) {
axios.get('https://euw1.api.riotgames.com/lol/summoner/v3/summoners/by-name/XXXXXXXX', {headers: headers})
.then(response => {
console.log(response.data)
})
.catch(error => {
console.log(error)
})
})
Here is my Vue code:
import axios from 'axios'
export default {
name: 'summoner',
data () {
return {
summoner: [],
errors: []
}
},
created () {
console.log('Created')
axios.get('/api/summoner')
.then(response => {
console.log('Hit me')
this.summoner = response.data
})
.catch(e => {
this.errors.push(e)
console.log(e)
})
}
}
The console.log(response.data) is showing me the object I expect which is:
{ id: XXXXXXXX,
accountId: XXXXXXXX,
name: 'XXXXXXXX',
profileIconId: XXXXXXXX,
revisionDate: XXXXXXXX,
summonerLevel: XXXXXXXX }
The console.log('Hit Me') is never fired
The console.log('Created') is fired on page load.
Nothing I seem to try allows me to display any of the object using Vue e.g:
{{ summoner.id }}
Just to add, I have configured a proxy in webpack which forwards the below requests to Express. As far as I can tell, this is working as each time I refresh the page, I see the ExpressJS console.log(response.data) fire
Could anyone help?
Thanks!
In your express code you do not return the repsonse (which you also override in the axios response). Try changing it to
app.get('/summoner', function(request, res) { // <--- careful here is a change
axios.get('https://euw1.api.riotgames.com/lol/summoner/v3/summoners/by-name/XXXXXXXX', {headers: headers})
.then(response => {
console.log(response.data)
return res.status(200).send(response.data);
})
.catch(error => {
console.log(error)
return res.status(400).send(error);
})
})
I actually resolved this by doing:
res.json([response.data])
In the ExpressJS side of things.
I also had to use response.data[0] within Vue.