I am coding a restaurant reviews app with Vue.js and Django REST Framework.
User can "POST" pictures on their reviews.
As soon as the user click a 'Create review' button, this function is triggered:
addReview () {
let endpoint = `/api/restaurant_review/`;
let method = "POST";
apiService(endpoint, method, { maps: this.$route.params.maps, review_author: 1 })
.then(res => {
let review_id = res.id
console.log(review_id)
return review_id
})
},
So I also get a review_id from my response. I pass it to an other component where the user can upload pictures this way:
<ReviewEditor
:id= "review_id"/>
In my data() I have:
review_id: 0,
So in my ReviewEditor component, I get the id like this:
props: {
id: {
type: Number,
required: true
},
}
And then:
onUpload() {
const fd = new FormData();
let axiosConfig = {
headers: {
'X-CSRFTOKEN': CSRF_TOKEN,
}
};
fd.append('picture_1', this.selectedFile)
fd.append('restaurant_review', this.id)
axios.post('http://127.0.0.1:8000/api/outside_pic/', fd, axiosConfig)
.then(res => {
console.log(res)
})
}
My onUpload() function works well if I pass manually the id, but if I do it dynamically with this.id, I have an error message telling me that 'restaurant_id' = 0, and therefore doesn't exists. I also tried review_id: 0, but with no luck either.
Related
I need to activate a modal component from vuex store. I was using 'this.$refs['modalSuccess'].show()' to show the modal inside the component when the result API was successed!
But I needed to change the function 'sendLeadResponse' from methods (component) to action (store). After that, I cannot activate the modal anymore with this 'this.$refs['modalSuccess'].show()'.
Is there any way to call it from a store?
This is the following flow:
Button: activate a method inside the component;
Method: activate an action from store;
Action: it uses a external API;
Modal: If the result is ok it activates a modal which it is inside the component;
COMPONENT WITH BUTTON AND THE MODAL
<template>
<section>
<div class="w-100 d-md-flex justify-content-md-end">
<SmallButton
smallButtonText="Quero ser cliente →"
#event="createLeadObject()"
id="show-btn"
/>
</div>
<b-modal
ref="modalSuccess"
ok-only
> Obrigado pelo interesse! Em breve entraremos em contato.
</b-modal>
</div>
</section>
</template>
<script>
import SmallButton from '../SmallButton.vue'
export default {
name: 'BeClientForm',
components: {
SmallButton
},
methods: {
createLeadObject(){
const dataLeadObject = {
date: new Date(),
fullName: this.lead.name,
email: this.lead.email,
phone: this.lead.phone,
comment: this.lead.comment
}
this.$store.dispatch('sendLeadResponse', dataLeadObject)
},
}
}
</script>
ACTION FROM STORE
actions: {
async sendLeadResponse({commit}, dataLeadObject){
const jsonDataObject = JSON.stringify(dataLeadObject)
await fetch("http://localhost:5000/api/lead/leadResponse", {
method: "POST",
headers: {"Content-type": "application/json"},
body: jsonDataObject
})
.then((resp) => resp.json())
.then((data) => {
if (data.error) {
commit('MESSAGE_RESPONSE', data.error)
}
else {
commit('RESET_LEAD_RESPONSE')
!!!!!!!!!!!!! this.$refs['modalSuccess'].show() !!!!!!!!!!!!!! [it is not working)
}
})
},
}
The Vuex store is designed to only care about the state. It does not have direct access to your components or this.$refs. What you can do is set a piece of state in your store based on the result of your fetch and have your component access that state, and/or return a promise from your action so the result is handed directly back to your component
async sendLeadResponse({ commit }, dataLeadObject) {
const jsonDataObject = JSON.stringify(dataLeadObject);
// assign promise from fetch
const response = await fetch('http://localhost:5000/api/lead/leadResponse', {
method: 'POST',
headers: { 'Content-type': 'application/json' },
body: jsonDataObject
})
.then(resp => resp.json())
.then(data => {
if (data.error) {
commit('MESSAGE_RESPONSE', data.error);
// promise to resolve to false
return false;
} else {
commit('RESET_LEAD_RESPONSE');
// promise to resolve to true
return true;
}
});
// return promise
return response
},
// change to async
async createLeadObject() {
const dataLeadObject = {
date: new Date(),
fullName: this.lead.name,
email: this.lead.email,
phone: this.lead.phone,
comment: this.lead.comment
};
const response = await this.$store.dispatch('sendLeadResponse', dataLeadObject);
// if response is 'true', show modal
if (response) {
this.$refs['modalSuccess'].show();
}
}
I have following Table / Array:
If I press the blue button, then all items with the same group as the record should change the Status (Gratis).
But now it just change the Value of the Record and all items above it. As an example, if I press the Button on Record No. 1 then itselft and all above (No. 0) get an change of the Status (Gratis).
Following code im using to go through the array and change the Status:
private _updateFreeStatus = (record: QuestionModel): void => {
fetch('api/Test/UpdateGratisStatus', {
headers: { 'Content-Type': 'application/json' },
method: 'PUT',
body: JSON.stringify({
'group': record.group,
'free': record.free,
})
});
this.state.question.map(item => {
if (item.group === record.group)
{
item.free = !record.free;
}
});
}
do not mutate the state
create a copy, and use setState
Use
const updatedQuestions = this.state.question.map(item => {
if (item.group === record.group) {
return {
...item,
free: !record.free
}
}
return item;
});
this.setState({question: updatedQuestions});
I have this in my javascript:
<script>
var stripe = Stripe('pk_test_51Gv0ngD3zt5RrIg0XQiKHaK7TOAqzju9yps8jJB2Gch6ksmG4FSnqgyWLv3Qld2EkNHgAb30PLKduYGBuYtZe71A0066dp27DB');
var elements = stripe.elements();
// Custom styling can be passed to options when creating an Element.
var style = {
base: {
// Add your base input styles here. For example:
fontSize: '16px',
color: '#32325d',
},
};
// Create an instance of the card Element.
var card = elements.create('card', {
hidePostalCode: true, style: style });
// Add an instance of the card Element into the `card-element` <div>.
card.mount('#card-element');
var form = document.getElementById('payment-form');
form.addEventListener('submit', function (event) {
// We don't want to let default form submission happen here,
// which would refresh the page.
event.preventDefault();
stripe.createPaymentMethod({
type: 'card',
card: card,
billing_details: {
// Include any additional collected billing details.
name: 'Jenny Rosen',
},
}).then(stripePaymentMethodHandler);
});
function stripePaymentMethodHandler(result) {
if (result.error) {
// Show error in payment form
} else {
$.ajax({
headers: { 'Content-Type': 'application/json' },
method: 'POST',
url: "/PayStripe",
data: JSON.stringify({
payment_method_id: result.paymentMethod.id,
}),
success: function (json) {
handleServerResponse(json);
}
});
}
}
function handleServerResponse(response) {
if (response.error) {
// Show error from server on payment form
} else if (response.requires_action) {
// Use Stripe.js to handle required card action
stripe.handleCardAction(
response.payment_intent_client_secret
).then(handleStripeJsResult);
} else {
// Show success message
}
}
function handleStripeJsResult(result) {
if (result.error) {
// Show error in payment form
} else {
// The card action has been handled
// The PaymentIntent can be confirmed again on the server
fetch('/pay', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ payment_intent_id: result.paymentIntent.id })
}).then(function (confirmResult) {
return confirmResult.json();
}).then(handleServerResponse);
}
}
</script>
This is my HomeController:
public ActionResult PayStripe(string payment_method_id)
{
StripeConfiguration.ApiKey = "sk_test_51Gv0ngD3zt5RrIg0KmTYo92QYmujb9Gp3dv8zz7fOJYjbLna3gRPOkHzZMSVMISHNgmPSrSncUtKL2DS86R4DEJI00mVv9GusU";
var paymentIntentService = new PaymentIntentService();
PaymentIntent paymentIntent = null;
try
{
if (payment_method_id != "") {
// Create the PaymentIntent
var createOptions = new PaymentIntentCreateOptions
{
PaymentMethod = payment_method_id,
Amount = 1099,
Currency = "gbp",
ConfirmationMethod = "manual",
Confirm = true,
};
paymentIntent = paymentIntentService.Create(createOptions);
}
if (payment_method_id != "")
{
var confirmOptions = new PaymentIntentConfirmOptions { };
paymentIntent = paymentIntentService.Confirm(
payment_method_id,
confirmOptions
); <-- ERROR HERE "No such payment_intent: pm_1Gyj0uD3zt5RrIg0lSfDPKOO"
}
}
catch (StripeException e)
{
return Json(new { error = e.StripeError.Message });
}
return generatePaymentResponse(paymentIntent);
}
ERROR HERE "No such payment_intent: pm_1Gyj0uD3zt5RrIg0lSfDPKOO"
Can any body see what i am missing here?
I created a Connected account and still get the same error.
Your code is calling the PaymentIntent Confirm API but you're passing a PaymentMethod id (pm_123) as the first argument instead of the PaymentIntent id pi_123 which is why you're getting that error. Instead, you need to make sure you pass the PaymentMethod id inside confirmOptions and the PaymentIntent id as the first argument.
Relatedly, your code is creating a PaymentIntent but also passing Confirm = true which means you are already confirming it. And right after you are trying to re-confirm it which does't really make sense. You should pass the PaymentMethod id when you are confirming it.
If you want to create and confirm a PaymentIntent in one call you would do this instead:
var options = new PaymentIntentCreateOptions
{
PaymentMethod = payment_method_id,
Amount = 1099,
Currency = "gbp",
ConfirmationMethod = "manual",
PaymentMethod = payment_method_id,
Confirm = true,
};
var paymentIntent = paymentIntentService.Create(options);
I have got a Vue Component which has a list of values, when you select these values this changed the selected array, which in tern is posted to an endpoint.
I have an issue if the user spam clicks these values, as an individual post is created for each change, I want it so that if the user selects another item then the currently pending post is cancelled, so then the new value is posted and updates the endpoint with both the selected items.
However i'm having an issue with aborting the current axios request, I have provided the code below. There are no errors, the request simply doesn't cancel.
export default {
props: {
endpoint: {
default: '',
type: String
},
parameters: {
default: null,
type: Object
}
},
data: () => ({
loaded: false,
selected: [],
save: [],
data: [],
cancel: undefined
}),
methods: {
update() {
const self = this;
let params = this.parameters;
params.data = this.selected;
this.$root.$emit('saving', {
id: this._uid,
saving: true
});
if (self.cancel !== undefined) {
console.log('cancel');
this.cancel();
}
window.axios.post(this.endpoint + '/save', params, {
cancelToken: new window.axios.CancelToken(function executor(c) {
self.cancel = c;
})
}).then(() => {
this.$nextTick(() => {
this.loaded = true;
this.$root.$emit('saving', {
id: this._uid,
saving: false
});
});
}).catch(function (thrown) {
if (window.axios.isCancel(thrown)) {
console.log('Request canceled', thrown.message);
}
});
}
}
}
I have got a global instance of Axios created on my Vue Application.
I am having issues setting a variable via ajax.
const store = new Vuex.Store({
state: {
conversationsList: []
},
mutations: {
conversationList(state, payload) {
state.conversationList = payload;
}
}
});
setInterval(function () {
axios.get('/conversation/get-conversations')
.then((response) => {
store.commit('conversationList', response.data);
});
}, 1000);
I cant understand why the state.conversationList = payload does not change the value?
Even replacing the ajax call with a simple array assignment such as
var testList = [
{id: 1, author: 'john', type: 'follower', lastMessage : 'hi'}
];
store.commit('conversationList', testList);
doesnt work