pass an argument from axios to a method vue - javascript

I'm new to vue and I'm trying to make this work. I get some data from a XML, everything works, but I want to change which value I get from XML using a computed which gets a value from Store.
My computed is:
currentStep: {
set (val) {
this.$store.commit('setCurrentStep', val)
},
get () {
return this.$store.state.currentStep
}
}
With axios and xml2js I get all data with this Method:
getData() {
axios.get("https://something.xml").then((response) => {
this.parseXML(response.data).then((data) => {
this.flightInformations = data
})
})
},
parseXML(data) {
return new Promise((resolve) => {
let parser = new xml2js.Parser({
trim: true,
explicitArray: true,
});
parser.parseString(data, function (err, result) {
let obj = null
obj = result.flugplan.abflug[0].flug;
let flight_dates = {};
for (let item of obj) {
let flight_date = item.datum.join().toString();
if (!flight_dates[flight_date]) {
flight_dates[flight_date] = [];
}
flight_dates[flight_date].push({
flightNr: item.flugnr.join().toString(),
flightPlace: item.ort.join().toString(),
flightPlan: item.plan.join().toString(),
flightExpected: item.erwartet.join().toString(),
flightDate: item.datum.join().toString(),
})
}
resolve(flight_dates);
})
})
}
I need to change my OBJ using my computed like:
let obj = null
if (this.currentStep === 'departures') {
obj = result.flugplan.abflug[0].flug;
} else {
obj = result.flugplan.ankunft[0].flug;
}
But it does not work. Can you guys please help ?
Thank you very much.

Computed can only return some value instead of modifying anything.
Try this one:
computed: {
someData() {
return this.currentStep === 'departures' ? result.flugplan.abflug[0].flug : result.flugplan.ankunft[0].flug;
}
}
After that use a someData value:
const obj = this.someData

I get it finally and now works! here is the code, if someone have the same issue
getData() {
axios.get("something.xml").then((response) => {
this.parseXML(response.data).then((data) => {
this.flightInformations = data
})
.catch(err => {
console.log(`${err} data is not avaiable`)
})
})
},
parseXML(data) {
return new Promise((resolve) => {
let parser = new xml2js.Parser({
trim: true,
explicitArray: true,
});
parser.parseString(data, (err, result) => {
let obj = null
if (this.$store.state.currentStep === 'abflug') {
obj = result.flugplan.abflug[0].flug
} else {
obj = result.flugplan.ankunft[0].flug
}
let flight_dates = {};
for (let item of obj) {
let flight_date = item.datum.join().toString();
if (!flight_dates[flight_date]) {
flight_dates[flight_date] = [];
}
flight_dates[flight_date].push({
flightNr: item.flugnr.join().toString(),
flightPlace: item.ort.join().toString(),
flightPlan: item.plan.join().toString(),
flightExpected: item.erwartet.join().toString(),
flightDate: item.datum.join().toString()
})
}
resolve(flight_dates)
})
})
}
Now using Store, when I change my CurrentStep, it also changes which part of XML it reads.

Related

Trying to understand an object composition pattern which features a factory and a function based mixin technique

