How to access Vue component data inside callback - vue.js

Im trying to integrate Paymentez (a payments processor) into my site. I get "success" or "failure" responses after doing a test transaction but cant change data in the Vue component (want to show a modal/dialog).
data: function() {
return {
success: false,
failure: false
}
},
created() {
this.paymentCheckout = new window._PAYMENTEZ.modal({
client_app_code: "***********", // Client Credentials
client_app_key: "***************", // Client Credentials
locale: "es", // User's preferred language (es, en, pt). English will be used by default.
env_mode: "stg", // `prod`, `stg`, `local` to change environment. Default is `stg`
onOpen: function () {
console.log("modal open");
},
onClose: function () {
console.log("modal closed");
},
onResponse: function (response) {
// The callback to invoke when the Checkout process is completed
/*
In Case of an error, this will be the response.
response = {
"error": {
"type": "Server Error",
"help": "Try Again Later",
"description": "Sorry, there was a problem loading Checkout."
}
}
When the User completes all the Flow in the Checkout, this will be the response.
response = {
"transaction":{
"status": "success", // success or failure
"id": "CB-81011", // transaction_id
"status_detail": 3 // for the status detail please refer to: https://paymentez.github.io/api-doc/#status-details
}
}*/
console.log(response);
document.getElementById("response").innerHTML = JSON.stringify(
response
);
},
});
/* what I want is something like:
if(response.transaction.status == "success") {
this.success = true
}
else if(response.transaction.status == "failure") {
this.failure = true
}
else if (response.error) {
// show error
}
*/
I've added the Paymentez library via CDN and initialized it in a created() hook.
this.success and this.failure remain false.
Cant access this inside the callback

To be able to access the outer this, your callbacks need to be arrow functions. Example:
// ...
onResponse: response => {
this.success = true; // <= works! (changes your component's reactive prop).
console.log('console is your friend', this);
console.log(response);
}
//...
If they're normal functions they overwrite the outer this with their own scope (and that's what this points to inside them). Read more here.

Related

Json structure changes once I close the app

I'm having a weird, issue, actually, I'm working with react-redux in a react-native app.
when the user logs in, everything goes smoothly in the user profile, but once I close the app and go back again, I'm getting a weird JSON format.
User reducer :
import AsyncStorage from '#react-native-async-storage/async-storage';
export function userReducer(
state = AsyncStorage.getItem('user') ? AsyncStorage.getItem('user') : null,
action,
) {
switch (action.type) {
case 'LOGIN':
return action.payload;
case 'LOGOUT':
return null;
case 'VERIFY':
return { ...state, verified: action.payload };
case 'USER_LIST_RESET':
return { users: [] };
default:
return state;
}
}
Login Form:
const submitForm = async () => {
if (isValidForm()) {
try {
const { data } = await axios.post(
'https://c36a-196-235-44-112.eu.ngrok.io/login',
{
email,
password,
},
);
dispatch({ type: 'LOGIN', payload: data });
AsyncStorage.setItem('user', JSON.stringify(data));
console.log('Logged In');
navigation.navigate('home');
} catch (error) {
console.log(error.message);
}
}
};
Getting the user in the userProfile :
const { user } = useSelector(state => ({ ...state }));
console.log(user)
The first Data I get once I login :
{"first_name": "John", "id": "63b0a010c015dd4b1f5fdb2c", "last_name": "Doe", "message": "Register Success ! please activate your email to start", "picture": "pic.png", "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjYzYjBhMDEwYzAxNWRkNGIxZjVmZGIyYyIsImlhdCI6MTY3Mjk1MjU3NCwiZXhwIjoxNjczNTU3Mzc0fQ.XI9JnC4eeOQb5YJkNCC-Bqw4F9gpA1Xm6k_qJdkaXuw", "username": "JohnDoe", "verified": false}
The second data I get once I close and re open the app :
{"_A": null, "_x": 0, "_y": 1, "_z": "{\"id\":\"63b0a010c015dd4b1f5fdb2c\",\"username\":\"JohnDoe\",\"picture\":\"pic.png\",\"first_name\":\"John\",\"last_name\":\"Doe\",\"token\":\"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjYzYjBhMDEwYzAxNWRkNGIxZjVmZGIyYyIsImlhdCI6MTY3Mjk1MTY3NiwiZXhwIjoxNjczNTU2NDc2fQ.lVLg3pjfTFGt1K63v76sucinIUZJgOxSujSox12Xy0s\",\"verified\":false,\"message\":\"Register Success ! please activate your email to start\"}"}
I was trying to get the same data if I close the app, but I'm not, I'm actually getting another JSON form that is not compatible with the logic I'm working with.
AsyncStorage.getItem() returns a Promise, it is an asynchronous function:
https://reactnative.dev/docs/asyncstorage#getitem
So when retrieving an item you will either need to use async/await syntax to wait for the promise to resolve before you can do something with the retrieved item, or you will need to specify a callback function when calling AsyncStorage.getItem() in which you do something with the retrieved item.

