How to get value from Axios request? - javascript

I have this code
(Pay attention to the HTML class 'symbolTicket "')
<template>
<div class="chart">
<span class="symbolTicket">
{{getTicket()}}
</span>
<div class="chartContent">
</div>
<!-- <div class="chartContent"> end -->
</div>
<!-- <div class="chart"> end -->
</template>
<script>
import axios from 'axios';
export default{
data() {
return {
};
},
methods: {
getTicket: function () {
return axios.get("http://localhost:2000/" , {
params: {
foo: 'SELECT * FROM eur_usd WHERE primary_key = 2;'
}
})
.then(function (response) {
console.log(response.data.ticket);
return response.data.ticket;
})
.catch(function (error) {
console.log(error);
});
},
},
}
</script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
I need to somehow get the value out of the query.
P.S. The result of the current solution can be seen on the screen.
From the top you can see what value is returned. (Object instead of data)
From the bottom of the console log - we see that the answer itself is working (no errors.)
It is this data that needs to be displayed inside the tag.

The standard way to do this would be to display a data property in the template.
<span class="symbolTicket">
{{ ticket }}
</span>
data () {
return {
ticket: null
}
}
Then load the value from the created hook:
created () {
this.getTicket()
},
methods: {
getTicket () {
return axios.get("http://localhost:2000/" , {
params: {
foo: 'SELECT * FROM eur_usd WHERE primary_key = 2;'
}
})
.then(response => {
const ticket = response.data.ticket;
// Update the data property
this.ticket = ticket;
console.log(ticket);
return ticket;
})
.catch(function (error) {
console.log(error);
});
}
}
The method getTicket is making an asynchronous request to the server so there's no way it can return the ticket directly. All it can return is the corresponding promise. The template needs the value synchronously, so relying on the return value from getTicket can't work.
You may also need to handle the case where ticket is null. During the initial rendering the request to the server won't have completed, so ticket will still be null.
If you're happy using async/await the getTicket method can be simplified but it won't change the overall flow described above. You still need a separate data property to hold the result.

Related

Why does my API data show up as undefined when using a v-if in vue.js?

TEMPLATE
<template>
<div class="profile-container">
<div class="theme-container">
<img class="theme" src="#" alt="PH">
</div>
<div class="profile-pic-container">
<img class="profile-pic" :src="responseData.profile_pic" alt="PH">
</div>
<div class="profile-info-container">
<div class="follow-message-button-container">
<button class="direct-message-button btn"><svg><use href="#chat-icon"></use></svg></button>
<Follow v-if="responseData.followers.includes($store.state.userId)"></Follow>
</div>
<h3 class="profile-username">#{{responseData.username}}</h3>
<p class="profile-bio">{{responseData.bio}}</p>
<div class="follower-following-count">
Followers: {{responseData.followers.length}}
Following: {{responseData.following.length}}
</div>
</div>
</div>
</template>
responseData.followers.length works correctly but responseData.followers.includes($store.state.userId) does not. It gives me an error saying:
Cannot read property includes of undefined
SCRIPT
<script>
import Follow from "#/components/Follow";
import getAPICall from "#/mixins/getAPICall";
import getSecondAPICall from "#/mixins/getSecondAPICall";
import Post from "#/components/Post";
export default {
name: "Profile",
components: {Post, Follow},
data() {
return {
list: [],
responseData: {},
responseData2: {},
APIUrl: `api/user/${this.$route.params.userId}`
}
},
methods: {
},
mixins: [getAPICall, getSecondAPICall],
created() {
this.getAPICall(this.APIUrl)
this.getSecondAPICall(`api/user-post-list/${this.$route.params.userId}`)
}
}
</script>
This is what my axios api call looks like
MIXINS
import {getAPI} from "#/axios.api";
import store from "#/store";
export default {
data() {
return {
getAPICall(APIUrl) {
getAPI.get(APIUrl, {headers: {Authorization: `Bearer ${this.$store.state.accessToken}`}}
).then(response => {
this.responseData = response.data
}).catch(err => {
console.log(err)
store.dispatch('useRefreshToken'
).then(_ => {
console.log(_)
getAPI.get(APIUrl, {headers: {Authorization: `Bearer ${this.$store.state.accessToken}`}}
).then(response => {
this.responseData = response.data
}).catch(err => {
console.log(err)
})
}).catch(err => {
console.log(err)
})
}
)
}
}
}
}
When I console log responseData in the created() hook I get an empty proxy.
When I console log it in the mounted hook I get a proxy object with the correct data but if I try to call my API mixins from the mounted hook I still get the same error as before and the rest of my page breaks.
Console logging responseData in the browser returns undefined.
Try to make sure that you have responseData . As vue is first creating the template it is looking for properties in reponseData. And in this case it is not finding the properties. I faced such problems few times. The page is rendered before the api is returing data. Declare responseData: null and check
<div class="profile-container" v-if=" responseData !== null">
problem is here,
responseData.followers is not take place immediately when render. because api call response will take time. so replace that line like this way
<Follow
v-if="responseData.followers && responseData.followers.includes($store.state.userId)">
</Follow>
and may be you should call those api synchronously, but it is depending on your requirement. if there is any dependency between those two api then should call synchronously but any other case it is ok.
//asynchronous operation
created() {
this.getAPICall(this.APIUrl)
this.getSecondAPICall(`api/user-post-list/${this.$route.params.userId}`)
}
//synchronous operation
async created() {
await this.getAPICall(this.APIUrl)
await this.getSecondAPICall(`api/user-post-list/${this.$route.params.userId}`)
}
There is little change required in your code like followers: [] has set in your data() return
data() {
return {
list: [],
responseData: {followers: []},
responseData2: {},
APIUrl: `api/user/${this.$route.params.userId}`
}
},