I'm trying to understand behavior of function based composition in JavaScript.
const Animal = (name) => {
let properties = { name };
return ({
get name() { return properties.name },
set name(newName) { properties.name = newName },
breathe: function() {console.log(`${this.name} breathes!`); }
})
}
const aquaticKind = (animal) => ({
swim: () => console.log(`${animal.name} swims`)
})
const walkingKind = (animal, noOfLegs) => {
const properties = { noOfLegs }
return ({
get noOfLegs() { return properties.noOfLegs },
set noOfLegs(n) { properties.noOfLegs = n; },
walk: () => console.log(`${animal.name} walks with ${properties.noOfLegs} legs`)
})
}
const egglayingKind = (animal) => ({
layEgg: () => console.log(`${animal.name} laid an egg`)
})
const Crocodile = (name) => {
const info = Animal(name);
return Object.assign(info,
walkingKind(info, 4),
aquaticKind(info),
egglayingKind(info)
);
}
const snooty = Crocodile('snooty');
snooty.breathe();
snooty.swim();
snooty.walk();
snooty.name = "coolie";
snooty.noOfLegs = 23 // I expected this to get update to 23
snooty.swim();
snooty.walk();
snooty.layEgg();
If you run the code above, you will see that noOfLegs never get updated, while name get updated. I can't seem to wrap my head around this. How do we make noOfLegs get updated too?
MDN Documentation for object.assign shows you how to copy "accessors"
Here's your code that works as expected - the completeAssign function is based entirely on the code in that link
const completeAssign = (target, ...sources) => {
sources.forEach(source => {
const descriptors = Object.keys(source).reduce((descriptors, key) => {
descriptors[key] = Object.getOwnPropertyDescriptor(source, key);
return descriptors;
}, {});
Object.getOwnPropertySymbols(source).forEach(sym => {
const descriptor = Object.getOwnPropertyDescriptor(source, sym);
if (descriptor.enumerable) {
descriptors[sym] = descriptor;
}
});
Object.defineProperties(target, descriptors);
});
return target;
};
const Animal = (name) => {
const properties = { name };
return ({
get name() { return properties.name },
set name(newName) { properties.name = newName },
breathe () { console.log(`${this.name} breathes!`); }
})
}
const aquaticKind = (animal) => ({
swim: () => console.log(`${animal.name} swims`)
});
const walkingKind = (animal, noOfLegs) => {
const properties = { noOfLegs };
return ({
get noOfLegs() { return properties.noOfLegs },
set noOfLegs(n) { properties.noOfLegs = n; },
walk: () => console.log(`${animal.name} walks with ${properties.noOfLegs} legs`)
})
}
const egglayingKind = (animal) => ({
layEgg: () => console.log(`${animal.name} laid an egg`)
})
const Crocodile = (name) => {
const info = Animal(name);
return completeAssign(info,
walkingKind(info, 4),
aquaticKind(info),
egglayingKind(info)
);
}
const snooty = Crocodile('snooty');
snooty.breathe();
snooty.swim();
snooty.walk();
snooty.name = "coolie";
snooty.noOfLegs = 23;
snooty.swim();
snooty.walk();
snooty.layEgg();

Trying to access state in oncompleted method

I have API query and getting the result and setting those in a state variable in Oncompleted method of API query, Now i am updating the same state variable in another api query "onCompleted method.
I am not able to access the result from state what i have set before in first api query and below is my code
Query 1:
const designHubQueryOnCompleted = designHubProject => {
if (designHubProject) {
const {
name,
spaceTypes
} = designHubProject;
updateState(draft => { // setting state here
draft.projectName = name;
draft.spaceTypes = (spaceTypes || []).map(po => {
const obj = getTargetObject(po);
return {
id: po.id,
name: obj.name,
category: obj.librarySpaceTypeCategory?.name,
description: obj.description,
warning: null // trying to modify this variable result in another query
};
});
});
}
};
const { projectDataLoading, projectDataError } = useProjectDataQuery(
projectNumber,
DESIGNHUB_PROJECT_SPACE_TYPES_MIN,
({ designHubProjects }) => designHubQueryOnCompleted(designHubProjects[0])
);
Query 2:
const {
// data: designhubProjectSpaceTypeWarnings,
loading: designhubProjectSpaceTypeWarningsLoading,
error: designhubProjectSpaceTypeWarningsError
} = useQuery(DESIGNHUB_PROJECT_LINKED_SPACETYPE_WARNINGS, {
variables: {
where: {
projectNumber: { eq: projectNumber }
}
},
onCompleted: data => {
const projectSpaceTypeWarnings = data.designHubProjectLinkedSpaceTypeWarnings[0];
const warnings = projectSpaceTypeWarnings.spaceTypeWarnings.reduce((acc, item) => {
const spaceTypeIdWithWarningState = {
spaceTypeId: item.spaceTypeProjectObjectId,
isInWarningState: item.isInWarningState
};
acc.push(spaceTypeIdWithWarningState);
return acc;
}, []);
console.log(state.spaceTypes); // trying to access the state here but getting empty array
if (state.spaceTypes.length > 0) {
const updatedSpaceTypes = state.spaceTypes;
updatedSpaceTypes.forEach(item => {
const spaceTypeWarning = { ...item };
spaceTypeWarning.warning = warnings?.filter(
w => w.spaceTypeId === spaceTypeWarning.id
).isInWarningState;
return spaceTypeWarning;
});
updateState(draft => {
draft.spaceTypes = updatedSpaceTypes;
});
}
}
});
Could any one please let me know where I am doing wrong with above code Or any other approach to modify the state, Many thanks in advance!!

Use async API call inside loop in computed property with vue-async-computed