How Do I Update A Database Column In Shopware Via The Administration

I have created an administration page in the Administration and I want to update information in the database when the page is loaded (in Vue js term CREATED). My code below does not do anything and I can not find any error. Help fix my code and how do I get errors from Shopware Administration.
const { Component, Mixin } = Shopware;
import template from './store-settings-page.html.twig'
Component.register('store-settings-page', {
template,
inject: [
'repositoryFactory'
],
metaInfo() {
return {
title: this.$createTitle()
};
},
data: function () {
return {
entity: undefined,
entityId: '4e2891496c4e4587a3a7efe587fc8c80',
}
},
computed: {
storeKeysRepository() {
return this.repositoryFactory.create('store_keys');
},
},
created() {
this.storeKeysRepository
.get(this.entityId, Shopware.Context.api)
.then(entity => {
this.entity = entity;
});
/* const repository = this.storeKeysRepository();
this.entity = repository.create(Shopware.Context.api);
this.entity.name = 'Diekedie';
repository.save(this.entity, Shopware.Context.api);
*/
// a function which is called over the ui
this.entity.name = 'updated';
// sends the request immediately
this.storeKeysRepository
.save(this.entity, Shopware.Context.api)
.then(() => {
// the entity is stateless, the data has be fetched from the server, if required
this.storeKeysRepository
.get(this.entityId, Shopware.Context.api)
.then(entity => {
this.entity = entity;
});
});
},
});
Looks like you're not awaiting the fetch request meaning your entity would still be undefined when it reaches the save call on the repository.
You should move the save call inside the chained method of the first request. Also unless you have some fields which are indexed or computed server side, you might not need to refetch the entity after the successful save call.
this.storeKeysRepository.get(this.entityId, Shopware.Context.api).then((entity) => {
this.entity = entity;
this.entity.name = 'updated';
this.storeKeysRepository.save(this.entity, Shopware.Context.api);
});

Multiple commits in vuex action not triggering mutation