Stripe not being called

I am trying to use Vue.js for my front end to call Stripe and create a token which then is sent to my backend. I have tested everything using plain HTML/JS and it all works fine, my issue comes in trying to use Vue.js I think my issue might be in how I am binding the stripe public key. Below is my code, and I have zero output to speak of, I get just redriected to the same page but wth ? at the end of the URL. Nothing else, console shows nothing and no error message or anything send to my back end.
template code
There is more but not related
<div class="col-md-8">
<card class='stripe-card col-md-8'
:class='{ complete }'
:stripe='stripeKey'
:options='stripeOptions'
#change='complete = $event.complete'
/>
<button class='pay-with-stripe' #click='pay' :disabled='!complete'>Submit Payment Details</button>
<br>
</div>
script section with relavent added
import { Card, createToken } from 'vue-stripe-elements-plus'
import axios from 'axios';
export default {
components: { Card },
data() {
return {
errorMessage: null,
successMessage: null,
complete: false,
stripeKey: process.env.VUE_APP_STRIPE_PUB_KEY,
stripeOptions: {
// see https://stripe.com/docs/stripe.js#element-options for details
hidePostalCode: true
},
current: {
stripe: {
plan: null,
last4: null
}
},
}
},
methods: {
pay () {
createToken().then(result => {
axios.post('/billing/updateCard', {
token: result.token,
})
.then(res => {
if(res.data.success == true) {
this.successMessage = res.data.message
console.log(res.data.message)
}
if(res.data.success == false) {
this.errorMessage = res.data.message // Display error message from server if an error exists
}
})
.catch((err) => {
if(err) console.log(err)
if(err) this.$router.push('/company/settings?success=false')
})
});
}
}
}
</script>
I have checked that the API key is actually in the data value by doing <p>{{ stripeKey }}</p> and seeing the value show up. So yes the key is there and the key is valid (tested copy/paste into my HTML/JS test)
created(){
this.key=process.env.VUE_APP_STRIPE_KEY;
}
try this, i used this piece of code in my project and it worked... the issue maybe is that your key is not yet initialized when card us rendered idk. maybe key isnt issue at all. try this and let me know if works and we will debug it together.

Axios put request issue

I'm currently building a blog and I'm stuck in the edit article part.
So, on the edit article page I use v-model in order to retrieve the data from the vue store :
<form action="/http://localhost:4000/articles" method="POST">
<div role="button" type="submit" #click="submitArticle">Save</div>
<div class="article-writing__inner" v-for="article in articles">
<div class="title-offset">Title</div>
<input class="input-title" type="text" v-model="article.title"/>
<tinymce id="d1"v-model="article.text"></tinymce>
</div>
</form>
I use a computed property for the v-for loop:
computed: {
articles() {
return this.$store.state.articles
}
}
And finally I send my data to the API with axios like this :
methods: {
submitArticle() {
axios.put('http://localhost:4000/articles/:id', {
title: article.title,
text: article.text,
})
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
});
}
}
As I expected, I can't access the store (v-model) data in axios. In the create article template, I used v-model like below and I managed to post with title: this.title.
data() {
return {
title: "",
text: ""
}
}
How can I bind the v-model from local component data function, or to axios?Or is that another way to do it?
Thank you for your time :)
Article is not set to anything in the the put call to axios. One way to grab your state values in the axios call is to do the following.
submitArticle() {
let vm = this;
axios.put('http://localhost:4000/articles/:id', {
title: vm.article.title,
text: vm.article.text,
})
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
});
}
}
It's all about the scoping of what 'this' is in context of the axios call.

Using Axios and Vue to fetch api data - returning undefined