I have a computed property inside a Vue component that looks like so:
allUsers() {
const vm = this;
const users = this.getAll.map((item) => {
let newUser = {};
if (typeof item !== 'object') {
newUser = {
id: vm.userModel.id,
userId: vm.userModel.userId,
data: null,
tenantData: null,
};
} else {
newUser = item;
}
return newUser;
});
return users;
},
I need to insert some additional data into each newUser object, but getting that data requires 1) looping through another set of data for each newUser item and 2) getting the data returned from an axios call to a REST API endpoint:
async delete({ device, personId }) {
return await super.perform(axios.delete(ServiceUrlProvider.gmiUrl()
.concat('/person/')
.concat(personId)
.concat('/device/')
.concat(device.deviceId)));
}
Ideally I would be able to do something like this:
allUsers() {
const vm = this;
const users = this.getAll.map((item) => {
let newUser = {};
if (typeof item !== 'object') {
newUser = {
id: vm.userModel.id,
userId: vm.userModel.userId,
data: null,
tenantData: null,
};
} else {
newUser = item;
}
this.tenantApps.forEach((app) => {
userDeviceService.fetchPersonAppDevice({
id: item.id,
appCode: app.code,
})
.then((resp) => {
// Code here to add returned value to newUser object.
});
});
return newUser;
});
return users;
},
but since it is bad practice to allow async actions in computed properties, I have to try something else. Based on what I found, I'm trying vue-async-computed, and I've moved my method to the separate asyncComputed object:
asyncComputed: {
allUsers() {
const vm = this;
const users = this.getAll.map((item) => {
let newUser = {};
if (typeof item !== 'object') {
newUser = {
id: vm.userModel.id,
userId: vm.userModel.userId,
data: null,
tenantData: null,
};
} else {
newUser = item;
}
this.tenantApps.forEach((app) => {
userDeviceService.fetchPersonAppDevice({
id: item.id,
appCode: app.code,
})
.then((resp) => {
if (Array.isArray(resp.data) && resp.data.length > 0) {
newUser.hasDevice = true;
} else {
newUser.hasDevice = false;
}
});
});
return newUser;
});
return users;
},
},
My problem is getting allUsers() to wait for the returned call to userDeviceService.fetchPersonAppDevice(), since as it is now, it finishes and returns without waiting. I can't just use await on the forEach loop. How do I need to implement that call so that I can add the returned data to my newUser object?
UPDATE: Per comment by Estus Flask below, I've modified my allUsers computed value like so:
asyncComputed: {
async allUsers() {
const vm = this;
const users = this.getAll.map((item) => {
let newUser = {};
if (typeof item !== 'object') {
newUser = {
id: vm.userModel.id,
userId: vm.userModel.userId,
data: null,
tenantData: null,
};
} else {
newUser = item;
}
const devicePromises = [];
this.tenantApps.forEach((app) => {
devicePromises.push(userDeviceService.fetchPersonAppDevice({
id: item.id,
appCode: app.code,
}));
});
const devices = await Promise.all(devicePromises);
return newUser;
});
return users;
},
},
However, I get an error on the await Promise.all(devicePromises); call saying that the await operator can only be used in an async function. I've changed allUsers to be asynchronous, so why the error?

how to get and display data from firebase realtime database?

I want to get data from the database. Then change them. And then display.
Please tell me how to solve this problem and why I can not do it.
Here is my code
let firebaseConfig = {...};
firebase.initializeApp(firebaseConfig);
let ref = firebase.database().ref('/data')
class DataTable {
constructor(parent) {
this.parent = parent;
}
buildTable(data) {
this.data = data;
const keys = Object.keys(data[0]);
console.log(keys)
let div = document.createElement('div');
let tab = document.createElement('table');
let tb = document.createElement('tbody');
const buildTableBody = () => {
for (let a of data) {
let tr = document.createElement('tr');
keys.forEach((key) => {
let td = document.createElement('td');
let tn = document.createTextNode(a[key])
td.appendChild(tn);
tr.appendChild(td);
});
tb.appendChild(tr);
}
tab.appendChild(tb);
div.appendChild(tab);
}
this.parent.appendChild(div);
buildTableBody()
}
}
const table = new DataTable(document.body);
table.buildTable(
ref.once("value").then((snap) => {
const data = snap.val()
data.map(i => {
let res = {
'#': Number(i.id),
'Name': i.name,
};
return Object.entries(res).reduce((memo, [key, value]) => {
if (value) {
return {
...memo,
[key]: value
}
} else {
return memo;
}
}, {})
})
}))
But it returns to me PromiseĀ {}proto: Promise[[PromiseStatus]]: "resolved"[[PromiseValue]]: undefined
The way you're trying to pass the data into buildTable doesn't work. If you put a breakpoint inside buildTable, you'll be able to see that.
The reason is that the data is loaded from Firebase asynchronously, and any code that needs the data has to be called from inside the once() callback. So you'll want to put the call to buildTable within that callback, like this:
ref.once("value").then((snap) => {
const data = snap.val()
let result = data.map(i => {
let res = {
'#': Number(i.id),
'Name': i.name,
};
return Object.entries(res).reduce((memo, [key, value]) => {
if (value) {
return {
...memo,
[key]: value
}
} else {
return memo;
}
}, {})
})
table.buildTable(result);
}))

