Elements only appear after I input something - javascript

For some reason, everything is being initialized properly when I load the page for the first time, except for the paymentID and Amount, which are being display only after I click on something or input anything in a text box.
This is my code which initializes my webpage.
created: function () {
// Initializing persons
AXIOS.get('/persons')
.then(response => {
this.persons = response.data;
this.persons.forEach(person => this.getRegistrations(person.name))
this.persons.forEach(person =>
person.eventsAttended.forEach(event => {
this.getPaymentofRegistrations(person.name, event.name)
}))
})
.catch(e => {this.errorPerson = e});
.
.
.
.
getRegistrations: function (personName) {
AXIOS.get('/events/person/'.concat(personName))
.then(response => {
if (!response.data || response.data.length <= 0) return;
let indexPart = this.persons.map(x => x.name).indexOf(personName);
this.persons[indexPart].eventsAttended = [];
response.data.forEach(event => {
this.persons[indexPart].eventsAttended.push(event);
});
})
.catch(e => {
e = e.response.data.message ? e.response.data.message : e;
console.log(e);
});
},
getPaymentofRegistrations: function (personName, eventName) {
AXIOS.get('/registrations?person='+personName+'&event='+eventName)
.then(response => {
if (!response.data || response.data.length <= 0) return;
let indexPart1 = this.persons.map(x => x.name).indexOf(personName);
let indexPart2 = this.persons[indexPart1].eventsAttended.map(x => x.name).indexOf(eventName);
this.persons[indexPart1].eventsAttended[indexPart2].paymentId = response.data.bitcoin.userID;
this.persons[indexPart1].eventsAttended[indexPart2].paymentAmount = response.data.bitcoin.amount;
})
.catch(e => {
console.log(e)
})
}
Images attached for a better understanding of the problem.
It only takes writing a letter in a text box (without even clicking on a reactive button) for the Payment and Amount info to appear:

This code is very complex and hard to understand but if I should make a bid Vue.set can help for you:
https://v2.vuejs.org/v2/guide/reactivity.html#For-Objects
or you can store eventsAttended collections in another data property, not as a nested object.

Related

How can I use Free Dictionary API to get the top definition of a word?

I've been trying to make a program that spits out the definitions of a word list for a project. I am using https://dictionaryapi.dev/. I've never worked with web apis before, so can I get some help with this.
I've tried
var data = $.getJSON("https://api.dictionaryapi.dev/api/v2/entries/en/hello")
then
document.getElementById('output').innerHTML = data.meanings[1].definition
but it doesn't work. It says it can't find what meanings is.
You could use flatMap to retrieve just the definitions from the response:
const DICTIONARY_API_BASE_URL =
'https://api.dictionaryapi.dev/api/v2/entries/en/';
const DEFINITIONS_DIV = document.getElementById('definitions');
const fetchWordDefinitions = async word => {
console.log(`Making request for definitions of ${word}...`);
const response = await fetch(DICTIONARY_API_BASE_URL + word);
const json = await response.json();
return json[0].meanings
.flatMap(m => m.definitions)
.flatMap(d => d.definition);
};
const getWordDefinitions = () => {
const word = document.getElementById('word').value;
if (word == null || word == '') {
return alert('Error: You must enter a word to fetch');
}
DEFINITIONS_DIV.innerHTML = '';
fetchWordDefinitions(word)
.then(defintions => {
defintions.forEach(d => {
DEFINITIONS_DIV.innerHTML += `<p>${d}</p>`;
});
})
.catch(_ => {
DEFINITIONS_DIV.innerHTML += `<p>Error: Could not retrive any defintions for ${word}.</p>`;
});
};
* {
font-family: sans-serif
}
<!DOCTYPE html>
<html>
<body>
<h1>Fetch the definitions for a word!</h1>
<input type="text" id="word" name="word">
<input type="button" value="Fetch" onClick="getWordDefinitions()">
<div id="definitions"></div>
</body>
</html>
What I usually do with cases like this is to make use of the console.log() function.
fetch('https://api.dictionaryapi.dev/api/v2/entries/en/english')
.then(response => {
return response.json();
})
.then(word => {
console.log(word);
})
You can use Chrome developer tools by pressing F12. A console window will open in your browser, here you can expand the JSON response request returned from console.log(word); this will allow you to view each of the child elements. This should give you a better idea of how the structure of the JSON is formatted. Once you understand the structure you can remove the console.log(word); and assign it to a variable
var singleWordDefinition = word[0].meanings[0].definitions[0].definition;
Example Code:
function returnDefinition() {
fetch('https://api.dictionaryapi.dev/api/v2/entries/en/hello')
.then(response => {
return response.json();
})
.then(word => {
var singleWordDefinition = word[0].meanings[0].definitions[0].definition;
console.log("SINGLE: " + singleWordDefinition);
const wordDefinitionArr = word[0].meanings;
wordDefinitionArr.forEach(wordDefinition => {
console.log("FROM ARRAY: " + wordDefinition.definitions[0].definition);
});
})
};
Console output

React Child Component Is Not Rerendering When Props Are Updated

My parent component takes input from a form and the state changes when the value goes out of focus via onBlur.
useEffect(() => {
let duplicate = false;
const findHierarchy = () => {
duplicationSearchParam
.filter(
(object, index) =>
index ===
duplicationSearchParam.findIndex(
(obj) => JSON.stringify(obj.name) === JSON.stringify(object.name)
)
)
.map((element) => {
DuplicateChecker(element.name).then((data) => {
if (data.status > 200) {
element.hierarchy = [];
} else {
element.hierarchy = data;
}
});
if (duplicate) {
} else {
duplicate = element?.hierarchy?.length !== 0;
}
});
return duplicate;
};
let dupe = findHierarchy();
if (dupe) {
setConfirmationProps({
retrievedData: formData,
duplicate: true,
responseHierarchy: [...duplicationSearchParam],
});
} else {
setConfirmationProps({
retrievedData: formData,
duplicate: false,
responseHierarchy: [],
});
}
}, [duplicationSearchParam]);
I have a child component also uses a useeffect hook to check for any state changes of the confirmationProps prop.
the issue is that the event gets triggered onblur, and if the user clicks on the next button. this function gets processes
const next = (data) => {
if (inProgress === true) {
return;
}
inProgress = true;
let countryLabels = [];
formData.addresses?.map((address) => {
fetch(`/api/ref/country/${address?.country}`)
.then((data) => {
countryLabels.push(data.label);
return countryLabels;
})
.then((countries) => {
let clean = MapCleanse(data, countries);
fetch("/api/v1/organization/cleanse", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(clean),
})
.then((data) => {
if (data.status > 200) {
console.log(data.message);
message.error(getErrorCode(data.message.toString()));
} else {
Promise.all([confirmationProps, duplicationSearchParam]).then(
(values) => {
console.log(values);
console.log(data);
setCleansed(data);
**setCurrent(current + 1);**
inProgress = false;
}
);
}
})
.catch((err) => {
console.log(err);
inProgress = false;
});
})
.catch((err) => {
console.log(err);
inProgress = false;
});
});
console.log(confirmationProps);
};
The important part in the above code snippet is the setCurrent(current + 1) as this is what directs our code to render the child component
in the child component, i have a use effect hook that is watching [props.duplicateData.responseHierarchy]
I do output the values of props.duplicateData.responsehierarchy to the console to see if the updated information gets passed to the child component and it does. the values are present.
I have a conditional render statement that looks like this
{cleansedTree?.length > 0 || treeDuplicate ? (...)}
so although the data is present and is processed and massaged in the child component. it still will not re render or display properly. unless the user goes back to the previous screen and proceeds to the next screen again... which forces a re-render of the child component.
I have boiled it down and am assuming that the conditional rendering of the HTML is to blame. Or maybe when the promise resolves and the state gets set for the confirmation props that the data somehow gets lost or the useefect doesn't pick it up.
I have tried the useefect dependency array to contain the props object itself and other properties that arent directly related
UPDATE: this is a code snippet of the processing that gets done in the childs useeffect
useEffect(() => {
console.log(props.duplicate);
console.log(props.duplicateData);
console.log(props.confirmationProps);
let newArray = props.duplicateData.filter((value) => value);
let duplicateCheck = newArray.map((checker) =>
checker?.hierarchy?.find((Qstring) =>
Qstring?.highlightedId?.includes(UUIDToString(props?.rawEdit?.id))
)
);
duplicateCheck = duplicateCheck.filter((value) => value);
console.log(newArray, "new array");
console.log(duplicateCheck, "duplicate check");
if (newArray?.length > 0 && duplicateCheck?.length === 0) {
let list = [];
newArray.map((dupeData) => {
if (dupeData !== []) {
let clean = dupeData.hierarchy?.filter(
(hierarchy) => !hierarchy.queryString
);
let queryParam = dupeData.hierarchy?.filter(
(hierarchy) => hierarchy.queryString
);
setSelectedKeys([queryParam?.[0]?.highlightedId]);
let treeNode = {};
if (clean?.length > 0) {
console.log("clean", clean);
Object.keys(clean).map(function (key) {
treeNode = buildDuplicate(clean[key]);
list.push(treeNode);
return list;
});
setCleansedTree([...list]);
setTreeDuplicate(true);
} else {
setTreeDuplicate(false);
}
}
});
}
}, [props.duplicateData.responseHierarchy]);
This is a decently complex bit of code to noodle through, but you did say that **setCurrent(current + 1);** is quite important. This pattern isn't effectively handling state the way you think it is...
setCurrent(prevCurrent => prevCurrent + 1)
if you did this
(count === 3)
setCount(count + 1) 4
setCount(count + 1) 4
setCount(count + 1) 4
You'd think you'd be manipulating count 3 times, but you wouldn't.
Not saying this is your answer, but this is a quick test to see if anything changes.
The issue with this problem was that the state was getting set before the promise was resolved. to solve this issue I added a promise.all function inside of my map and then proceeded to set the state.
What was confusing me was that in the console it was displaying the data as it should. but in fact, as I learned, the console isn't as reliable as you think. if someone runs into a similar issue make sure to console the object by getting the keys. this will return the true state of the object, and solve a lot of headache

