Data return is undefined vue.js? - 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', });
}
});

Related

Setting variables in Vue 2 using Fetch API: Async Task

am relatively new to async tasks but I cant comprehend why my fetch API wont set my vue variable but on console.log it shows the Variable. I’ve tried Async/Await in vain. See the code segment below on my .vue component.
data(){
return{
pg:’’
}
},
methods:{
insertData(){
this.insertDataAPI()
console.log(this.pg) //THIS GIVES EMPTY STRING INSTEAD OF FETCHED DATA
},
insertDataAPI(){
fetch(‘EndPoint’, {
method:'POST',
headers:{
// some headers
},
body:JSON.stringify({
// some data
})
}).then( res => res.json())
.then(async page =>this.pg = await page //Console.log logs the page fine
// but variable pg is not set
).catch( (err) => {
console.log(err)
});
}
}
async/await is a different handler for promise.then().catch(). As fetch returns a promise you can use both
Option 1, await the fetch:
methods: {
insertData() {
this.insertDataAPI();
console.log(this.pg);
},
insertDataAPI() {
const response = await fetch(‘EndPoint’, {
method:'POST',
headers:{
// some headers
},
body:JSON.stringify({
// some data
})
});
this.pg = response.json();
}
}
Option 2, await the insertDataAPI:
methods: {
async insertData() {
await this.insertDataAPI();
console.log(this.pg);
},
insertDataAPI() {
return fetch(‘EndPoint’, {
method:'POST',
headers:{
// some headers
},
body:JSON.stringify({
// some data
})
}).then(res => res.json())
.then(page => this.pg = page)
.catch( (err) => {
console.log(err)
});
}
}
let's try to read about the way async/ await work
you can try on Axiost lib for easier to fetch APIs

Nuxt js Router Push Not Working After Delete

I've created a simple CRUD with Nuxt. Data is provided by Lumen. I got a problem with the DELETE, data is deleted but Nuxt does not redirect to the other page.
Here is my script:
<script>
export default {
name: 'EmployeePage',
data() {
return {
fields: ['name','email','image','address'],
emplyees:[],
}
},
mounted() {
this.$axios.get('/employee').then(response => {
this.pegawais = response.data.data
}).catch(error => {
console.log(error.response.data)
})
},
methods: {
async delete(id) {
await this.$axios.delete(`/employee/${id}`).then(response => {
this.$router.push({ name: 'employee' }) <-----this redirect not working
})
}
}
}
</script>
I want Nuxt to redirect to the employee page that display all the data after the deletion.
You should not mix async/await and .then. Use the first approach, that way you will not have the .then callback hell and it will be cleaner overall.
Like this
<script>
export default {
name: 'EmployeePage',
data() {
return {
fields: ['name', 'email', 'image', 'address'],
emplyees: [],
}
},
async mounted() {
try {
const response = await this.$axios.get('/employee')
this.pegawais = response.data.data
} catch (error) {
console.log(error.response.data)
}
},
methods: {
async delete(id) {
await this.$axios.delete(`/employee/${id}`)
await this.$router.push({ name: 'employee' })
},
},
}
</script>
await this.$router.push does not require an await but it's a Promise too, so I'm writing it like that in case you need to call something else afterwards.
this.$axios.$get('/employee') can also be used if you want to remove a .data aka this.pegawais = response.data as shown here.

How do I make this axios call inside my own API route?