Uncaught TypeError: Cannot set property 'key' of undefined

Chrome is throwing Uncaught TypeError: Cannot set property 'key' of undefined error, but I really can't figure out what is wrong with the code. I've tried console.log(item) and it is undefined. But using lodash and clone, I'm not sure how to set the value. Sorry for such a noob question, but it would be great if someone could explain to me what is going on, and I'll make sure to spend a lot of time to learn from this!
Below is my code...
class Actions {
initSession() {
return (dispatch) => {
Firebase.auth().onAuthStateChanged(function(result) {
var profile = null;
if (result) {
profile = {
id: result.uid,
name: result.providerData[0].displayName,
avatar: result.providerData[0].photoURL
}
}
dispatch(profile);
});
}
}
login() {
return (dispatch) => {
var provider = new Firebase.auth.FacebookAuthProvider();
Firebase.auth().signInWithPopup(provider).then(function(result) {
var user = result.user;
var profile = {
id: user.uid,
name: user.providerData[0].displayName,
avatar: user.providerData[0].photoURL
}
Firebase.database().ref('/users/'+user.uid).set(profile);
dispatch(profile);
}).catch(function(error) {
console.log('Failed!', error);
});
}
}
logout() {
return(dispatch) => {
Firebase.auth().signOut().then(function() {
// Sign-out successful.
dispatch(null);
}, function(error) {
// An error happened.
console.log(error);
});
}
}
getComments(productId) {
return (dispatch) => {
var commentRef = Firebase.database().ref('comments/'+productId);
commentRef.on('value', function(snapshot) {
var commentsValue = snapshot.val();
var comments = _(commentsValue).keys().map((commentKey) => {
var item = _.clone(commentsValue[commentKey]);
item.key = commentKey;
return item;
})
.value();
dispatch(comments);
});
}
}
getProducts() {
return(dispatch) => {
Firebase.database().ref('products').on('value', function(snapshot) {
var productsValue = snapshot.val();
var products = _(productsValue).keys().map((productKey) => {
var item = _.clone(productsValue[productKey]);
item.key = productKey;
return item;
})
.value();
console.log(item);
dispatch(products);
});
}
}
getProducts() {
return(dispatch) => {
Firebase.database().ref('products').on('value', function(snapshot) {
var productsValue = snapshot.val();
var products = _(productsValue).keys().map((productKey) => {
var item = _.clone(productsValue[productKey]);
item.key = productKey;
return item;
})
.value();
dispatch(products);
});
}
}
addProduct(product) {
return (dispatch) => {
Firebase.database().ref('products').push(product);
}
}
addVote(productId, userId) {
return (dispatch) => {
var voteRef = Firebase.database().ref('votes/'+productId+'/'+userId);
var upvoteRef = Firebase.database().ref('products/'+productId+'/upvote');
voteRef.on('value', function(snapshot) {
if(snapshot.val() == null) {
voteRef.set(true);
var vote = 0;
upvoteRef.on('value', function(snapshot) {
vote = snapshot.val();
});
upvoteRef.set(vote+1);
}
});
}
}
addComment(productId, comment) {
return (dispatch) => {
Firebase.database().ref('comments/'+productId).push(comment);
}
}
getComments(productId) {
return (dispatch) => {
var commentRef = Firebase.database().ref('comments/'+productId);
commentRef.on('value', function(snapshot) {
var commentsValue = snapshot.val();
var comments = _(commentsValue).keys().map((commentKey) => {
var item = _.clone(commentsValue[commentKey]);
item.key = commentKey;
return item;
})
.value();
dispatch(comments);
});
}
}
}
export default alt.createActions(Actions);
And here is the error that I'm getting...
Chrome Console Error:
Uncaught TypeError: Cannot set property 'key' of undefined:
Everything works fine with the data you provided, but I suppose sometimes data comes different and the item becomes undefined you can add a condition so that you can determine whether the data is undefined or not and set the 'key' only for defined items.
item = _.clone(productsValue[productKey]);
if(item) {
item.key = productKey;
}
return item;
You don't have productKey declared anywhere.
var productKey;

Categories

Resources