Running into a snag with trying to integrate my API with Vue/Axios. Basically, Axios is getting the data (it DOES console.log what I want)... But when I try to get that data to my empty variable (in the data object of my component) to store it, it throws an "undefined at eval" error. Any ideas on why this isn't working for me? Thanks!
<template>
<div class="wallet-container">
<h1 class="title">{{ title }}</h1>
<div class="row">
{{ thoughtWallet }}
</div>
</div>
</template>
<script>
import axios from 'axios';
export default {
name: 'ThoughtWallet',
data () {
return {
title: 'My ThoughtWallet',
thoughtWallet: [],
}
},
created: function() {
this.loadThoughtWallet();
},
methods: {
loadThoughtWallet: function() {
this.thoughtWallet[0] = 'Loading...',
axios.get('http://localhost:3000/api/thoughts').then(function(response) {
console.log(response.data); // DISPLAYS THE DATA I WANT
this.thoughtWallet = response.data; // THROWS TYPE ERROR: Cannot set property 'thoughtWallet' of undefined at eval
}).catch(function(error) {
console.log(error);
});
}
}
}
</script>
Because you're using .then(function(..) { }) this won't refer to the vue context this.
You have two solutions, one is to set a variable that references the this you want before the axios call, e.g.:
var that = this.thoughtWallet
axios.get('http://localhost:3000/api/thoughts').then(function(response) {
console.log(response.data); // DISPLAYS THE DATA I WANT
that = response.data; // THROWS TYPE ERROR: Cannot set property 'thoughtWallet' of undefined at eval
}).catch(function(error) {
console.log(error);
});
The other is to use the new syntax (for which you need to make sure your code is transpiled correctly for browsers that don't support it yet), which allows you to access this inside the scoped body of the axios then.
axios.get('http://localhost:3000/api/thoughts').then((response) => {
console.log(response.data); // DISPLAYS THE DATA I WANT
this.thoughtWallet = response.data; // THROWS TYPE ERROR: Cannot set property 'thoughtWallet' of undefined at eval
}).catch(function(error) {
console.log(error);
});
The reason this happens is because inside that function/then, this will be referring to the context of the function, hence there won't be a thoughtWallet property
this.thoughtWallet inside the .get method is referring to the axios object, not Vue's. You can simply define Vue's this on the start:
methods: {
loadThoughtWallet: function() {
let self = this;
this.thoughtWallet[0] = 'Loading...',
axios.get('http://localhost:3000/api/thoughts').then(function(response) {
console.log(response.data); // DISPLAYS THE DATA I WANT
self.thoughtWallet = response.data;
}).catch(function(error) {
console.log(error);
});
}
}

Grab attribute of current record for Meteor Method Call

I am working on a project to pull in twitter timeline's for selected teams/players. When I am on the team/_id page, how can I grab an attribute to path through a method?
Below is my client side javascript, as well as the relevant route from iron router. When I type in something like "patriots" to the "????" section, I get a result. I would like to do this dynamically, I currently have the twitter handles stored under the twitter attribute.
Template.tweets.helpers({
teams: function() {
return Teams.find();
},
});
Template.tweets.onRendered(function () {
var twitterHandle = "???";
Meteor.call('getTimeline', twitterHandle, function(err,results){
if (err) {
console.log("error", error);
};
console.log(results);
Session.set("twitter", JSON.parse(results.content));
})
return Session.get("twitter");
});
Router.route('/teams/:_id', {
name: 'teamView',
template: 'teamView',
data: function(){
var currentTeam = this.params._id;
return Teams.findOne({ _id: currentTeam });
var twitterHandle = this.params.twitter;
return Teams.findOne({twitter: twitterHandle});
}
});
<template name="tweets">
<h3>Tweets</h3>
<div class="container">
{{twitter}}
</div>
</template>
You should be able to access all information from the current route using the Router.current() object. In your case you can use Router.current().params._id to get the _id param:
var twitterHandle = Router.current().params._id;
Edits based on your comments below
I did not notice that you were calling the Teams.findOne function twice in your route's data function. Form the looks of it you're already storing the twitter handle in the Teams collection, so you merely need to access the data that's returned by the route.
Template.tweets.helpers({
twitterData: function() {
//return the data stored in the callback function of the Meteor method call in the onRendered event
return Session.get('twitter');
}
});
Template.tweets.onRendered(function () {
//clear any previously stored data making the call
Session.set('twitter', null);
//property of the team document returned by the data function in the route.
var twitterHandle = this.data.twitter;
Meteor.call('getTimeline', twitterHandle, function(err,results){
if (err) {
console.log("error", error);
} else {
Session.set("twitter", JSON.parse(results.content));
}
});
});
Router.route('/teams/:_id', {
name: 'teamView',
template: 'teamView',
data: function(){
var currentTeam = this.params._id;
return Teams.findOne({ _id: currentTeam });
}
});
<template name="tweets">
<h3>Tweets</h3>
<div class="container">
<!-- twitterData will be an object, so you'll need to figure out what properties to display and use dot notation//-->
{{twitterData}}
</div>
</template>

Categories

Resources