get data from json file using javascript and show data out table

I tried to get the data from the json file with javascript but it doesn't output the data
here is my code:
fetch('https://raw.githubusercontent.com/trvodi/test/main/json1.json')
.then((res) => res.json())
.then((data) => {
var json = data;
var i;
var iLength = json.data.item.length;
for (i = 0; i < iLength; i++) {
alert(json.data.item[i].FromMember);
}
}).catch((err) => {
console.log(err)
})
please help me. thank you
If you'd add the following line:
console.log(json.data.item, json.data.item.length);
You'll see that json.data.item.length is undefined because json.data.item is an object.
I'd recommend using
for (let i in json.data.item) {
let item = json.data.item[i];
console.log(item.FromMember);
}
To loop over the objects as shown in this demo:
fetch('https://raw.githubusercontent.com/trvodi/test/main/json1.json')
.then((res) => res.json())
.then((data) => {
for (let i in data.data.item) {
let item = data.data.item[i];
console.log(item.FromMember);
}
})
.catch((err) => {
console.log(err)
})
For more info about why (and alternatives) I'd choose for (let i in json.data.item), please see the following question/answer:
How to loop through a plain JavaScript object with the objects as members?

Unable to save fetched data in Jquery

I'm working on my front-end, and I've arrived at a roadblock. I'm trying to fetch data from my back-end, and it is actually fetching the data. But only after everything else? I'll show you.
$(function(){
function GetURLId() {
var url = window.location.href;
var path = url.substring(url.lastIndexOf('/') + 1);
var id = path.substring(path.lastIndexOf('?id=') + 4, path.lastIndexOf("?id") + 5)
return id;
}
var url = 'https://localhost:5001/api/rental/byId/' + GetURLId();
fetch(url)
.then((resp) => resp.json())
.then(function(data) {
Object.keys(data).forEach(key => {
console.log(`${key}: ${data[key]}`);
})
});
});
So first I get which id I'm working with out of the URL. Then where the problem lays is the code under it. I'm able to fetch my data as it console.logs this:
id: 2
status: "Open"
damage: true
So the data does actually fetch from my back-end. But now, everytime I try to save the data it goes undefined. I've tried:
$(function(){
var rental = []; // Added an array
var url = 'https://localhost:5001/api/rental/byId/' + GetURLId();
fetch(url)
.then((resp) => resp.json())
.then(function(data) {
Object.keys(data).forEach(key => {
console.log(`${key}: ${data[key]}`);
rental.push(rental[key] = data[key]);
})
});
console.log(rental['id']); // Returns undefined
});
And:
var rental = []; // Added an array outside of the function
$(function(){
var url = 'https://localhost:5001/api/rental/byId/' + GetURLId();
fetch(url)
.then((resp) => resp.json())
.then(function(data) {
Object.keys(data).forEach(key => {
console.log(`${key}: ${data[key]}`);
rental.push(rental[key] = data[key]);
})
});
console.log(rental['id']); // Returns undefined
});
But! With the last one where the rental is outside of the function, I can actually call it in the console. And in the console it actually does return the value.
Inside Console:
> rental["id"]
< 2
Lastly I've tried to check the value of the key and value inside of the fetch, like this:
$(function(){
var url = 'https://localhost:5001/api/rental/byId/' + GetURLId();
fetch(url)
.then((resp) => resp.json())
.then(function(data) {
Object.keys(data).forEach(key => {
if(key == "status" && data[key] != "Reserved") {
console.log(`${key}: ${data[key]}`); // Returns damage: undefined 3 times
}
})
});
});
But this as well doesn't work. It returns damage: undefined 3 times in console.
So if anyone knows what is going on here it would be awesome!
Thanks alot in advance.
Fetch requests are asynchronous. This means that when you call fetch it might take a while to complete it, so JavaScript allows the rest of the code to continue without blocking. So logging anything to the console before your request has finished will obviously result in an empty array.
Also, Arrays are index-, not name based in JavaScript. However, because arrays are essentially objects it still works, but you should never do the following below.
var rental = [];
rental['id'] = 'foo';
console.log(rental['id']);
Instead use a plain object which is meant to be used that way.
var rental = {};
rental['id'] = 'foo';
console.log(rental['id']);
In your last example you seem to do everything just fine. Are you sure your fetched data does not have a value of undefined in its structure? It would help to see what the data looks like.
The answer: 2 errors in my code.
- First I didn't properly account for the asynchronous nature of the code.
- Second, when trying to fix it with another then block and executing my code in there. I didn't return a value in the proceeding then block, but the forEach instead.
fetch(url)
.then(resp => resp.json())
.then(data => {
var rentalStatus;
Object.keys(data).forEach(key => {
rental[key] = data[key];
if(key == "status") {
rentalStatus = data[key];
}
})
return rentalStatus;
})
.then(rentalStatus => {
console.log(rental["id"]); // This does return the id now!
if(rentalStatus == "Reserved") {
$("#assign-items").removeClass("d-none");
}
}).catch(error => {
console.log("Error:" + error);
});