I'm attempting to set a loading status on a component which will display a loading graphic while the request is being processed. I have this working with a call to an API, returning a promise from a fetch to a REST interface. However, when attempting this with a simple call to a service it only seems to call the last mutation
In the vuex store:
var initialState = {
status: { loading: false },
all_clients: [],
current_client: {
loaded: false,
}
}
export const fund = {
namespaced: true,
state: initialState,
actions: {
getClientOverview({ commit }, client_group_id) {
commit('loadingRequest');
clientService.getClientOverview(client_group_id)
.then(
clientInfo => {
commit('loadingSuccess')
},
error => {
commit('loadingError', error);
}
)
}
},
mutations: {
// Mutations to set loading and error statuses
loadingRequest(state) {
state.status = { loading: true };
},
loadingSuccess(state) {
state.status = { loading: false };
},
loadingError(state,error) {
state.status = { loading: false };
store.dispatch('alert/error', "Error Loading Client: " + error)
},
}
and in the corresponding client service that is called:
function getClientOverview(client_group_id) {
return new Promise((resolve,reject) => {
try {
// Note here that client.state.all_clients is an array of objects already set in the store
let clientDetail = client.state.all_clients.filter(function(item) {
return item.client_group_id === client_group_id;
});
// THIS PAUSE CODE JUST ADDED TO SLOW THINGS DOWN A BIT ON FRONT END
// SO I CAN SEE IF MUTATIONS ARE WORKING CORRECTLY
var d = new Date();
var d2 = null;
do { d2 = new Date(); }
while(d2-d < 2000);
// TO HERE
if(clientDetail.length == 0){
reject("Client Information not found")
}
resolve(clientDetail[0])
}catch(error){
reject(error)
}
})
}
A client is being returned as expected, as a resolved promise, but I only see 'loading' being set to false on the front end, it doesn't set to true while the service is running its process.
If I remove the commit('loadingSuccess') line then I can see the original commit being called as expected and loading being set to true - it seems as though only one commit is being called per action
Any help with this would be gratefully appreciated!
Thanks

VueJS data doesnt change on URL change

My problem is that when I go from one user page to another user page the info in component still remains from first user. So if I go from /user/username1 to /user/username2 info remains from username1. How can I fix this ? This is my code:
UserProfile.vue
mounted() {
this.$store.dispatch('getUserProfile').then(data => {
if(data.success = true) {
this.username = data.user.username;
this.positive = data.user.positiverep;
this.negative = data.user.negativerep;
this.createdAt = data.user.createdAt;
this.lastLogin = data.user.lastLogin;
data.invites.forEach(element => {
this.invites.push(element);
});
}
});
},
And this is from actions.js file to get user:
const getUserProfile = async ({
commit
}) => {
try {
const response = await API.get('/user/' + router.currentRoute.params.username);
if (response.status === 200 && response.data.user) {
const data = {
success: true,
user: response.data.user,
invites: response.data.invites
}
return data;
} else {
return console.log('Something went wrong.');
}
} catch (error) {
console.log(error);
}
};
Should I add watch maybe instead of mounted to keep track of username change in url ?
You can use watch with the immediate property, you can then remove the code in mounted as the watch handler will be called instead.
watch: {
'$route.params.username': {
handler: function() {
this.$store.dispatch('getUserProfile').then(data => {
if(data.success = true) {
this.username = data.user.username;
this.positive = data.user.positiverep;
this.negative = data.user.negativerep;
this.createdAt = data.user.createdAt;
this.lastLogin = data.user.lastLogin;
data.invites.forEach(element => {
this.invites.push(element);
});
}
});
},
deep: true,
immediate: true,
},
}
Your page is loaded before the data is retrieved it seems, you need put a "loading" property in the data and have a v-if="!loading" for your component then it will only render once the display is updated. Personally I would avoid watch if I can it is not great for performance of for fine grained handling.
Yes you should add wach on statement that contain user info.(you may have a problem to watch on object, so you can save user info in json, but im not sure). When user changing - call action, after recived response call mutation that should change a state, then watch this state.
And you might use better syntax to receive data from store. That is really bad idea call dispatch directly from your mouted hook, use vuex documentation to make your code better.

How could I create a function with a completion handler in React-native?

I am trying to use a completion handler in react-native is that possible?
pls some samples will help.
Thanks.
So i am calling this method in an instance class from a parent class, but want the method to return a value when done.
Right now its returns before the value is created but would rather like for the value to be passed once created.
getfcmToken() {
//generate token here
firebase.messaging().getToken().then(token => {
if (token) {
console.log("LOG: ", token);
_userID = token
alert(_userID)
} else {
// user doesn't have a device token yet
}
})
return this._userID;
}
I think you can just send a function as a parameter to getfcmToken. For example:
in helper/ instance class
getfcmToken(callback) {
firebase.messaging().getToken().then(token => {
if (token) {
this._userID = token;
callback({success: true, token: token};
} else {
// user doesn't have a device token yet
callback({success: false, message: 'User doesn't have device token'});
}
});
}
and then in parent class:
getUserToken() {
firebaseHelper.getfcmToken((result)=>{
if (success === true) {
//do something with token
}
});
}