This is my first time trying to make an API call to a third party while inside my own API route. The following code does not work because I get the error "Cannot use import statement outside a module." This code is called by a thunk at the front end.
If I can't import axios, what's an alternative?
EDIT: I got rid of the error by doing 'const axios = require('axios') but now the results I'm getting is undefined.
EDIT2: Resolved. Through use of the following:
router.get("/:zip", async (req, res, next) => {
try {
let data = [];
await axios
.get(`https://api.yelp.com/v3/businesses/search`, {
headers: {
Authorization: `Bearer ${process.env.SECRET_KEY_YELP}`,
},
params: {
location: req.params.zip,
// categories: "coffee",
},
})
.then((response) => {
data = response.data;
});
res.send(data);
} catch (err) {
next(err);
}
});
ORIGINAL CODE WITH ISSUE:
const router = require("express").Router();
module.exports = router;
import axios from "axios";
router.get("/:zip", async (req, res, next) => {
try {
//const restaurants = await Test.findAll({})
const result = await axios.get(
`https://api.yelp.com/v3/businesses/search?location=${req.params.zip}`,
{
headers: {
Authorization: `Bearer ${process.env.SECRET_KEY_YELP}`,
},
params: {
categories: "coffee",
},
}
).data;
res.send(result);
} catch (err) {
next(err);
}
});
Posted above. It needed a .then snippet.
let data = [];
await axios
.get(`https://api.yelp.com/v3/businesses/search`, {
headers: {
Authorization: `Bearer ${process.env.SECRET_KEY_YELP}`,
},
params: {
location: req.params.zip,
// categories: "coffee",
},
})
.then((response) => {
data = response.data;
});
res.send(data);

How can I test data returned from an ajax call in mounted is correctly rendered?

I have a component (simplified)
<template>
<div v-if="account">
<h1 v-text="accountName"></h1>
</div>
</template>
<script>
import repo from '../../repo';
export default {
data() {
return {
account: {}
}
},
mounted() {
return this.load();
},
computed: {
accountName: function () {
return this.account.forename + ' ' + this.account.surname;
}
},
methods: {
load() {
return repo
.get(repo.accounts, {
params: {
id: this.$route.params.id
}
})
.then((response) => {
console.log(response.data);
this.account = response.data;
this.validateObj = this.account;
}, (error) => {
switch (error.response.status) {
case 403:
this.$router.push({name: '403'});
break;
default:
this.$refs['generic_modal'].open(error.message);
}
});
}
}
}
</script>
Which on mount, calls an API, gets the returned data, and renders the forename and surname.
I'm trying to write a mocha test to check that this works. I can do it using a timeout.
it('mounts', done => {
const $route = {
params: {
id: 1
}
};
mock.onGet('/api/accounts/1').reply(200, {
forename: 'Tom',
surname: 'Hart'
});
const wrapper = shallowMount(AccountsEdit, {
i18n,
mocks: {
$route
}
});
setTimeout(a => {
expect(wrapper.html()).toContain('Tom Hart');
done();
}, 1900);
});
But I wondered is there a better way? I was hoping to hook into the axios.get call, and run the check once that's finished, however, I can't seem to figure out how to do it.
EDIT: I tried using $nextTick, however, that didn't work either
wrapper.vm.$nextTick(() => {
expect(wrapper.html()).toContain('Tom Hart');
done();
});
{ Error: expect(received).toContain(expected) // indexOf
Expected substring: "Tom Hart"
Received string: "<div><h1>undefined undefined</h1></div>"
at VueComponent.<anonymous> (/home/tom/Dev/V6/Admin/.tmp/mocha-webpack/1554202885644/tests/Javascript/Components/Pages/account-edit.spec.js:37:1)
at Array.<anonymous> (/home/tom/Dev/V6/Admin/node_modules/vue/dist/vue.runtime.common.dev.js:1976:12)
at flushCallbacks (/home/tom/Dev/V6/Admin/node_modules/vue/dist/vue.runtime.common.dev.js:1902:14)
matcherResult: { message: [Function: message], pass: false } }
{ forename: 'Tom', surname: 'Hart' }
1) mounts
0 passing (2s)
1 failing
1) Accounts Edit Page
mounts:
Error: Timeout of 2000ms exceeded. For async tests and hooks, ensure "done()" is called; if returning a Promise, ensure it resolves. (/home/tom/Dev/V6/Admin/.tmp/mocha-webpack/1554202885644/bundle.js)
EDIT 2: It seems just as a test, chaining $nextTick eventually works, so I guess something else is causing ticks before my call returns? Is there anyway to tell what caused a tick to happen?
wrapper.vm.$nextTick(() => {
wrapper.vm.$nextTick(() => {
wrapper.vm.$nextTick(() => {
wrapper.vm.$nextTick(() => {
wrapper.vm.$nextTick(() => {
wrapper.vm.$nextTick(() => {
expect(wrapper.find('h1').html()).toContain('Tom Hart');
done();
});
});
});
});
});
});
Hey we had similar problem and found this library:
https://www.npmjs.com/package/flush-promises
Which allow to us wait all promises before continue testing.
Try to do something like this:
const flushPromises = require('flush-promises');
it('mounts', (done) => {
const $route = {
params: {
id: 1
}
};
mock.onGet('/api/accounts/1').reply(200, {
forename: 'Tom',
surname: 'Hart'
});
const wrapper = shallowMount(AccountsEdit, {
i18n,
mocks: {
$route
}
});
flushPromises().then(() => {
expect(wrapper.html()).toContain('Tom Hart');
done();
});
});