what does "event =&gt" does in RxJS?

I came across this code below but I don't understand why we are doing event is equal and greater than and then console.log
I would really appreciate if someone explains it
const node = document.querySelector('input[type=text]');
const input$ = Rx.Observable.fromEvent(node, 'input');
input$.subscribe({
next: event => console.log(`You just typed ${event.target.value}!`),
error: err => console.log(`Oops... ${err}`),
complete: () => console.log(`Complete!`),
});
const input$ = Rx.Observable.fromEvent(node, 'input')
.map(event => event.target.value)
.filter(value => value.length >= 2)
.subscribe(value => {
// use the `value`
});
This looks like Javascript code that's been passed through an HTML sanitizer.
The original code using arrow functions should be as follows:
const node = document.querySelector('input[type=text]');
const input$ = Rx.Observable.fromEvent(node, 'input');
input$.subscribe({
next: event => console.log(`You just typed ${event.target.value}!`),
error: err => console.log(`Oops... ${err}`),
complete: () => console.log(`Complete!`),
});
const input$ = Rx.Observable.fromEvent(node, 'input')
.map(event => event.target.value)
.filter(value => value.length >= 2)
.subscribe(value => {
// use the `value`
});
This is invalid JavaScript. =&gt should be => and what you're seeing is simply ES6's arrow functions.
This is a display bug in the page you're seeing. It probably stems from the fact that < and > in HTML text should be transformed into < and > so as not to cause parse errors with the same characters when they serve as tag opening and closing (as in <div>).

Categories