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.
Related
I would like to configure my Angular component, so that the page only loads if the ID in the URL is valid. The point here is, that I want to protect the page from users manually entering a random URL, and accessing any page.
I have a component with lists.
If I click on the "Show Details", Angular navigates to the details page. I would like to only open this page, if the entered URL contains a valid ID. To achieve this, I call a service to gather all IDs into an array of strings. And then examine if the entered ID is a member of that array.
What I have tried:
list.component.ts:
ngOnInit() {
this.fetchLists();
}
fetchLists() {
from(this.listService.getGroups())
.pipe(
takeUntil(this.destroy$)
)
.subscribe({
next: (listUI: ListUI[]) => {
this.listData = listUI;
},
error: (error) => {
this.logger.debug(error.message);
this.certError = true;
}
});
}
details.component.ts:
ngOnInit() {
this.fetchListsAndIDs();
if (this.validIDsList.includes(listID)) {
this.router.navigateByUrl(`/groups/lists/${listID}/details`);
}
else {this.router.navigateByUrl(`/groups/lists`);}
}
fetchListsAndIDs() {
from(this.listService.getGroups())
.pipe(
takeUntil(this.destroy$)
)
.subscribe({
next: (listUI: ListUI[]) => {
const listData = listUI;
this.validIDsList = listData.map((lists) => lists.id);
},
error: (error) => {
this.logger.debug(error.message);
this.certError = true;
}
});
}
app.routing.module.ts
{
path: 'groups/lists/${listID}/details',
component: DetailsComponent
}
The page "groups/lists/99999999999/details" opens, with zero data, and "this.validIDsList" is undefined. Can someone please help me how to fix this?
You almost have the right code, but you missed the part that, this.fetchListsAndIDs() is executing an asynchronous observable, so your if..else block is executing before even the API call completes.
I would suggest, you include the if...else check inside the next() handler. I have reversed the conditions to check for NOT first, since you are already in details.components.ts which represents ``/groups/lists/${listID}/details) route, you should only redirect the user back to lists if id is not valid, else the component should continue with its work.
I added code to grab the listId from URL. It is missing in the code you posted in the question.
ngOnInit() {
this.listID = this.route.snapshot.paramMap.get('listID');
this.fetchListsAndIDs();
}
fetchListsAndIDs() {
from(this.listService.getGroups())
.pipe(
takeUntil(this.destroy$)
)
.subscribe({
next: (listUI: ListUI[]) => {
const listData = listUI;
this.validIDsList = listData.map((lists) => lists.id);
this.handleNavigation();
},
error: (error) => {
this.logger.debug(error.message);
this.certError = true;
}
});
}
handleNavigation() {
if (!this.validIDsList.includes(this.listID)) {
this.router.navigateByUrl(`/groups/lists`);
} else {
// call the function to continue with details component
}
}
My project were working fine. I just found out in console network that one of my GET request is sending twice, even I just send it once. See network console
If I comment the the whole code of created function, all GET request would no longer load/exist in the console network. (see code below)
I want to know what causes this, and how should I fix this?
Here is the Component.vue
<script>
export default {
created: async function() {
await this.$store.dispatch('file/all');
},
};
</script>
And the vuex module post.js's action:
const actions = {
all({commit}, data) {
return axios.get(`files`)
.then(response => {
commit('setData', response);
});
},
}
After many hours of searching, I found out that the key that is assigned to the Component caused the problem.
When the key is modified the GET request will send again. This the reason why it sends twice. Special thanks to #Anatoly for giving me the hint.
Below is the usage codes:
<template>
<Component :key="componentKey" #edit="dataIsChanged"/>
</template>
<script>
export default {
components: { Component },
data: () => ({
componentKey: 0,
}),
methods: {
dataIsChanged: function() {
this.componentKey = Math.random();
}
}
};
</script>
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.
I am using star-rating plugin in vue js, and I am using v-model to show the ratings from db. Everything works fine as when user is not logged in and he/she tries to rate it shows an error "login to rate", but the stars dont reset to db value instead it shows the rating of not logged in user. Currently after the error msg I am refreshing the whole page. Is there a simple way to reset the stars instead of refreshing the whole page?
:show-rating="false" #rating-selected="setRating" v-model="rating"
v-bind:star-size="20"
above is the start rating and while clicking it calls a function where I am checking if user is logged in or not with an api call. Thanks in advance.
setRating: function (rating) {
axios.get('/checkuser').then(response => {
this.user = response.data;
if (this.user === "Logout") {
toastr.error('Please login to rate', 'Error', {
positionClass: 'toast-bottom-right'
});
window.location = "/menu/" + this.menu_id;
} else {
// save in to db
}
}).catch(error => {
// TODO: Handle error
});
},
You will have to reset rating object if it's not logged in.
setRating: function (rating) {
axios.get('/checkuser').then(response => {
...
if (this.user === "Logout") {
...
this.rating = 0; <=== reset rating here (in data, not the rating parameter)
}
...
})
...
},
managed to fix it by using "this.load()" after the api call, which refreshes all components. :)
I just have a question to find out if this is possible:
So what I am doing is when I submit a post I wait for it to complete then update the user object in firebase to insert a time-stamp.
This is fine and works but when the time-stamp is inserted it is causing other subscriptions that are subscribed to changes in the user object to update.
What I want to do it update the user object without causing other subscribers to be updated.
Here is where I am updating the timestamp:
I tried commenting out this line of code which stops the data duplication issue on screen but I need this code to run as I need to update the timestamp when a post is submitted.
this.af.database.object('users/' + x[0].uid + '/lastPostAt').set(timestamp)
.then(x => { this.dialogsService.showSuccessDialog('Post Submitted'); });
Here is where I am subscribing to all the posts:
subscribeAllPosts(): Observable<Post[]> {
return this.af.database.list('/posts')
.map(Post.fromJsonList);
}
Here is where I am creating the array of posts in my constructor to display via a loop in the html:
this.activeItem = this.items[0];
this.postsService.subscribeAllPosts()
.subscribe(posts => {
let container = new Array<PostContainer>();
for (let post of posts) {
this.getEquippedItemsForUsername(post.username).subscribe(
x => {
try {
container.push(new PostContainer(post, x[0].equippedItems));
} catch (ex) { }
}
);
}
this.postContainers = container;
});
In the inner subscription it gets the equippedItems for the user of the post:
getEquippedItemsForUsername(username: string) {
return this.usersService.subscribeUserByUsername(username);
}
Which in turns calls:
subscribeUserByUsername (username: string) {
return this.af.database.list('users' , {
query: {
orderByChild: 'username',
equalTo: username
}
});
}
In the HTML it loops through the postContainer[]:
<li *ngFor="let item of postContainers">
So all that works the issue as stated is that if I do not have the following commented out then the posts will be duplicated more and more as the posts are submitted. If I refresh the app then the posts will show the correct non duplicated posts until another post is submitted.
this.af.database.object('users/' + x[0].uid + '/lastPostAt').set(timestamp)
.then(x => { this.dialogsService.showSuccessDialog('Post Submitted'); });
EDIT: Solved by splitting up logic.