Why can't I pass my user_name value into my component? (Auth)

I am trying to pass the name of the user after authentication into a Vue component, but I get a name: undefined value after load.
Here is my AuthService.js:
//config details taken from OAUTH JS doc: https://github.com/andreassolberg/jso
import { JSO, Fetcher } from 'jso';
const client = new JSO({
providerID: '<my-provider>',
default_lifetime: 1800,
client_id: '<my-client-id>',
redirect_uri: 'http://localhost:8080/',
authorization:'<my-auth-server>/oauth/authorize'
//scopes: { request: ['https://www.googleapis.com/auth/userinfo.profile'] }
});
export default {
getProfile() {
// JSO plugin provides a simple wrapper around the fetch API to handle headers
let f = new Fetcher(client);
let url = 'https://www.googleapis.com/auth/userinfo.profile';
f.fetch(url, {})
.then(data => {
return data.json();
})
.then(data => {
return data.user_name;
})
.catch(err => {
console.error('Error from fetcher', err);
});
}
};
Then, in my single file component named MainNav, I have:
import AuthService from "#/AuthService";
export default {
name: "MainNav",
data() {
return {
name: ""
};
},
created() {
this.name = AuthService.getProfile();
}
};
</script>
Anyone have any tips on how I can get the user_name value from the AuthService to my component? I will then need to then display the name in my nav template. Doing a console.log test works fine, just can't return it to my SFC. Also, the JSO library is here: https://github.com/andreassolberg/jso#fetching-data-from-a-oauth-protected-endpoint
Because getProfile returns nothing (undefined). I see you use es6 then you can use async functions
//config details taken from OAUTH JS doc: https://github.com/andreassolberg/jso
import { JSO, Fetcher } from 'jso';
const client = new JSO({
providerID: '<my-provider>',
default_lifetime: 1800,
client_id: '<my-client-id>',
redirect_uri: 'http://localhost:8080/',
authorization:'<my-auth-server>/oauth/authorize'
//scopes: { request: ['https://www.googleapis.com/auth/userinfo.profile'] }
});
export default {
getProfile() {
// JSO plugin provides a simple wrapper around the fetch API to handle headers
let f = new Fetcher(client);
let url = 'https://www.googleapis.com/auth/userinfo.profile';
return f.fetch(url, {}) // return promise here
.then(data => {
return data.json();
})
.then(data => {
return data.user_name;
})
.catch(err => {
console.error('Error from fetcher', err);
});
}
};
And
import AuthService from "#/AuthService";
export default {
name: "MainNav",
data() {
return {
name: ""
};
},
async created() {
try {
this.name = await AuthService.getProfile();
} catch(error) {
// handle
}
}
};
</script>
Or without async (add one more then)
import AuthService from "#/AuthService";
export default {
name: "MainNav",
data() {
return {
name: ""
};
},
created() {
AuthService.getProfile().then((userName) => this.name = userName))
.catch((error) => { /* handle */ })
}
};
</script>